#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» переменная в этом случае ?