Rails запрос со ссылочным атрибутом в where

#mysql #sql #ruby-on-rails #sqlite

#mysql #sql #ruby-on-rails #sqlite

Вопрос:

пример модели пользователей :

create_table "users"
t.string "name"
t.boolean "admin"
t.boolean "internal"
end

необходимо запрашивать с помощью «admin» или «internal» в предложении where SQL-запроса. На момент написания запроса неизвестно, какое логическое значение будет использоваться, поэтому переменная, скажем usertype , используется для хранения строки «admin» или «internal». Это в основном означает, что я хотел бы использовать ссылочный атрибут в моем предложении where.

Выполнение следующего запроса :

User.select("id").where("#{usertype} = 't'")

отлично работает в моей базе данных sqlite для разработки (поскольку sqlite хранит true как ‘t’, а false как ‘f’), но я предполагаю, что использование того же запроса в другой базе данных (например, Mysql или Postrgres) может не сработать.

В качестве альтернативы я попытался

User.select("id").where("#{usertype} = ?", true)

он также работает и не использует специфичный для sqlite ‘t’. Однако является ли это хорошим и независимым от базы данных решением?

Ответ №1:

Вы всегда должны использовать true или false (или переменные или код, который будет оценивать «истинность» или «ложность») и позволить rails обрабатывать преобразование в то, как ваша СУБД хранит логические значения.

Вы делаете это во втором примере

 User.select("id").where("#{usertype} = ?", true)
  

Итак, ответ: «да, это хорошее, независимое от базы данных решение». Но вы можете сделать это немного аккуратнее: если все ваши условия имеют вид «=», тогда вы можете использовать хэш, например

 {:foo => "bar"}
{"foo" => "bar"} 
  

которые оба эквивалентны

 ["foo = ?", "bar"]
  

Это означает, что в вашем случае вы можете отказаться от вычисления строки и просто передать свою переменную.

 User.select("id").where({usertype => true})
  

или, если вы хотите пропустить необязательный { amp; }

 User.select("id").where(usertype => true)
  

Редактировать: ответ на комментарий об использовании динамически определенного метода в вашем коде ruby для получения значения из объекта.

Вы можете использовать send метод для вызова соответствующего средства доступа к объекту. Например,

 @foo.bar == 123
  

эквивалентно

 @foo.send("bar") == 123
  

Итак, в вашем примере вы бы сказали

 a.send(usertype)
  

В качестве примечания, если вы хотите установить значение usertype (что, я думаю, не имело бы смысла в вашем случае, а просто иллюстрация), вам нужно будет вызвать «установочную» версию метода, которая будет либо admin= или internal= . Итак, в этом случае вам нужно будет использовать вычисление строки:

 @user.send("#{usertype}=", "foo")
  

это все равно, что сказать

 @user.admin = "foo"
  

или

 @user.internal = "foo"
  

Комментарии:

1. Спасибо за быстрый ответ. Я новичок в ruby и rails и все еще нахожусь в нижней части кривой обучения …. теперь, если бы я переместил проверку на истинность из предложения where в отдельный тест после нахождения записи, например a = User.find("id") , а затем .admin или.internal, как я мог бы использовать «usertype» переменная в этом случае ?