3

我正在使用 Ruby on Rails 3.2.2 并且正在试验 Squeel gem。我想知道(以某种方式,通过使用 Squeel gem 与否)是否可以在子句中scope“直接”“添加”与方法相关的 SQLwhere子句。也就是说,我有:

class Article < ActiveRecord::Base
  # Note: This is a scope method.
  def self.created_by(user)
    where(:user_id => user.id)
  end

  # I would like to use a scope method like the following.
  #
  # Note: Code in the following method doesn't work, but it should help
  # understanding what I mean.
  def self.scope_method_name(user)
    where{ created_by(user) | ... & ... }
  end
end

因此,当我运行时,Article.scope_method_name(@current_user).to_sql它应该返回如下内容:

SELECT articles.* FROM articles WHERE articles.user_id = 1 OR ... AND ...

尝试过 sifters,但那些(至少对我而言)是专门用于其他Squeel 语句的。也就是说,如果我声明一个 sifter,那么我不能使用它来限定ActiveRecords,因为该 sifter 返回一个Squeel::Nodes::Predicate对象而不是一个ActiveRecord::Relation.

4

2 回答 2

1

您必须下拉到更原始的 AREL 以进行 OR 操作

def self.scope_method_name(user)
  t = arel_table
  where(
    (t[:user_id].eq(user.id).or(
    t[:blah].eq('otherthing')
      ).and([:bleh].eq('thirdthing'))
    )
end

或类似的规定。

于 2012-06-26T12:03:07.403 回答
0

您可以像这样链接范围,Article.by_author(user).by_editor()但这会将所有条件与 AND 连接起来。因此,为了解决这个问题,您可以使用 Squeel 编写单个作用域(而不是链接它们),例如:

class Article < ActiveRecord::Base

  scope :by_author, ->(user) { where{author_id == user.id} }
  scope :by_editor, ->(user) { where{editor_id == user.id} }
  scope :by_title, ->(token) { where{title =~ "%#{token}%"} }
  scope :by_author_or_editor, ->(user) { where{(author_id == user.id)|(editor_id == user.id)} }
  scope :by_author_or_editor_and_title, ->(user, token) { where{((author_id == user.id)|(editor_id == user.id))&(title =~ "%#{token}%")} }
end

或者你可以使用筛子:

class Article < ActiveRecord::Base

  sifter :sift_author do |user|
    author_id == user.id
  end

  sifter :sift_editor do |user|
    editor_id == user.id
  end

  sift :sift_title do |token|
    title =~ "%#{token}%"
  end

  scope :by_author, ->(user) { where{sift :sift_author, user} }
  scope :by_editor, ->(user) { where{sift :sift_editor, user} }
  scope :by_title, ->(token) { where{sift :sift_title, token} }
  scope :by_author_or_editor, -> (user) { where{(sift :sift_author, user)|(sift :sift_editor, user)} }
  scope :by_author_or_editor_and_title, ->(user, token) { where{((sift :sift_author, user)|(sift :sift_editor, user))&(sift :sift_title, token)} }
end

这为您提供了返回 ActiveRecord::Relation 的范围,因此您理论上可以进一步链接它们。

于 2013-08-14T14:36:46.423 回答