Reputation: 750
I have a table with items, and a table with item characteristics. Corresponding models:
class Characteristic < ActiveRecord::Base
belongs_to :item
end
class Item < ActiveRecord::Base
has_many :characteristics
end
Each characteristic has it's name (i.e. 'price'), value, an a reference to an item. I need to select items by multiple characteristics, say, price = 100 and weight = 50. For this, i need to join tables twice, like this:
Item.joins('INNER JOIN characteristics c1 ON c1.item_id = items.id').
joins('INNER JOIN characteristics c2 ON c2.item_id = items.id').
where('c1' => {name: 'price', value: '100'},
'c2' => {name: 'weight', value: '50'})
and this is where the problem is. Characteristic's value is stored in database as string, and when i try to compare it to an integer, or range, I get a type conversion error. But when i don't use an alias for a table, there is no error. So, the code below works:
Item.joins('INNER JOIN "characteristics" ON "characteristics"."item_id" = "items"."id"').
where(characteristics: {characteristic_type_id: 223, value: 380})
But this one does not:
Item.joins('INNER JOIN "characteristics" c1 ON c1."item_id" = "items"."id"').
where(c1: {characteristic_type_id: 223, value: 380})
So how can I select items with, say, price in 50..100 and color 'brown'?
UPD: neither of above code works, actually. First one does not produce an SQL error, but it does the wrong thing. It just quotes the value so it becomes string. I.e.
where(c1: {value: 10..15})
becomes
WHERE ("c1"."value" BETWEEN '10' AND '15')
which is, obviously, not what I really want So I decided do add one more field to characteristics, value_f:decimal{8,2} to hold the numeric value of characteristic. I also added
after_validation do
self.value_f = value.to_f
end
to characteristic's model. So, when I want to compare a value to a number, I just use value_f instead.
Upvotes: 2
Views: 152
Reputation: 750
Found the solution: Postgresql. CREATE CAST 'character varying' to 'integer'
CREATE CAST (varchar AS integer) WITH INOUT AS IMPLICIT;
Still have to figure out how to execute this on Heroku, but that's a different question
Upvotes: 0
Reputation: 7405
Try this:
Item.joins(:characteristics).where(characteristics: [{name: 'price', value: '100'},{name: 'weight', value: '50'}] )
Upvotes: 1