在数组中构建 Active Record 条件 - 私有方法“scan”称为错误

发布于 2024-08-26 14:45:31 字数 759 浏览 8 评论 0原文

我正在尝试使用数组动态构建一组条件,如第一个答案中所建议的: 模型中的一个或多个参数使用 Ruby on Rails 查找条件。然而,我似乎做错了一些事情,我不确定我正在尝试的事情是否从根本上不合理,或者我只是搞砸了我的语法。

我在这里简化为一个条件来尝试说明问题,因为我尝试在对我正在处理的 5 种不同条件样式进行分层之前沿着这些思路构建一个简单的概念证明。

这有效:

excluded.push 12
excluded.push 30
@allsites = Site.all(:conditions => ["id not in (?)", excluded])

这会导致私有方法“扫描”,称为错误:

conditionsSet = []
excluded.push 12
excluded.push 30
conditionsSet << ["id not in (?)", excluded]
@allsites = Site.all(:conditions => conditionsSet)

感谢您的任何建议。我不确定将其作为我在顶部指出的相关问题/答案的后续项目是否正确。因为我有一个问题没有答案。如果有更好的方法来发布与现有帖子相关的内容,请告诉我。

I'm attempting to build a set of conditions dynamically using an array as suggested in the first answer here: One or more params in model find conditions with Ruby on Rails. However I seem to be doing something incorrectly and I'm not sure if what I'm trying is fundamentally unsound or if I'm simply botching my syntax.

I'm simplifying down to a single condition here to try to illustrate the issue as I've tried to built a simple Proof of concept along these lines before layering on the 5 different condition styles I'm contending with.

This works:

excluded.push 12
excluded.push 30
@allsites = Site.all(:conditions => ["id not in (?)", excluded])

This results in a private method 'scan' called error:

conditionsSet = []
excluded.push 12
excluded.push 30
conditionsSet << ["id not in (?)", excluded]
@allsites = Site.all(:conditions => conditionsSet)

Thanks for any advice. I wasn't sure if the proper thing was to put this as a followup item to the related question/answers I noted at the top. Since I've got a problem not an answer. If there is a better way to post this related to the existing post please let me know.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

┈┾☆殇 2024-09-02 14:45:31

试试这个:

Rails 2.3

class Site < ActiveRecord::Base

  def self.build_conditions(ids, name=nil, state=nil)
     cond = []
     cond << send(:sanitize_sql_array, ["id NOT IN (?)", ids]) unless ids.empty?
     cond << send(:sanitize_sql_array, ["name = ? ", name]) unless name
     cond << send(:sanitize_sql_array, ["state = ? ", state]) unless state
     cond.join(" and ")
  end    
end

现在在你的控制器中的某个地方:

Site.all(:conditions => Site.build_conditions([1,2])) 
Site.all(:conditions => Site.build_conditions(nil, "ABC"))

Rails 3

class Site < ActiveRecord::Base          
  def self.exclude_ids_by_name_and_state(ids, name=nil, state=nil)
    result = scoped
    result = result.where("id NOT IN (?)", ids) if ids.present?
    result = result.where(:name => name) if name.present?
    result = result.where(:state => state) if state.present?
    result
  end    
end

现在在你的控制器中的某个地方:

Site.exclude_ids_by_name_and_state([1,2])).all 
Site.exclude_ids_by_name_and_state(nil, "ABC").all

Try this:

Rails 2.3

class Site < ActiveRecord::Base

  def self.build_conditions(ids, name=nil, state=nil)
     cond = []
     cond << send(:sanitize_sql_array, ["id NOT IN (?)", ids]) unless ids.empty?
     cond << send(:sanitize_sql_array, ["name = ? ", name]) unless name
     cond << send(:sanitize_sql_array, ["state = ? ", state]) unless state
     cond.join(" and ")
  end    
end

Now somewhere in your controller:

Site.all(:conditions => Site.build_conditions([1,2])) 
Site.all(:conditions => Site.build_conditions(nil, "ABC"))

Rails 3

class Site < ActiveRecord::Base          
  def self.exclude_ids_by_name_and_state(ids, name=nil, state=nil)
    result = scoped
    result = result.where("id NOT IN (?)", ids) if ids.present?
    result = result.where(:name => name) if name.present?
    result = result.where(:state => state) if state.present?
    result
  end    
end

Now somewhere in your controller:

Site.exclude_ids_by_name_and_state([1,2])).all 
Site.exclude_ids_by_name_and_state(nil, "ABC").all
世界等同你 2024-09-02 14:45:31

您需要:

conditionsSet += ["id not in (?)", excepted]

而不是:

conditionsSet << ["id not in (?)", excepted]

+= 将两个数组添加在一起(将其视为将两个数组合并为一个数组),而 << 将新元素推入数组。因此,当使用 <<:conditions 时,您会得到: [["id not in (?)", excepted]]想要一个数组,其中第一个元素是字符串(而不是数组)。

You want:

conditionsSet += ["id not in (?)", excluded]

instead of:

conditionsSet << ["id not in (?)", excluded]

+= adds the two arrays together (think of it as merging the two into one array) while << pushes a new element onto the array. So you are getting: [["id not in (?)", excluded]] when using <<, and :conditions wants an array where this first element is a string (not an array).

终难遇 2024-09-02 14:45:31

尝试 SmartTuple,它是专门为此类情况设计的。

def self.build_conditions(options = {})
  [
    SmartTuple.new(" AND "),
    (["id NOT IN (?)", ids] if options[:ids].present?),
    ({:name => options[:name]} if options[:name].present?),
    ({:state => options[:state]} if options[:state].present?),
  ].sum.compile
end

...

Site.all(:conditions => Site.build_conditions(:ids => {1,2]))
Site.all(:conditions => Site.build_conditions(:name => "abc", :state => "disabled")

对我来说,最好使用 options 哈希而不是有序参数。随着项目的发展,可能会出现更多的情况,而您将不知道哪些情况会出现。哈希看起来和行为都更清晰,而且您可以轻松验证它以避免软件错误。

Try SmartTuple, it's designed specifically for cases like this.

def self.build_conditions(options = {})
  [
    SmartTuple.new(" AND "),
    (["id NOT IN (?)", ids] if options[:ids].present?),
    ({:name => options[:name]} if options[:name].present?),
    ({:state => options[:state]} if options[:state].present?),
  ].sum.compile
end

...

Site.all(:conditions => Site.build_conditions(:ids => {1,2]))
Site.all(:conditions => Site.build_conditions(:name => "abc", :state => "disabled")

To me it's also preferrable to use options hash instead of ordered arguments. As your project grows, more conditions may appear and you'll lose track of which comes which. Hash looks and behaves clearer plus you can easily validate it to avoid software errors.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文