Squeel и рельсы... динамический пункт
Используя Squeel, в приложении rails у меня есть хэш условий:
{'trans' => 'manual'}
который я в конечном итоге планирую переместить в массив... так что я также могу иметь назначение оператора.
[[field,operator,value][field,operator,value]]
Я хочу использовать метод Model, который на данный момент я опускаю оператор, и я просто пытаюсь ==, чтобы заставить это работать... однако то, что у меня есть ниже, не работает.
def self.with_conditions(conditions)
joins{car}.where do
conditions.map {|key,value| (key==value) }.inject(:&)
end
end
Я также попробовал это:
def self.with_conditions(conditions)
joins{car}.where do
query = nil
conditions.each do |key, value|
q = (key == value)
if query
query &= q
else
query = q
end
end
query
end
end
Итак, как мне заставить это работать с ==, и как мне в итоге заставить это работать и с динамическим оператором? Спасибо
В консоли мой SQL не читается ни в одном из моих условий... например:
в консоли:
> Timeslip.with_conditions({'car.year'=>'1991'})
SELECT "timeslips".* FROM "timeslips" INNER JOIN "cars" ON "cars"."id" = "timeslips"."car_id"
2 ответа
Вам необходимо программно построить запрос Squeel. Например:
def self.with_conditions(conditions)
conditions.map do |col, str|
Squeel::Nodes::Predicate.new(Squeel::Nodes::Stub.new(col), :matches, str) # (email.matches "user@example.com")
end.inject do |t, expr|
t & expr # joins each expression from the .map above with & - to be converted to AND in the sql
end.tap do |block|
return where{(block)} # pass the constructed expression to Squeel
end
end
На моем User::User
модель, которую я могу запустить
User::User.with_conditions({email: "user@example.com", first_name: "Deefour"}).to_sql
и я получу
SELECT "user_users".* FROM "user_users" WHERE (("user_users"."email" LIKE 'user@example.com' AND "user_users"."first_name" LIKE 'Deefour'))
Я не знаю, помогает ли это, но я сделал это с помощью этого вспомогательного метода:
def query_for_matches(key, value)
stub = Squeel::Nodes::Stub.new(key)
Squeel::Nodes::Predicate.new(stub, :matches, "%#{value}%")
end
У вас есть хеш параметров из запроса чего-то:
dynamic_params = {'username' => 'some_name', 'email' => 'email@example.com'}
Тогда я использую это с цепочкой where
в цикле:
query = SomeModel #could be User, etc
dynamic_params.each_pair {|key,value| query = query.where(query_for_matches(key, value)) }
Затем вы можете пройти query
на ваш взгляд или что-то в этом роде. Я был на рельсах всего пару недель, поэтому я не уверен, что это лучшая практика, но она работает.