PHWinfo banniere

Titres
PORTAIL ANNUAIRE ARTICLES COMPARATEUR HÉBERGEURS DEVIS FORUMS RÉDUCTEUR D'URL
Précédent   PHWinfo > Autres forums > Forum Programmation & Conception > comp.lang.ruby > Quick way to get attributes (without using collect)
S'inscrire FAQ Membres Recherche Messages du jour Marquer les forums comme lus
Quick way to get attributes (without using collect)

Réponse
 
LinkBack Outils de la discussion
Vieux 20/11/2007, 17h03   #1
Max Williams
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Quick way to get attributes (without using collect)

This was inspired by Rails, but i think it's common Ruby question. Say
i have an array of Employee objects, which have an attribute "name". I
want to get all the names, as an array.

Let's say i already have the variable "employees", which points to an
array of Employee objects.

What i want to do is something like this -

employee_names = employees.names

But what i have to keep on doing is something like this -

employee_names = employees.collect{ |emp| emp.name}

Now, this isn't a *massive* hassle, and i find Array#collect incredibly
useful, but it's a bit annoying to have to keep typing it again and
again. Is there a way to set it up so that

foos

is automatically treated as

collect { |x| x.foo }

?

Or another way to do this simply?

thanks
max
--
Posted via http://www.ruby-forum.com/.

  Réponse avec citation
Vieux 20/11/2007, 17h12   #2
Farrel Lifson
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Quick way to get attributes (without using collect)

On 20/11/2007, Max Williams <toastkid.williams@gmail.com> wrote:
> This was inspired by Rails, but i think it's common Ruby question. Say
> i have an array of Employee objects, which have an attribute "name". I
> want to get all the names, as an array.
>
> Let's say i already have the variable "employees", which points to an
> array of Employee objects.
>
> What i want to do is something like this -
>
> employee_names = employees.names
>
> But what i have to keep on doing is something like this -
>
> employee_names = employees.collect{ |emp| emp.name}
>
> Now, this isn't a *massive* hassle, and i find Array#collect incredibly
> useful, but it's a bit annoying to have to keep typing it again and
> again. Is there a way to set it up so that
>
> .foos
>
> is automatically treated as
>
> .collect { |x| x.foo }
>
> ?
>
> Or another way to do this simply?


You can use the Symbol#to_proc method

class Symbol
def to_proc
Proc.new {|e| e.send(self)}
end
end

Which will let you right
employee_names = employees.collect(&:name)

Farrel

  Réponse avec citation
Vieux 20/11/2007, 17h16   #3
Jano Svitok
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Quick way to get attributes (without using collect)

On Nov 20, 2007 6:03 PM, Max Williams <toastkid.williams@gmail.com> wrote:
> This was inspired by Rails, but i think it's common Ruby question. Say
> i have an array of Employee objects, which have an attribute "name". I
> want to get all the names, as an array.
>
> Let's say i already have the variable "employees", which points to an
> array of Employee objects.
>
> What i want to do is something like this -
>
> employee_names = employees.names
>
> But what i have to keep on doing is something like this -
>
> employee_names = employees.collect{ |emp| emp.name}
>
> Now, this isn't a *massive* hassle, and i find Array#collect incredibly
> useful, but it's a bit annoying to have to keep typing it again and
> again. Is there a way to set it up so that
>
> .foos
>
> is automatically treated as
>
> .collect { |x| x.foo }
>
> ?
>
> Or another way to do this simply?


Let me introduce to you #method_missing. It's being called when the
method called is not found. The standard implementation just raises
NoMethodError,
but you can do anything there. In fact, this is how Rails does it's
find_by_this_and_that magic.

So, this is the idea (not tested, just written in the mail):

class Array
def method_missing(name, *args)
single_method = name.to_s.chop # 1. name is a symbol, 2. chop for simplicity
if !empty? && first.respond_to?(single_method)
collect { |x| x.send(single_method, *args) } # do whatever you want here
else
super # inherited implementation
end
end
end

Just make sure that this will not break the whole system (check for
's', and look any methods that might end with it, etc.)

Lookup the code in the Rails' sources, most probably you'll find there
nice singular/plural conversion etc.

  Réponse avec citation
Vieux 20/11/2007, 17h24   #4
Sebastian Hungerecker
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Quick way to get attributes (without using collect)

Max Williams wrote:
> This was inspired by Rails, but i think it's common Ruby question.
> [...]
> What i want to do is something like this -
>
> employee_names = employees.names
>
> But what i have to keep on doing is something like this -
>
> employee_names = employees.collect{ |emp| emp.name}


In rails you can do "employee_names = employees.collect(&:name)" which is
somewhat more concise (though it incurs a performance penalty, I am told).

> Is there a way to set it up so that
> .foos
> is automatically treated as
> .collect { |x| x.foo }


module Enumerable
def method_missing(meth, *args, &blk)
map {|x| x.send(meth,*args, &blk)}
end
end

This might easily lead to bugs though if you want to invoke method on the
elements of the enum, not considering or not knowing that the enum itself
implements that method as well. For example:
[2,4,6] / 2 #=> [1, 2, 3]
But:
[2,4,6] * 2 #=> [2,4,6,2,4,6]

Or:
["1","2","3"].to_i #=> [1, 2, 3]
But:
[1,2,3].to_s #=> "123"


HTH,
Sebastian
--
Jabber: sepp2k@jabber.org
ICQ: 205544826

  Réponse avec citation
Vieux 20/11/2007, 17h30   #5
Max Williams
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Quick way to get attributes (without using collect)

Thanks guys - i'll try the method missing approach, and also the rails
built in slightly shorter version

cheers
max
--
Posted via http://www.ruby-forum.com/.

  Réponse avec citation
Vieux 20/11/2007, 17h55   #6
Brian Adkins
Aucun Avatar
 
Messages: n/a
Hébergeur:
Par défaut Re: Quick way to get attributes (without using collect)

On Nov 20, 12:12 pm, Farrel Lifson <farrel.lif...@gmail.com> wrote:
> On 20/11/2007, Max Williams <toastkid.willi...@gmail.com> wrote:
> > Say
> > i have an array of Employee objects, which have an attribute "name". I
> > want to get all the names, as an array.
> > ...
> > What i want to do is something like this -

>
> > employee_names = employees.names

>
> > But what i have to keep on doing is something like this -

>
> > employee_names = employees.collect{ |emp| emp.name}

>
> You can use the Symbol#to_proc method
>
> class Symbol
> def to_proc
> Proc.new {|e| e.send(self)}
> end
> end
>
> Which will let you right
> employee_names = employees.collect(&:name)


map is shorter than collect. Also, adding optional args to to_proc
will make it more generally useful.

class Symbol
def to_proc
lambda {|obj, *args| obj.send(self, *args) }
end
end

employee_names = employees.map(&:name)

I'd be wary of using method_missing for this.

Brian Adkins
  Réponse avec citation
Réponse


Outils de la discussion

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Trackbacks are oui
Pingbacks are oui
Refbacks are oui


Fuseau horaire GMT +1. Il est actuellement 02h02.


Édité par : vBulletin® version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.2.0 RC5 Tous droits réservés.
Version française #16 par l'association vBulletin francophone
PHWinfo est un site Éducation Sans Frontières
Ad Management by RedTyger
©Tous droits réservés par les parties respectives
Page generated in 0,15405 seconds with 14 queries