[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

obj.attr(qualifier) = value -- possible?

Michael Schuerig

5/15/2009 6:56:00 PM


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

--
Michael Schuerig
mailto:michael@schuerig.de
http://www.schuerig.d...

8 Answers

Rick DeNatale

5/15/2009 7:10:00 PM

0

On Fri, May 15, 2009 at 3:00 PM, Michael Schuerig <michael@schuerig.de> wro=
te:
>
> I want to write a method that can be called like this
>
> =A0obj.attr(qualifier) =3D value
>
> So far, I don't see how to achieve this. I've tried
>
> class C
> =A0def attr=3D(qualifier, value)
> =A0 =A0...
> =A0end
> end
>
> as well as
>
> class D
> =A0def attr(qualifier)
> =A0 =A0Proxy.new(self, qualifier)
> =A0end
> =A0class Proxy
> =A0 =A0def =3D(value)
> =A0 =A0 =A0...
> =A0 =A0end
> =A0end
> 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 =3D qualifier, value


--=20
Rick DeNatale

Blog: http://talklikeaduck.denh...
Twitter: http://twitter.com/Ri...
WWR: http://www.workingwithrails.com/person/9021-ric...
LinkedIn: http://www.linkedin.com/in/ri...

Joel VanderWerf

5/15/2009 7:14:00 PM

0

Michael Schuerig wrote:
> 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
>

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"

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

Adam Gardner

5/15/2009 7:18:00 PM

0

Rick Denatale wrote:
> On Fri, May 15, 2009 at 3:00 PM, Michael Schuerig <michael@schuerig.de>
> 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.
--
Posted via http://www.ruby-....

Michael Schuerig

5/15/2009 7:50:00 PM

0

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

--
Michael Schuerig
mailto:michael@schuerig.de
http://www.schuerig.d...

Anthony Eden

5/15/2009 8:13:00 PM

0

On Fri, May 15, 2009 at 3:55 PM, Michael Schuerig <michael@schuerig.de> wro=
te:
> Joel VanderWerf wrote:
>
>> I'm pretty sure that's impossible -- there is no #() method, or #()=3D.
>> But there is #[]=3D, 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
> =A0validates_presence_of :type # actor, director, ...
> end
>
> class Movie < ActiveRecord::Base
> =A0has_many :roles
> =A0has_many :participants, :through =3D> :roles do
> =A0 =A0def as(role)
> =A0 =A0 =A0self.scoped(...) # joins and conditions omitted
> =A0 =A0end
> =A0end
> 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') =3D 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 =3D yield
end


-A


--=20
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://...

Brian Adkins

5/15/2009 8:31:00 PM

0

Michael Schuerig <michael@schuerig.de> 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)

--
Brian Adkins
http://...

Michael Schuerig

5/15/2009 8:45:00 PM

0

Anthony Eden wrote:

> On Fri, May 15, 2009 at 3:55 PM, Michael Schuerig
> <michael@schuerig.de> 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.
>
> 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

--
Michael Schuerig
mailto:michael@schuerig.de
http://www.schuerig.d...

Robert Klemme

5/16/2009 1:42:00 PM

0

On 15.05.2009 21:50, Michael Schuerig 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

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestprac...