我有一个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
我知道这是完全错误的语法,但它应该指出我想做的事情。
允许帐户保存需求条件的任何建议方法,然后检查用户是否符合这些要求?
答案 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