Thanks for the reply, but it’s not that easy as it seems. My
RecordWithFeatures overloads the “find” method. Implementing the
functionality as a module would completely overWRITE the find method.
I had already a discussion on that on this list, it’s not trivial,
because “find” uses recursive calls, so there are two options for the
implementation.
First (as I did), subclassing AR and overriding find. The second (I also
tried) writing a module and aliasing the find method. The second one
works great, but from a coder’s point of view, it is really messy,
because in some cases it can break “find” completetly.
Now I post both solutions, maybe someone have an idea how (if) those can
be improved.
The first one: Extending AR
class RecordWithFeatures < ActiveRecord::Base
def self.descends_from_active_record?
superclass == RecordWithFeatures
end
def self.class_name_of_active_record_descendant(klass)
…
end
def self.without_context_scope
begin
Thread.current[:bypass_context_scope] = true
result = yield
ensure
Thread.current[:bypass_context_scope] = nil
end
return result
end
def self.bypass_context_scope?
Thread.current[:bypass_context_scope] == true
end
def self.find(*args)
unless bypass_context_scope?
with_scope(:find => {:conditions => “…”}) do
return without_context_scope { super }
end
end
super
end
def self.find_context_neutral(*args)
return without_context_scope { find(*args) }
end
end
class SomeModel << RecordWithFeatures
belongs_to :context
validates_presence_of :context
end
And now the other one with “including” and “aliasing”!
module ContextRecord
def self.included(base) # :nodoc:
base.extend ClassMethods
end
module ClassMethods
def bound_to_context
belongs_to :context
validates_presence_of :context
class_eval { extend ContextRecord::SingletonMethods }
include InstanceMethods
class << self
alias_method :original_find, :find
alias_method :find, :find_with_context_scope
end
end
end
module SingletonMethods
def without_context_scope
begin
Thread.current[:bypass_context_scope] = true
result = yield
ensure
Thread.current[:bypass_context_scope] = nil
end
return result
end
def bypass_context_scope?
Thread.current[:bypass_context_scope] == true
end
def find(*args)
unless bypass_context_scope?
with_scope(:find => {:conditions => "..."}) do
return without_context_scope {original_find(*args)}
end
end
original_find(*args)
end
def find_context_neutral(*args)
without_context_scope {original_find(*args)}
end
end
module InstanceMethods
# …
end
end
ActiveRecord::Base.class_eval { include ContextRecord }
class SomeModel << ActiveRecord::Base
bound_to_context
end
Thanks
Dim