创建默认范围以使参数下调的好方法是什么?

时间:2016-02-23 18:38:14

标签: ruby-on-rails activerecord

例如,假设您在保存之前始终保留用户电子邮件。

要查找,

User.find_by(email: params[:email].downcase)

但我不想每次发现时都要编写代码。

另外,我不想要不区分大小写的搜索。

而且,它应该是可组合的,并且可以在哪里工作。例如,

User.where(email: params[:email], status:'active')

1 个答案:

答案 0 :(得分:3)

您可以为此定义范围:

class User < ActiveRecord::Base
  scope :with_email, lambda { |email| where(email: email.downcase) }

并像这样使用它:

User.with_email(params[:email]).where(status: 'active')

最终你可以这样做:

# in User model
def self.normalized_search(search_attrs = {})
  searchable_attributes = [:username, :email, :first_name, :last_name]
  scope = self.scoped
  search_attrs.each do |attr, value|
    next unless searchable_attributes.include?(attr.to_sym)
    next if value.blank?

    scope = scope.where(attr.to_sym => value.to_s.downcase)
  end
  scope
end

然后你可以使用:

User.normalized_search({email: 'HeyHo@santa.com', username: 'Santa'})

此代码非常灵活:您可以轻松添加/删除属性以允许对其进行搜索,您可以轻松地替换链式where(在每个之间添加&#34; AND&#34;子句)到手动编写的SQL查询与&#34; OR&#34;等等。

如果您希望每次都使用默认范围(几乎),使用列的值,您可以使用default_scope

class User < ActiveRecord::Base
  default_scope { where(is_admin: false) }

然后调用User.where(something: some_variable)将排除User is_admin true的{​​{1}}条记录。要忽略默认范围,请使用User.unscoped.where(...)

有关default_scope的更多信息:http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html