使任何订单可链接

发布于 2024-10-18 04:06:56 字数 406 浏览 6 评论 0原文

我想根据一个复杂的标准对我的 Person 模型对象进行排序,该标准无法在单个查询中进行总结 - 因此在命名范围内。现在我使用一个类方法,例如:

def Person.very_complicated_sorting
  Person.all.sort { |x,y| x.bunch_of_calculations <=> y.bunch_of_calculations }
end

有没有办法使它可链接?例如

Person.tallest.very_complicate_sorting.youngest

,其中 tallestyoungest 是两个命名范围。

I want to sort my Person model objects based on a complicated criterion that can't be summarized in a single query - and so in a named scope. Right now I use a class method like:

def Person.very_complicated_sorting
  Person.all.sort { |x,y| x.bunch_of_calculations <=> y.bunch_of_calculations }
end

Is there a way to make this chainable? E.g.

Person.tallest.very_complicate_sorting.youngest

where tallest and youngest are two named scopes.

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

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

发布评论

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

评论(3

╰つ倒转 2024-10-25 04:06:56

不幸的是,这是不可能的。

命名作用域的工作方式是“惰性地”构建一组组合的 SQL 参数,直到您实际尝试使用它们执行某些操作时才会对这些参数进行评估。例如,以下命名范围链:

people = Person.tallest.youngest

不会导致任何数据库查询运行,它实际上会导致 ActiveRecord::NamedScope 对象存储在 >people 变量。仅当您访问或迭代该对象时,才会运行 SQL 并加载对象。

你的问题是你的排序方法不是用 SQL 表达的,而是一组 Ruby 条件。当 Rails 到达您的 sort_by 时,它必须去获取并实例化 Person 对象,以便它可以在它们上运行您的条件。完成后,您将拥有一个 Array 对象,而不再是 NamedScope 对象。

This isn't possible unfortunately.

The way named scopes work is by "lazily" building up a combined set of SQL parameters, which aren't evaluated until you actually try to do something with them. So for example the following chain of named scopes:

people = Person.tallest.youngest

will not cause any database query to be run, it actually causes an ActiveRecord::NamedScope object to be stored in the people variable. Only when you access or iterate through that object is the SQL run and the objects loaded.

Your problem is that your sorting method isn't being expressed in SQL, it's a set of Ruby conditions. When Rails gets to your sort_by it has to go and fetch and instantiate the Person objects so that it can run your condition on them. After it's done that you have an Array of objects and not a NamedScope object any more.

风苍溪 2024-10-25 04:06:56

您的 very_complicated_sorting 应该位于您的 Person 模型中。

您不能不在方法内写入 Person.all ,否则它无法链接。

只需保留:

def self.very_complicated_sorting
  sort_by { |x,y| x.bunch_of_calcultaions <=> y.bunch_of_calculations }
end

Your very_complicated_sorting should be in your Person model.

You musn't not write Person.all inside the method, it couldn't be chainable otherwise.

Just keep:

def self.very_complicated_sorting
  sort_by { |x,y| x.bunch_of_calcultaions <=> y.bunch_of_calculations }
end
混浊又暗下来 2024-10-25 04:06:56

如果您对数据库库使用 Sequel 而不是 ActiveRecord,这是可能的。它允许您使用 def_dataset_method 在模型上创建对 数据集 进行操作的方法(其中模型是包括);只要您的方法返回一个数据集,那么您就可以根据需要链接它们。例如:

class Person < Sequel::Model
  def_dataset_method :active_only do
    filter :active=>true
  end
  def_dataset_method :sort_much do
    order :name, :age.desc
  end
end

active_peeps = Person.active_only.sort_much
peeps_active = Person.sort_much.active_only

要留在数据集领域需要您仅使用可以表达为 SQL 的方法。您不能期望从数据库中请求某些记录,然后对它们执行复杂的仅​​ Ruby 逻辑(例如,根据在 Ruby 哈希中查找的 object_id 对它们进行排序),然后 /em> 继续对结果数组执行 SQL。 Ruby 不在您的数据库上运行(pl/Ruby 除外)。

或者,您可以直接使用 Ruby 数组,然后以任意顺序链接您喜欢的任何 Ruby 方法(如果它们都对数组进行操作并返回数组)。您必须在代码中明确决定何时从数据库获取结果,然后对数组进行操作。

This is possible if you use Sequel instead of ActiveRecord for your database library. It lets you use def_dataset_method on Models to create methods that operate on Datasets (of which Models are included); as long as your methods return a Dataset then you can chain them as you like. For example:

class Person < Sequel::Model
  def_dataset_method :active_only do
    filter :active=>true
  end
  def_dataset_method :sort_much do
    order :name, :age.desc
  end
end

active_peeps = Person.active_only.sort_much
peeps_active = Person.sort_much.active_only

To stay in Dataset land requires you to only use methods that can be expressed as SQL. You cannot expect to ask for some records from the database, then perform complex Ruby-only logic on them (say, sorting them by their object_id looked up in a Ruby Hash), and then continue to perform SQL on the resulting array. Ruby does not run on your database (other than pl/Ruby).

Alternatively, you can go straight to a Ruby array and then chain whatever Ruby methods you like in any order, if they all operate on arrays and return arrays. You must make a clear decision in your code as to when you are going to fetch the results from the Database and then operate on the array afterwards.

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