Forum: Ruby on Rails has_many and class function

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Be1e3ee645d23c95ba650c21bc885927?d=identicon&s=25 Fabien Jakimowicz (Guest)
on 2007-08-02 11:47
(Received via mailing list)
Hello,

i have two models :

class Container <  ActiveRecord::Base
   has_many :bottles
end

class Bottle < ActiveRecord::Base
   belongs_to :container

   def self.find_all_from_container(container)
     container.bottles.find(:all)
   end
end

i was asking myself if there was a better way to write the function
find_all_from_container : i can call it from an instance of Container
but how to pass the container instance directly (ie without giving
the argument). To replace this :

@container = Container.find(id)
@bottles = Bottle.find_all_from_container(@container)

by something like this :

@container . Container.find(id)
@bottles = @container.bottles.find_all_from_container
243ddd626ce44f3025c3de8c1f76edc0?d=identicon&s=25 Lutz Horn (Guest)
on 2007-08-02 12:02
(Received via mailing list)
Hi,

2007/8/2, Fabien Jakimowicz <fabien@jakimowicz.com>:
> end
...
> To replace this :
>
> @container = Container.find(id)
> @bottles = Bottle.find_all_from_container(@container)
>
> by something like this :
>
> @container . Container.find(id)
> @bottles = @container.bottles.find_all_from_container

has_many gives you what you want for free.

@container.bottles

results in all bottles in the container. No need to call find.

Lutz
Be1e3ee645d23c95ba650c21bc885927?d=identicon&s=25 Fabien Jakimowicz (Guest)
on 2007-08-02 12:10
(Received via mailing list)
On Aug 2, 2007, at 12:02 PM, Lutz Horn wrote:

>>
>> by something like this :
>>
>> @container . Container.find(id)
>> @bottles = @container.bottles.find_all_from_container
>
> has_many gives you what you want for free.
>
> @container.bottles
>
> results in all bottles in the container. No need to call find.
>
I should have add more code in find_all_from_container function. The
idea is not to get every entries but to scope entries and perform
some actions on them, like :

def self.fill_empty(container)
   bottles = container.bottles.find(:all, :conditions => {:is_empty
=> true})
   bottles.each {|bottle| bottle.fill}
end
243ddd626ce44f3025c3de8c1f76edc0?d=identicon&s=25 Lutz Horn (Guest)
on 2007-08-02 12:13
(Received via mailing list)
Hi,

2007/8/2, Fabien Jakimowicz <fabien@jakimowicz.com>:
> I should have add more code in find_all_from_container function. The
> idea is not to get every entries but to scope entries and perform
> some actions on them, like :
>
> def self.fill_empty(container)
>    bottles = container.bottles.find(:all, :conditions => {:is_empty
> => true})
>    bottles.each {|bottle| bottle.fill}
> end

You can do this by using select:

container.bottles.select { |bottle| bottle.is_empty }

The block given to select must return true for every object to be
included in the resulting list.

Lutz
Be1e3ee645d23c95ba650c21bc885927?d=identicon&s=25 Fabien Jakimowicz (Guest)
on 2007-08-02 12:20
(Received via mailing list)
On Aug 2, 2007, at 12:13 PM, Lutz Horn wrote:

>> => true})
>>    bottles.each {|bottle| bottle.fill}
>> end
>
> You can do this by using select:
>
> container.bottles.select { |bottle| bottle.is_empty }
>
> The block given to select must return true for every object to be
> included in the resulting list.
>
Thanks for this help, but i just want to get the container instance
in class function to perform various things, regardless of any code
in it.
A05834e9b5954947eb0ba3b570c47d5e?d=identicon&s=25 Pratik Naik (pratik)
on 2007-08-02 12:23
(Received via mailing list)
It really helps if you can ask your question with exact code you're
using.

On 8/2/07, Fabien Jakimowicz <fabien@jakimowicz.com> wrote:
> >>
> >> @container = Container.find(id)
> >
> end
>
> >
>


--
Cheers!
- Pratik
http://m.onkey.org
Be1e3ee645d23c95ba650c21bc885927?d=identicon&s=25 Fabien Jakimowicz (Guest)
on 2007-08-02 12:29
(Received via mailing list)
On Aug 2, 2007, at 12:22 PM, Pratik wrote:

>
> It really helps if you can ask your question with exact code you're
> using.
>

actually, there is no code about this, i just want to know if it is
possible to get the instance without explicitly giving it in the call.

This is more by curiosity rather than a strict code question.
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2007-08-02 14:21
(Received via mailing list)
Hi --

On Thu, 2 Aug 2007, Fabien Jakimowicz wrote:

>
> This is more by curiosity rather than a strict code question.

The thing is, the instance is the class object when you call a class
method:

   class C
   end

   def C.greet
     puts "Hi from #{self}"
   end

   C.greet   # Hi from C

There's no instance of C involved; you're sending the message directly
to C.  A class is (by design) an entirely different object from its
instances (except for constants, which an instance method can refer
to from "below", and except for class variables, which are weird and
quasi-global).

It's possible to engineer things so that a class method can have
access of a sort to an instance via a block.  Here's an example (and
if you look at the source code for AR associations, which let you do
things like this, you'll see some much more highly-evolved examples):

   class A
     def self.c_method(&block)
       include Module.new { define_method("m", &block) }
     end
   end

   class B < A
     c_method { puts "Hi; I'm #{self}." }
   end

   B.new.m  # Hi; I'm #<B:0x1ea08c>.

It's not exactly what you want, but it might give you some ideas.


David

--
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
   RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
     & consulting:  Ruby Power and Light, LLC (http://www.rubypal.com)
This topic is locked and can not be replied to.