Rollback of sql query in Rails 4 - sql

I have a table:
create_table "requests", force: :cascade do |t|
t.string "name"
t.string "address"
t.integer "client_id"
t.string "phone"
t.string "mobile"
t.text "social_media"
t.string "email"
t.integer "type"
t.text "subtype"
t.text "description"
t.string "priority"
t.integer "responsible"
t.integer "price"
t.boolean "payed", default: false
t.datetime "date"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
note, I have deleted all constraints, like not null etc.
and I have method:
def mark_payed
#request.update(payed: true)
redirect_to requests_path
end
so I want to update payed boolean attribute to true.
When i update request object with name defined like this one:(note: the name attribute is set)
2530;"ТОО ББ Нура";"---;--;-";;"---";"---";"";"";3;"";"---";"2";13;3000;FALSE;"";"2015-06-09 00:00:00";"2015-06-17 06:59:49.621709"
it works fine and my payed attribute is updated.
But in when i am updating this one: (note: the name attribute is empty ('').)
2532;"''";"''";89;"''";"''";"";"";3;"";"-";"2";2;1200;FALSE;"";"2015-06-09 00:00:00";"2015-06-16 11:18:54.296975"
I get a ROLLBACK.
HERE ARE THE LOGS FOR TWO CASES:
CASE 1:
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Request Load (0.4ms) SELECT "requests".* FROM "requests" WHERE "requests"."id" = $1 LIMIT 1 [["id", 2533]]
Request Load (0.4ms) SELECT "requests".* FROM "requests" WHERE "requests"."id" = $1 LIMIT 1 [["id", 2533]]
(0.4ms) BEGIN
(0.4ms) BEGIN
SQL (1.0ms) UPDATE "requests" SET "social_media" = $1, "subtype" = $2, "payed" = $3, "updated_at" = $4 WHERE "requests"."id" = $5 [["social_media", nil], ["subtype", nil], ["payed", "t"], ["updated_at", "2015-06-17 08:50:45.921870"], ["id", 2533]]
SQL (1.0ms) UPDATE "requests" SET "social_media" = $1, "subtype" = $2, "payed" = $3, "updated_at" = $4 WHERE "requests"."id" = $5 [["social_media", nil], ["subtype", nil], ["payed", "t"], ["updated_at", "2015-06-17 08:50:45.921870"], ["id", 2533]]
(8.7ms) COMMIT
(8.7ms) COMMIT
CASE 2:
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]]
Request Load (0.4ms) SELECT "requests".* FROM "requests" WHERE "requests"."id" = $1 LIMIT 1 [["id", 2532]]
Request Load (0.4ms) SELECT "requests".* FROM "requests" WHERE "requests"."id" = $1 LIMIT 1 [["id", 2532]]
(0.2ms) BEGIN
(0.2ms) BEGIN
(0.4ms) ROLLBACK
(0.4ms) ROLLBACK
So i get rollback in the update query. Also if it makes sense I have an before_update: update_attributes which finds_by client_id.
Notice, that client_id is null in first case, which works,
and is set in second case which doesn't. So I concluded that it is not due to before_update.
Also it is kind of strange to see logs doubled, but it is out of scope of my question for now.
EDIT: my before_update action (btw, i commented out before_update, the problem is same)
def update_attributes
#client = Client.find_by(client_id: self.client_id) if self.client_id.present?
if #client.present?
filled_cartridges.each do |d|
#r = FilledCartridge.find_by(request_id: d.id)
#cartridge = Cartridge.find_by(cartridge_name: d.cartridge_name)
if #cartridge.nil?
#cartridge = Cartridge.create!(cartridge_name: d.cartridge_name)
end
d.client_id = #client.id
d.cartridge_id = #cartridge.id
end
end
# update repair_cartridges attributes
end

Related

How to search-query ActiveRecord Associations (.joins) with SQL ILIKE

I am trying to query multiple Active Record-Models by passing query-params to a Controller. Within my tales_controller.rb I have the following index-method:
def index
#tales_count = Tale.all.count
if params[:search]
#tales = Tale.joins(:category)
.where('category.title ILIKE ?', "%#{params[:search]}%")
.where(
'title ILIKE :search OR
subtitle ILIKE :search OR
short_description ILIKE :search', search: "%#{params[:search]}%"
)
else
#tales = Tale.all
end
render template: 'tales/index'
end
Now, I can't seem to figure out the correct solution to this problem, as for the most part PG throws an error, saying: PG::AmbiguousColumn: ERROR: column reference "title" is ambiguous. I sense that this is due to the fact that I try to query the title-field on the Tale-, as well as on the Category-Model. However I am not able to fix this problem myself.
By providing the index-method with the right queries I expect to be able to query a couple fields on the Tale-Model (namely title, subtitle and short_description and potentially more), as well as the title-field on the Category-Model.
The Category-Model is referenced by the Tale-Model. This is what the schema.rb looks like:
create_table "tales", force: :cascade do |t|
t.string "public_id"
t.string "title"
t.string "subtitle"
t.string "player_count"
t.string "short_description"
t.datetime "published_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "category_id"
t.bigint "author_id"
t.index ["author_id"], name: "index_tales_on_author_id"
t.index ["category_id"], name: "index_tales_on_category_id"
end
EDIT: uhm, I just realized that by querying the way I currently do, I expect the category.title AND any of the other Tale-fields to carry the search-term. This is not want I intended, frankly.
Table name in Rails are by convention in the plural. So change this to read
.where('categories.title ILIKE ?', "%#{params[:search]}%")
and just for fun ILIKE in Postgres can be written as
.where('categories.title ~* ?', params[:search])

Uniqueness validation returning false non-uniqueness

Adding states to an empty database, where State validates :name, uniqueness: true.
Again, the DB is empty!
State.create(name:"Alabama")
(0.2ms) BEGIN
State Exists (0.6ms) SELECT 1 AS one FROM "states" WHERE "states"."name" = $1 LIMIT $2 [["name", "Alabama"], ["LIMIT", 1]]
(0.3ms) ROLLBACK
=> #<State:0x00007ffb711c3c60 id: nil, name: "Alabama", region_id: nil, created_at: nil, updated_at: nil>
State.all
State Load (0.5ms) SELECT "states".* FROM "states"
=> []
Why does it say this state exists when NO states exist???
When I get rid of the uniqueness validation, it's still acting funny:
State.all
State Load (0.7ms) SELECT "states".* FROM "states"
=> []

How to search my DB for specific m to n relations saved in a jointable

I am using a postgreSQL DB on my Rails app. I have established m-to-n relationships between Slots and Hashtags. The last thing I need is to find Slots who match specific Hashtags given per url params
Here is the schema.rb
create_table "hashtags", force: :cascade do |t|
t.string "value"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "hashtags_slots", id: false, force: :cascade do |t|
t.bigint "hashtag_id", null: false
t.bigint "slot_id", null: false
t.index ["hashtag_id"], name: "index_hashtags_slots_on_hashtag_id"
t.index ["slot_id"], name: "index_hashtags_slots_on_slot_id"
end
create_table "slots", force: :cascade do |t|
t.string "slot_name"
t.string "file_path"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["slot_name"], name: "index_slots_on_slot_name"
end
I want to show the Index of the slots filled with slots who have one of the hashtags that is given through the params[:hashtags]. The value of Hashtags can contain 1 or more Strings like so:
hashtags = "NetEnt PlayNGo Novomatic"
This is inside the index action of the Slot controller
if(params[:slot_name])
#slots = Slot.where(slot_name: params[:slot_name]).paginate(page: params[:page])
elsif(params[:hashtags])
#slots = slotsWithAtLeastOneOfThose(params[:hashtags])
else
#slots = Slot.all.paginate(page: params[:page])
end
How should a method
slotsWithAtLeastOneOfThose(hashtags)
slots = ...
return slots
end
look like to give me all the Slotsthat have at least one hashtag in the hashtags variable
Consider those relations:
Slot table:
id: 1 slot_name: Book of Dead
id: 2 slot_name: Big Win Cat
id: 3 slot_name: Big Bad Wolf
Hashtag table:
id: 1 value: PlayNGo
id: 2 value: Fun
id: 3 value: NetEnt
id: 4 value: MicroGaming
id: 5 value: NotFun
Hashtags_Slots table would look like this:
slot_id hashtag_id
1 1
1 2
2 2
2 3
2 5
3 4
3 5
And now the method
slotsWithAtLeastOneOfThose("PlayNGo NetEnt")
should give me all the Slots with the Hashtag PlayNGo and NetEnt
In this case
id: 1 slot_name: Book of Dead
id: 2 slot_name: Big Win Cat
Please check below query for getting slots with particular hash tag value
if(params[:slot_name])
#slots = Slot.where(slot_name: params[:slot_name]).paginate(page: params[:page])
elsif(params[:hashtags])
#slots = Slot.joins(:hashtags).where("hashtags.value LIKE ?", "%#{params[:hashtags]}%")
else
#slots = Slot.all.paginate(page: params[:page])
end

How can I call the id number of a supplier, that is in a link, call it from a controller

I have two tables, proveedors (suppliers) and productos (products).
Also I have a controller, in_stock_proveedors. In this view I show the list of all proveedors, all this proveedors has a link, where I call its id.
I would like know how can I call this id proveedors, from the link that I have in index (in_stock_proveedors), to proveedors controler.
This is my routes.rb file:
resources :productos
resources :proveedors
resources :in_stock_proveedors
devise_for :usuarios
get "/stock_proveedors", to: "proveedors#get_stock"
This is the link, that I have in_stock_proveedors, where from where I call
the id of the proveedor that I choose:
link_to "Ir al proveedor", stock_proveedors_path(:value =>{:id=>item['proveedors.id']})
This the method, in proveedors controller, where I want to receive the id number from the link, with the param p
def get_stock
#p = Proveedor.find(params[:id])
sql = 'SELECT productos.id as producto, productos.nombre as nombre
FROM productos
INNER JOIN proveedors ON productos.proveedor_id = proveedors.id
WHERE productos.proveedor_id = #p
GROUP BY productos.id'
#aux= ActiveRecord::Base.connection.execute(sql)
end
This is the index, of in_stock_proveedors
item['proveedors.id'])%>
This is the in_stock_proveedors controller
def index
sql3= "SELECT
proveedors.nombre as proveedor,
COUNT(productos.id) as distintos,
COUNT(CASE WHEN productos.stock > '0' THEN productos.id END) as instock,
proveedors.id
FROM proveedors
INNER JOIN productos ON proveedors.id = productos.proveedor_id
GROUP BY proveedors.id"
#aux3= ActiveRecord::Base.connection.execute(sql3)
end
This is the schema,for proveedors
create_table "proveedors", force: :cascade do |t|
t.string "nombre"
t.string "direccion"
t.string "email"
t.string "telefono"
t.string "rut"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "pais"
t.string "pagina_web"
t.integer "producto_id"
t.integer "orden_de_compra_id"
t.index ["orden_de_compra_id"], name: "index_proveedors_on_orden_de_compra_id"
t.index ["producto_id"], name: "index_proveedors_on_producto_id"
end
Assuming your controller action for the index page is something like
def index
sql = 'SELECT * FROM proveedors'
#proovedors = ActiveRecord::Base.connection.execute(sql)
end
loop through the #proovedors list in your index view file;
<% #proovedors.each do |proveedor| %>
<%= link_to "Ir al proveedor", stock_proveedors_path(:id => proveedor['id']) %>
<% end %>
Then, access params[:id] in your controller action
def get_stock
#p = Proveedor.find(params[:id])
...
end

Rails - how to select all records by ID range

I am trying to do a query for all cities (selecting only their name attribute) by their ID, and I want to be able to specify a range of ID's to select. My code is below:
def list_cities(start, stop)
cities = City.all(order: 'name ASC', id: start..stop, select: 'name')
cities.map { |city| "<li> #{city.name} </li>" }.join.html_safe
end
However, I get an error:
Unknown key: id
My implementation in my view is:
<%= list_cities(1,22) %>
This is a helper method to be put in all views, so I am not putting the logic in a particular controller.
My schema for this model is:
create_table "cities", :force => true do |t|
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "neighborhoods"
t.string "name"
t.integer "neighborhood_id"
end
When I ran the method in my console, I got:
City Load (0.9ms) SELECT name FROM "cities" WHERE ("cities"."id" BETWEEN 1 AND 3) ORDER BY name ASC
=> ""
I know it's not an issue of having an empty database since it worked with the following version of the method:
def list_cities(start, stop)
cities = City.all(order: 'name ASC', limit: stop - start, select: 'name')
cities.map { |city| "<li> #{city.name} </li>" }.join.html_safe
end
However, this method returns only the first 'n' records and not a range like I want.
When trying a simpler query in the console:
1.9.3p385 :009 > City.where(:id => 1..4)
City Load (0.9ms) SELECT "cities".* FROM "cities" WHERE ("cities"."id" BETWEEN 1 AND 4)
=> []
I figured out why it was happening...
I did City.all in my console and realized that my cities started with id "946" because I had seeded multiple times and the ID's were not what I thought they were! The solution offered was correct!
City.where(:id => start..stop).order('name ASC').select(:name)
You can turn your query to the following:
cities = City.all(order: 'name ASC', conditions: { id: start..stop }, select: 'name')
Speransky Danil's answer should work perfectly. you can try this too:
City.find((start..stop).to_a,:select=>:name,:order=>'name ASC')