Условия с переменными связывания и необязательными параметрами - PullRequest
2 голосов
/ 29 октября 2009

Допустим, у меня есть форма, где пользователи могут искать людей, чье имя начинается с определенной строки name, например, "Mi" найдет "Mike" и "Miguel". Я бы, вероятно, создал бы оператор find следующим образом:

find(:all, :conditions => ['name LIKE ?', "#{name}%"])

Допустим, форма также имеет два необязательных поля, hair_color и eye_color, которые можно использовать для дальнейшей фильтрации результатов. Игнорируя часть имени в запросе, оператор поиска для людей, которые могут принять произвольное количество необязательных параметров, может выглядеть так:

find(:all, :conditions => { params[:person] })

Который для моих двух дополнительных параметров будет вести себя как эквивалент этого:

find(:all, :conditions => { :hair_color => hair_color, :eye_color => eye_color })

Что я не могу понять, так это как объединить эти два вида запросов, где обязательное поле «имя» применяется к приведенному выше условию «нравится» и необязательные параметры hair_color и eye_color возможно, другие) могут быть добавлены для дальнейшей фильтрации результатов.

Я, конечно, могу создать строку запроса для этого, но я чувствую, что должен быть "путь рельсов", который был бы более элегантным. Как я могу объединить обязательные параметры связывания с необязательными параметрами?

Ответы [ 2 ]

4 голосов
/ 29 октября 2009

Это идеальное использование именованной области видимости.

создать именованную область в модели:

named_scope :with_name_like, lambda {|name|
  {:conditions => ['name LIKE ?', "#{name}%"]}
}

На данный момент вы можете позвонить

Model.with_name_like("Mi").find(:all, :conditions => params[:person])

И Rails объединит запросы для вас.

Редактировать: Код для Waseem:

Если имя является необязательным, вы можете опустить именованную область видимости в цепочке методов с условием if:

unless name.blank?
   Model.with_name_like("Mi").find(:all, :conditions => params[:person])
else
   Model.find(:all, :conditions => params[:person])
end

Или вы можете переопределить именованную область видимости, чтобы сделать то же самое.

named_scope :with_name_like, lambda {|name|
  if name.blank?
    {}
  else
    {:conditions => ['name LIKE ?', "#{name}%"]}
  end
}

Обновление

Вот версия последнего фрагмента кода для Rails 3:

scope :with_name_like, lambda {|name|
  if not name.blank?
    where('name LIKE ?', "#{name}%")
  end
}
0 голосов
/ 27 мая 2010

Чтобы выполнить также запрос Waseem, но разрешить nil вместо пробела? (что неправильно, если вы хотите использовать "@things = Thing.named_like (params [: name])" напрямую)

named_scope :named_like, lambda do |*args| 
  if (name=args.first)
    {:conditions => ["name like ?",name]}
  else
    {}
  end
end

# or oneliner version:

named_scope :named_like, lambda{|*args| (name=args.first ? {:conditions => ["name like ?",name]} : {}) } }

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...