How do you scope ActiveRecord associations in Rails 3?

后端 未结 6 1683
你的背包
你的背包 2021-01-30 01:21

I have a Rails 3 project. With Rails 3 came Arel and the ability to reuse one scope to build another. I am wondering if there is a way to use scopes when defining a relationsh

相关标签:
6条回答
  • 2021-01-30 02:00

    Instead of scopes I've just been defining class-methods, which has been working great

    def self.age0 do
      where("blah")
    end
    
    0 讨论(0)
  • How about association extensions?

    class Item < ActiveRecord::Base
      has_many :orders do
        def for_user(user_id)
          where(user_id: user_id)
        end
      end
    end
    
    Item.first.orders.for_user(current_user)
    

    UPDATE: I'd like to point out the advantage to association extensions as opposed to class methods or scopes is that you have access to the internals of the association proxy:

    proxy_association.owner returns the object that the association is a part of. proxy_association.reflection returns the reflection object that describes the association. proxy_association.target returns the associated object for belongs_to or has_one, or the collection of associated objects for has_many or has_and_belongs_to_many.

    More details here: http://guides.rubyonrails.org/association_basics.html#association-extensions

    0 讨论(0)
  • 2021-01-30 02:07

    I use something like:

    class Invoice < ActiveRecord::Base
      scope :aged_0,  lambda{ where("created_at IS NULL OR created_at < ?", Date.today + 30.days).joins(:owner) }
    end 
    
    0 讨论(0)
  • 2021-01-30 02:10

    If you're just trying to get the user's orders, why don't you just use the relationship?

    Presuming that the current user is accessible from the current_user method in your controller:

    @my_orders = current_user.orders
    

    This ensures only a user's specific orders will be shown. You can also do arbitrarily nested joins to get deeper resources by using joins

    current_user.orders.joins(:level1 => { :level2 => :level3 }).where('level3s.id' => X)
    
    0 讨论(0)
  • 2021-01-30 02:12

    You can use merge method in order to merge scopes from different models. For more details search for merge in this railscast

    0 讨论(0)
  • 2021-01-30 02:13

    I suggest you take a look at "Named scopes are dead"

    The author explains there how powerful Arel is :)

    I hope it'll help.

    EDIT #1 March 2014

    As some comments state, the difference is now a matter of personal taste.

    However, I still personally recommend to avoid exposing Arel's scope to an upper layer (being a controller or anything else that access the models directly), and doing so would require:

    1. Create a scope, and expose it thru a method in your model. That method would be the one you expose to the controller;
    2. If you never expose your models to your controllers (so you have some kind of service layer on top of them), then you're fine. The anti-corruption layer is your service and it can access your model's scope without worrying too much about how scopes are implemented.
    0 讨论(0)
提交回复
热议问题