Rails:在属性上保存过滤条件并检查条件是否通过?

时间:2014-09-26 00:06:37

标签: sql ruby-on-rails ruby ruby-on-rails-4 filter

我有一个SaaS应用程序,其中一个帐户有很多用户。

在帐户中,帐户所有者可以为申请成为帐户一部分的用户指定某些过滤器。例如,他可以设置必须满足这些要求条件才能使用户被接受考虑:user.age> 21,user.name.count> 4。

我在考虑创建一个属于Account的FilterCondition模型,其中行可能看起来像account_id: 1, attribute: "age", condition_string: "> 21"account_id: 1, attribute: "phone_type", condition_string: "== iphone"

然后当我只想接受符合这些条件的用户时,请执行

之类的操作
  #User.rb
  def passes_requirements?
    account.filter_conditions.each do |filter_conditions|
      attr = filter_condition.attribute
      return false if self.attr != filter_condition.condition
    end 
    true
  end

我知道这是完全错误的语法,但它应该指出我想做的事情。

允许帐户保存需求条件的任何建议方法,然后检查用户是否符合这些要求?

1 个答案:

答案 0 :(得分:2)

如果将条件字符串分成比较器(例如>)和要比较的值,将会更容易:

class FilterCondition < ActiveRecord::Base
  belongs_to :account

  validates :attribute, presence: true
  validates :comparator, presence: true
  validates :value, presence: true

  def matching_users(query_chain = User.where(account: account))
    query_chain.where("#{attribute} #{safe_comparator} ?", value)
  end

  private
  def safe_comparator
    safe_values = ['=', '>', '>=', '<', '<='] # etc
    return comparator if safe_values.include? comparator
    ''
  end
end

safe_comparator方法降低了SQL注入查询的风险。链接过滤器的集合有点棘手,但是类似下面的想法应该有效。

class Account < ActiveRecord::Base
  #....
  has_many :filter_conditions
  def filtered_users
    query = User.where(account: self)
    filter_conditions.each do |filter_condition|
      query = filter_condition.matching_users(query)
    end
    query
  end

end


account = Account.first

filter_1 = FilterCondition.create(
  account: account,
  attribute: :age,
  comparator: '>=',
  value: 21
)
filter_2 = FilterCondition.create(
  account: account,
  attribute: :age,
  comparator: '<=',
  value: 99
)


account.filtered_users