как связать, где запрос в рельсах 3 активной записи - PullRequest
7 голосов
/ 02 апреля 2012

Мне нужно добавить условия в зависимости от данных параметров.

@users = User.where('id', params[:id]) unless params[:id].nil?
@users = User.where('email', params[:email]) unless params[:email].nil?
@users = User.limit(10)

Но по какой-то причине это не работает.Спасибо

Ответы [ 6 ]

23 голосов
/ 02 апреля 2012

Каждый из ваших операторов заменяет переменную @users, и, поскольку ActiveRecord оценивает каждую лениво, первые два никогда не вызываются.

Если вы хотите поддерживать три отдельных запроса и строить их таким образом, вы можете сделать:

@users = User.limit(10)
@users = @users.where('id', params[:id]) if params[:id]
@users = @users.where('email', params[:email]) if params[:email]

Это не самая красивая, но она будет работать. Тем не менее, я рекомендую оставить его для одного вызова метода и определить его в модели.

# In the model

def self.by_id_and_email(id, email)
  users = limit(10)
  users = users.where('id', id)       if id.present?
  users = users.where('email', email) if email.present?

  users
end

# In the controller / out of the model

User.by_id_and_email(params[:id], params[:email])

Таким образом, вы можете снова использовать метод, уточнить его и написать тесты скорости (ier) для него.

7 голосов
/ 09 ноября 2012

Вы можете добавить области к вашей модели, которые ничего не делают, если параметр не указан, например. (вызов с областью действия просто возвращает текущую область)

# in the model

def self.by_id(id)
    return scoped unless id.present?
  where(:id => id)
end

def self.by_email(email)
  return scoped unless email.present?
  where(:email => email)
end


# in the controller

User.by_id(params[:id]).by_email(params[:email])
3 голосов
/ 02 апреля 2012

Вы можете сделать это просто:

wheres = [:id, :email].map{|key| params.has_key?(key) ? {key => params[key]} : {} }\
                      .inject({}){|hash, injected| hash.merge!(injected)}
@users = User.where(wheres).limit(10)

Кроме того, вы всегда можете абстрагировать вышеупомянутое в область.

2 голосов
/ 02 апреля 2012

Это идеальный случай для прицелов.Посмотрите этот asciicast для более подробного урока: http://asciicasts.com/episodes/215-advanced-queries-in-rails-3

Используя области действия, вы можете хранить предложения where как отдельные элементы, которые вы можете использовать по отдельности, но также можете связывать их так же, как предложения where.1004 *

0 голосов
/ 14 апреля 2016

На самом деле лучше, если вы создаете Scopes, например, Это отличная статья, объясняющая это

в вашей модели

scope :by_id, -> id { where(id: id) if id.present? }
scope :by_email, -> email { where(email: email) if email.present? }

и в вашем методеможно звонить таким образом

def my_function()
    User.by_id(id).by_email(email)
end
0 голосов
/ 02 апреля 2012

Вы можете сделать это через что-то вроде ...

if params[:id].exists? && params[:email].exists?
  @users = User.where('id = ? AND email = ?', params[:id], params[:email]).limit(10)
elsif #if only one of id/email exists then...
  @users = User.where( #conditions for only one of id/email ).limit(10)
else
  #raise some errors
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...