为什么使用范围合并方法在 Rails 3.1 上不再起作用?

发布于 2024-12-08 02:44:58 字数 2072 浏览 4 评论 0原文

我偶然发现了一篇关于 Rails 3+ 范围的精彩文章: http://edgerails.info/articles/what-s-new-in-edge-rails/2010/02/23/the-skinny-on-scopes-forming-named-scope/index.html

您可以在那里(在“疯狂小镇”部分)读到,可以合并来自不同模型的范围,如下所示:

class User < ActiveRecord::Base

  scope :published, lambda {
    joins(:posts).group("users.id") & Post.published
  }
end

它按预期工作,并允许您执行以下操作:

User.published.to_sql
#=> SELECT users.* FROM "users"
#   INNER JOIN "posts" ON "posts"."author_id" = "users"."id"
#   WHERE (posts.published_at IS NOT NULL AND posts.published_at <= '2010-02-27 02:55:45.063181')
#   GROUP BY users.id

我在我的 Rails 3.1 项目中尝试了这种方法,但显然它不起作用不再了。

所以我克隆了这篇文章的 Rails 3.0.0-beta1 项目,亲眼看到这些人没有说谎,事情正在按照他们所说的方式进行。

然后我对其进行了 3.1 编辑,现在我得到:

ruby-1.9.2-p290 :003 > User.published.to_sql
  User Load (0.3ms)  SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."author_id" = "users"."id" GROUP BY users.id
  Post Load (0.2ms)  SELECT "posts".* FROM "posts" WHERE (posts.published_at IS NOT NULL AND posts.published_at <= '2011-10-05 11:45:00.512231')
  User Load (0.1ms)  SELECT "users".* FROM "users" 
NoMethodError: undefined method `to_sql' for []:Array
  from (irb):3
  from /home/jerefrer/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.1.0/lib/rails/commands/console.rb:45:in `start'
  from /home/jerefrer/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.1.0/lib/rails/commands/console.rb:8:in `start'
  from /home/jerefrer/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.1.0/lib/rails/commands.rb:40:in `<top (required)>'
  from script/rails:9:in `require'
  from script/rails:9:in `<main>'

==>不再起作用了。

这让我很伤心,因为范围合并非常棒,但现在我不能像我想要的那样干燥。

你知道:

  • 两个版本之间发生了什么吗?
  • 还有其他方法可以做到同样的事情吗?

I stumbled upon a wonderful article about scopes on Rails 3+ : http://edgerails.info/articles/what-s-new-in-edge-rails/2010/02/23/the-skinny-on-scopes-formerly-named-scope/index.html

You can read there (in 'Crazy Town' section) that it's possible to merge scopes from different models like this :

class User < ActiveRecord::Base

  scope :published, lambda {
    joins(:posts).group("users.id") & Post.published
  }
end

which works just as expected, and allows you to do :

User.published.to_sql
#=> SELECT users.* FROM "users"
#   INNER JOIN "posts" ON "posts"."author_id" = "users"."id"
#   WHERE (posts.published_at IS NOT NULL AND posts.published_at <= '2010-02-27 02:55:45.063181')
#   GROUP BY users.id

I tried this approach in my Rails 3.1 project and apparently it's not working anymore.

So I cloned the article's Rails 3.0.0-beta1 project, saw by my eyes that the guys are not lying and things are working the way they tell.

Then I 3.1'ed it up, and now I get :

ruby-1.9.2-p290 :003 > User.published.to_sql
  User Load (0.3ms)  SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."author_id" = "users"."id" GROUP BY users.id
  Post Load (0.2ms)  SELECT "posts".* FROM "posts" WHERE (posts.published_at IS NOT NULL AND posts.published_at <= '2011-10-05 11:45:00.512231')
  User Load (0.1ms)  SELECT "users".* FROM "users" 
NoMethodError: undefined method `to_sql' for []:Array
  from (irb):3
  from /home/jerefrer/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.1.0/lib/rails/commands/console.rb:45:in `start'
  from /home/jerefrer/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.1.0/lib/rails/commands/console.rb:8:in `start'
  from /home/jerefrer/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.1.0/lib/rails/commands.rb:40:in `<top (required)>'
  from script/rails:9:in `require'
  from script/rails:9:in `<main>'

==> Doesn't work anymore.

And that makes me sad, because scope merging was awesome and now I can't be as DRY as I want.

Do you know :

  • What happened between the two versions ?
  • Any other way to do the same ?

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

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

发布评论

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

评论(1

太阳男子 2024-12-15 02:44:58

& 方法看起来不再有效(太糟糕了,我发现语法很简洁)。您可以将其替换为 ActiveRecord::Relation#merge

class User < ActiveRecord::Base

  scope :published, lambda {
    joins(:posts).group("users.id").merge(Post.published)
  }
end

Edit

看起来它不会再回来了,在 Rails 3.0.10 中尝试它会给出弃用警告:

DEPRECATION WARNING: Using & to merge relations has been deprecated and will be removed in Rails 3.1. Please use the relation's merge method, instead.

这是反对它的提交,以防有人感兴趣:https://github.com/rails/rails/commit/66003f596452aba927312c4218dfc8d408166d54

The & method doesn't look like it works anymore (too bad, I found the syntax was neat). You can replace it with ActiveRecord::Relation#merge:

class User < ActiveRecord::Base

  scope :published, lambda {
    joins(:posts).group("users.id").merge(Post.published)
  }
end

Edit

And it looks like it won't be back, trying it in rails 3.0.10 gives a deprecation warning:

DEPRECATION WARNING: Using & to merge relations has been deprecated and will be removed in Rails 3.1. Please use the relation's merge method, instead.

Here's the commit deprecating it, in case someone's interested: https://github.com/rails/rails/commit/66003f596452aba927312c4218dfc8d408166d54

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