Part of the problem is solved, part is not.
Part 1, the solved part:
Children of Lafcadio::DomainObject. This is normally subclassed by somebody using the library, and then fields are set using one-line directives:
def name; "global name method"; end
class Client < Lafcadio::DomainObject
text :name
integer :standard_rate
datetime :created
end
c = Client.new( 'name' => 'My first client', 'standard_rate' => 100, 'created' => Time.now )
puts c.name # was returning 'global name method', I fixed it to return 'My first client'
I fixed this by finding the spot in a class method where all the class fields are being collated for the first time:
class Lafcadio::DomainObject
def self.class_fields #:nodoc:
class_fields = @@class_fields[self]
unless class_fields
@@class_fields[self] = self.get_class_fields
class_fields = @@class_fields[self]
class_fields.each do |class_field|
begin
undef_method class_field.name.to_sym
rescue NameError
# not defined globally or in an included Module, skip it
end
end
end
class_fields
end
end
that solved it, though I'm not crazy about that begin..rescue..end block, I couldn't think of a less cumbersome way to do it.
Part 2, the much worse, as-of-yet-unsolved part:
Lafcadio has a query inference facility, inspired mostly by Criteria, that is useful for expressing queries in ways that can be either turned into SQL or run against an in-memory store. Here's an example:
one_year = 60 * 60 * 24 * 365
fave_clients = object_store.get_clients { |cli|
Query.And( cli.standard_rate.gte( 100 ), cli.created.gte( Time.now - one_year ) )
}
What actually happens is, inside that block, Lafcadio pushes through an object of class DomainObjectImpostor, which uses method_missing to create query clauses when it receives calls like #standard_rate and #created. (It actually spits out ObjectFieldImpostors, which then listen to methods like #gte.)
But here's the problem:
def name; "global name method"; end
first_client = object_store.get_clients { |cli|
cli.send( :name ).equals( 'My first client' )
}[0]
This won't work, because #name will get dispatched to the global method. And I can't use undef_method in this case, because I shouldn't undef the global #name method to _every_ instance of DomainObjectImpostor, because only some DomainObjectImpostors will be pretending to be Clients. Others will be pretending to be Users, Invoices, Projects, etc., etc., and they should be able to dispatch calls to the global #name method.
Is there a way to undef a method for just one instance? Or maybe I should consider instantiating new classes for every "instance", in the same way that you can call DelegateClass( some_class ) when using delegate.rb?
Or maybe I'm just making the whole thing overly complicated and there's some simple answer right in front of my nose ...
Francis Hwang
···
On Jun 2, 2005, at 9:55 AM, Yukihiro Matsumoto wrote:
Hi,
In message "Re: preventing Object#send from dispatching to a global > method?" > on Sun, 29 May 2005 00:42:46 +0900, Francis Hwang > <sera@fhwang.net> writes:
>Is there a way to prevent Object#send from dispatching to a global
>method?
How about undef'ing global methods from the class? See delegate.rb in
the distribution.
matz.