3

I have boxes and balls. Balls are in boxes. Ball can be either red and green.

class Box < ActiveRecord::Base
  has_many :balls
end

class Ball < ActiveRecord::Base
  belongs_to :box
  scope :green, where(:color => "green")
end

I want to set has_many only with green balls. I know that finder_sql method exists, but i don't know how to set via scopes.

I want that following examples to be equivalent:

@orders = @box.balls
@orders = @box.balls.green
petRUShka
  • 9,812
  • 12
  • 61
  • 95

4 Answers4

7

You can always use:

has_many :balls, :conditions => { :color => "green" }

It works in Rails3, but I am not sure if this syntax won't be deprecated due to some ActiveRecord::Relation equivalent. In the official documentation relased with Rails3 this syntax is still available, so I guess this stays out like it was in 2.3.x branch.

mdrozdziel
  • 5,528
  • 6
  • 39
  • 55
  • 2
    note that you would probably want to call the association :green_balls for clarity. – Eric Jan 16 '13 at 04:01
2

And in Rails 3, it's changed slightly:

class Item
  scope :red, where(:colour => 'red')
  scope :since, lambda {|time| where("created_at > ?", time) }
end

red_items = Item.red
available_red_items = red_items.where("quantity > ?", 0)
old_red_items = Item.red.since(10.days.ago)

Credit and more information

Jesse Wolgamott
  • 40,197
  • 4
  • 83
  • 109
  • I want to set scope only for has_many assotiation. I want to @box.balls to returns all balls with green color. And I want to Ball.all return all balls green and red. – petRUShka Jul 12 '10 at 17:02
  • Indeed. So you'd have on the Ball model, "scope :red, where(:coulour=>'red')" ... then, @box.balls.red – Jesse Wolgamott Jul 12 '10 at 17:53
  • :) I want to avoid use scope by hand. I want to set default scope for has_many, is it possible? – petRUShka Jul 12 '10 at 21:06
  • You need to set scope in the /app/models/ball.rb ------- after that, you'll say "Ball.red" to find all red balls. You can say "@box.balls.red".... If you want to just call "@box.red_balls" then create a "red_balls" method on Box that balls @box.balls.red" – Jesse Wolgamott Jul 12 '10 at 21:13
0

This is an old question, but I was just looking to do the same thing, and I came across this question while searching. I never found a solution, but I came up with something that works well.

For your example, you can do this:

class Box < ActiveRecord::Base
  has_many :balls do
    def self.extended(base)
      base.where_values += Ball.green.where_values
    end
  end
end

class Ball < ActiveRecord::Base
  belongs_to :box
  scope :green, where(:color => "green")
end

I'm not aware of the implications of doing this, but after some initial testing, it appears to work without issue. There are other values that can be set, like eager_load_values, join_values, order_values, etc.

Sean Hill
  • 14,978
  • 2
  • 50
  • 56
-1
default_scope :color, :conditions => { :color => "green"}

Use this

Sachin R
  • 11,606
  • 10
  • 35
  • 40
  • 2
    default_scope acts on whole model. But I need option that acts oonly on has_many association. I want to @box.balls to returns all balls with green color. And I want to Ball.all return all balls green and red. – petRUShka Jul 12 '10 at 17:03
  • 2
    DO NOT use this. Every time I have used `default_scope` I have regretted it. Be aware that there are [lots of potential foot-guns](http://pragdave.blogs.pragprog.com/pragdave/2012/03/be-careful-using-default_scope-and-order.html) related to this misfeature. – Adam Lassek May 15 '13 at 02:44