2011-10-05 7 views
11

natknąłem się wspaniały artykuł na temat zakresów na szynach 3+: http://edgerails.info/articles/what-s-new-in-edge-rails/2010/02/23/the-skinny-on-scopes-formerly-named-scope/index.htmlDlaczego używanie metody scalania z zakresami nie działa już w Rails 3.1?

Można tam przeczytać (w sekcji „Crazy Town”), że jest to możliwe do scalania zakresów z różnych modeli tak:

class User < ActiveRecord::Base 

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

który działa tak jak oczekiwano, i pozwala zrobić:

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 

próbowałem tego podejścia w moich Rails 3.1 projekt i najwyraźniej to nie działa już.

Więc sklonowałem artykuł dotyczący projektu Rails 3.0.0-beta1, widziałem oczami, że faceci nie kłamią i wszystko działa tak, jak mówią.

Potem 3.1'ed go, a teraz mam:

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>' 

==> już nie działa.

I to mnie zasmuca, ponieważ łączenie zakresów było niesamowite i teraz nie mogę być tak SUCHA, jak chcę.

Czy wiesz:

  • Co wydarzyło się między tymi dwoma wersjami?
  • W inny sposób zrobić to samo?

Odpowiedz

17

Metoda & nie wygląda już tak, jak działa (źle, znalazłem, że składnia była zgrabna). Można zastąpić go ActiveRecord::Relation#merge:

class User < ActiveRecord::Base 

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

Edit

I wygląda na to, że nie będzie z powrotem, próbując go w szynach 3.0.10 daje ostrzeżenie Deprecation:

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. 

Oto zatwierdzenie wycofania, na wypadek, gdyby ktoś był zainteresowany: https://github.com/rails/rails/commit/66003f596452aba927312c4218dfc8d408166d54

+1

Powrócił teraz do głównego oddziału: https://github.com /rails/rails/blob/24cc9e5b4f9b729f02d2e0b56265032d08933a41/activerecord/lib/active_record/relation/spawn_methods.rb#L7 – charlysisto

+1

@charlysisto ten plik nie zmienił się pomiędzy wersją 3.1.1 a wersją master, czy na pewno jest poprawny? –

+0

Masz rację, jakoś się pomyliłeś – charlysisto