I want to write a method that can be called like this
obj.attr(qualifier) = value
So far, I don’t see how to achieve this. I’ve tried
class C
def attr=(qualifier, value)
…
end
end
as well as
class D
def attr(qualifier)
Proxy.new(self, qualifier)
end
class Proxy
def =(value)
…
end
end
end
Neither is valid Ruby, apparently. Is there another, working way?
Michael
On Fri, May 15, 2009 at 3:00 PM, Michael S. [email protected]
wrote:
end
…
end
end
end
Neither is valid Ruby, apparently. Is there another, working way?
I don’t think you can get the calling syntax you want. The best you
can do I think is
obj.attr = qualifier, value
–
Rick DeNatale
Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
Michael S. wrote:
end
end
end
end
Neither is valid Ruby, apparently. Is there another, working way?
Michael
I’m pretty sure that’s impossible – there is no #() method, or #()=.
But there is #[]=, and you can adapt your Proxy approach to use it:
class D
def attr
Proxy.new(self)
end
def handle qualifier, value
puts “handling #{qualifier.inspect}, #{value.inspect}”
end
class Proxy
def initialize obj
@obj = obj
end
def []=(qualifier, value)
@obj.send (:handle, qualifier, value)
end
end
end
d = D.new
d.attr[“some qualifier”] = “some value”
Joel VanderWerf wrote:
I’m pretty sure that’s impossible – there is no #() method, or #()=.
But there is #[]=, and you can adapt your Proxy approach to use it:
That’s a good suggestion, but unfortunately, it doesn’t fit in my case.
I’m trying to do this stuff in an extension module for a Rails has_many
:through association. It looks roughly like this
class Role < ActiveRecord::Base
validates_presence_of :type # actor, director, …
end
class Movie < ActiveRecord::Base
has_many :roles
has_many :participants, :through => :roles do
def as(role)
self.scoped(…) # joins and conditions omitted
end
end
end
This allows me to write code like
movie.participants.as(‘actor’)
On top of that, I’d like to be able to write
movie.participants.as(‘actor’) = params[:movie][:actors]
and that’s where I’m stuck.
Michael
Rick Denatale wrote:
On Fri, May 15, 2009 at 3:00 PM, Michael S. [email protected]
wrote:
�end
� � �…
� �end
�end
end
Neither is valid Ruby, apparently. Is there another, working way?
I don’t think you can get the calling syntax you want. The best you
can do I think is
obj.attr = qualifier, value
Well, you could always go with obj.attr[qualifier] = value
irb(main):004:0> class Ooo
irb(main):005:1> attr_reader :attr
irb(main):006:1> def initialize
irb(main):007:2> @attr = {}
irb(main):008:2> end
irb(main):009:1> end
=> nil
irb(main):010:0> obj = Ooo.new
=> #<Ooo:0x6fe6b8 @attr={}>
irb(main):011:0> obj.attr[:happy] = :sad
=> :sad
irb(main):012:0> obj.attr
=> {:happy=>:sad}
irb(main):013:0> obj.attr[:happy]
=> :sad
irb(main):014:0>
This example used a hash because it’s easy, buy could make @attr be any
class that accepts the []= method, including a class of your own.
wickie
May 15, 2009, 10:13pm
6
On Fri, May 15, 2009 at 3:55 PM, Michael S. [email protected]
wrote:
validates_presence_of :type # actor, director, …
This allows me to write code like
movie.participants.as(‘actor’)
On top of that, I’d like to be able to write
movie.participants.as(‘actor’) = params[:movie][:actors]
and that’s where I’m stuck.
If you’re willing to use a block you could do
movie.participants.as(‘actor’) { params[:movie][:actors] }
and then:
def as(role, &block)
value = yield
end
-A
–
GMU/IT d- s: a32 C++(++++)$ UL@ P— L+(++) !E W+++$ !N o? K? w— !O
M++ V PS+ PE Y PGP t+ !5 X- R tv b++ DI+ D++ G- e++ h---- r+++ y++++**
http://anthony.mp
wickie
May 15, 2009, 10:45pm
7
Anthony E. wrote:
On Fri, May 15, 2009 at 3:55 PM, Michael S.
[email protected] wrote:
[…]
If you’re willing to use a block you could do
movie.participants.as(‘actor’) { params[:movie][:actors] }
and then:
def as(role, &block)
value = yield
end
Another interesting suggestion. But I think I use
def replace(role, value)
…
end
as there’s a precedent in the Rails association methods for #replace and
the generated #replace is not useful in this case anyway.
Michael
On 15.05.2009 21:50, Michael S. wrote:
This allows me to write code like
movie.participants.as(‘actor’)
On top of that, I’d like to be able to write
movie.participants.as(‘actor’) = params[:movie][:actors]
and that’s where I’m stuck.
The only way to modify behavior of the assignment operator in Ruby is
the route through []= AFAIK. If you want to use “=” you will have to do
down that route. But I see you have got your working solution already.
Just wanted to make sure expectations are not unrealistic.
Kind regards
robert
wickie
May 15, 2009, 10:35pm
9
Michael S. [email protected] writes:
I want to write a method that can be called like this
obj.attr(qualifier) = value
So far, I don’t see how to achieve this.
Me neither. And the following:
obj = Foo.new
obj.attr(qualifier).assign(value)
seems inferior to:
obj.attr_assign(qualifier, value)