Has_many :conditions =>

On 6 May 2008, at 15:52, James B. wrote:


has_one :active_client, :class_name => ‘Client’,
:conditions => '#{self.class.sanitize_sql_here([

These need to match. You’ve defined sql_sanitize_here but are using
sanitize_sql_here

Fred

Assuming that you’ve been consistent in the begin/end date column
names, you could/should create a module that you can include in the
models that need this functionality. It’d look something like this:

module ActivatedObject
def self.included(base)
base.extend ClassMethods
end

module ClassMethods
def sanitize_sql_here(array)
sanitize_sql array
end

def has_activated_object(class_name)
  self.has_one "active_#{class_name.to_s}",
               :class_name => class_name.to_s.classify,
               :conditions =>

‘#{self.class.sanitize_sql_here … }’
end

def has_activated_collection(collection_name)
  self.has_many "active_#{collection_name.to_s}",
               :class_name => collection_name.to_s.classify,
               :conditions =>

‘#{self.class.sanitize_sql_here … }’
end
end
end

With that in place you would:

class ClassWithActivatedAssociation < ARec::Base
include ActivatedObject
has_activated_object :client
has_activated_collection :payment_to_group_helpers # :slight_smile:


end

On May 6, 12:54 pm, James B. [email protected]

Sometimes, you just have to change tools:

@active = ‘( effective_from <= current_date
AND
( superseded_after IS NULL OR superseded_after >=
current_date ))’

has_one :buying_client, :class_name => ‘Client’,
:conditions => @active

“current_date”, being a standard SQL function evaluated on each call,
works perfectly for this situation.

Now the question is: Is there a place to put this so that all models can
use it without having to specifically include a module or redefine the
instance variable in each class?

James,

The pattern that I posted above is one that’s often used in ARec
‘acts’ extensions. You could go the plugin route with the code
(adding what’s necessary to create the instance variable).
Alternately you could keep it in lib and add

ActiveRecord::Base.send :include, ‘ActivatedObject’

at the end of the file to inject the has_active_xxx methods to
ActiveRecord. A

HTH,
AndyV

On May 6, 4:27 pm, James B. [email protected]

I take it that the module file in lib would need to be explicitly loaded
in config/enviorinment.rb or somewhere similar, correct?

On 7 May 2008, at 14:21, James B. wrote:

I take it that the module file in lib would need to be explicitly
loaded
in config/enviorinment.rb or somewhere similar, correct?
You’d probably do that in config/initializers these days

Fred

AndyV wrote:

James,

The pattern that I posted above is one that’s often used in ARec
‘acts’ extensions. You could go the plugin route with the code
(adding what’s necessary to create the instance variable).
Alternately you could keep it in lib and add

ActiveRecord::Base.send :include, ‘ActivatedObject’

at the end of the file to inject the has_active_xxx methods to
ActiveRecord. A

This helps very much. Thank you.

My thinking regarding implementation of this leans towards the AR::BASE
injection technique you outline above. It has the following attractions
for me:

  1. The code is kept in a readily identifiable file.
  2. The implementation details are invisible to coders working with the
    models; mainly, if not solely, me ;-).

What would you favour?

Hi –

On Wed, 7 May 2008, James B. wrote:

I take it that the module file in lib would need to be explicitly loaded
in config/enviorinment.rb or somewhere similar, correct?

It depends how it’s used. First of all, if you’re require’ing things
in environment.rb, they should probably be in config/initializers,
which is where (as of Rails 2.0) you put things that are one-time,
application-specific loads to be loaded when the server starts. If
your library doesn’t fall into that category, then lib is a likely
choice. If, however, it’s a non-ActiveRecord model, then app/models is
the place.

I know I’m generalizing past your case, but bear with me as it might
be helpful.

Rails has a mechanism for resolving unknown constants. If you refer
to, say, MyConstant, Rails will look in its load-path for a file
called my_constant.rb, and will load it. The assumption is that
MyConstant will be defined in my_constant.rb. If it isn’t, you get an
error message. (Likewise if my_constant.rb doesn’t exist, though a
different error message: unknown constant.)

If your constant is MyClass::MyConstant, Rails will look for
my_class/my_constant.rb somewhere in the load path.

All of this means that if you use this mechanism, naming your file
appropriately and letting Rails automatically load it the first time
you use the name of your class or module, you don’t have to load it
explicitly.

By the way, here’s a nice demo of the constant-resolving mechanism,
which Rails also uses for its own purposes. I have a model class
called Container, in models/container.rb.

$ ./script/console
Loading development environment (Rails 2.0.2)

Object.constants.grep(/Container/)
=> [] # No matching constants.
Container # I refer to Container;

                                    # this prompts Rails to
                                    # go load the model file
                                    # in an attempt to resolve
                                    # the constant, which succeeds.

=> Container(id: integer, name: string, created_at: datetime,
updated_at: datetime)

Object.constants.grep(/Container/) # And here it is.
=> [“Container”]

David


Rails training from David A. Black and Ruby Power and Light:
INTRO TO RAILS June 9-12 Berlin
ADVANCING WITH RAILS June 16-19 Berlin
INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!

David A. Black wrote:

I know I’m generalizing past your case, but bear with me as it might
be helpful.

Sad to say perhaps, but my ignorance is so vast I that I am grateful for
every snippet of information that I can fit into my existing
understanding. Your help is greatly appreciated.

I tried out something similar in console which, in its own way, is
equally illuminating.

$ ruby script/console
Loading development environment (Rails 2.0.2)

Application
LoadError: Expected ./app/controllers/application.rb to define
Application

The module I am contemplating will probably have a “terminate”,
“terminate_row” or perhaps “deactivate_row” method to set the
superseded_after attribute as well as setting the active_row attribute
to contain the sql code that passes through :conditions. There may be
other related helper methods that belong in there as well. Given that
there likely will be more than one method I will probably put the
resulting file (active_row.rb ?) into config/initializers.

I learned a lot from this. Many thanks.

James B. wrote:

David A. Black wrote:

I know I’m generalizing past your case, but bear with me as it might
be helpful.

Sad to say perhaps, but my ignorance is so vast I that I am grateful for
every snippet of information that I can fit into my existing
understanding. Your help is greatly appreciated.

This applies to everyone, especially Fred and Andy, lest the context
imply otherwise.