Dynamic Method Calls

Right now I have some inefficient code that looks like this…

LdapAccount is my model… and record.attributes is a hash of attribute
name,value pairs.

records.each do |record|
LdapAccount.create(:uid => record.attributes[“uid”].to_s) do |c|
c.buildingname = record.attributes[“buildingName”].to_s if
record.attributes.has_key?(“buildingName”)
c.cn = record.attributes[“cn”].to_s if
record.attributes.has_key?(“cn”)
c.department = record.attributes[“department”].to_s if
record.attributes.has_key?(“department”)
c.displayname = record.attributes[“displayName”].to_s if
record.attributes.has_key?(“displayName”)
c.employeetype = record.attributes[“employeeType”].to_s if
record.attributes.has_key?(“employeeType”)
c.givenname = record.attributes[“givenName”].to_s if
record.attributes.has_key?(“givenName”)
c.homedirectory = record.attributes[“homeDirectory”].to_s if
record.attributes.has_key?(“homeDirectory”)
c.mail = record.attributes[“mail”].to_s if
record.attributes.has_key?(“mail”)
end
end

There’s probably 20 or more attributes I’ll eventually be checking…I’m
working with tens of thousands of records…and not all records have
values for every attribute. So rather than do all the extra wasted
work, I’d really like to be able to do something simpler like this…

records.each do |record|
LdapAccount.create(:uid => record.attributes[“uid”].to_s) do |c|
record.attributes.each_pair do |k,v|
c.k = v
end
end
end

…but I get…
undefined method `k=’ for #LdapAccount:.....

Did a little research and read about the send method…so I tried
this…

c.send(k = v)

…but I get… (in this case the String value of v = “smtp.wiu.edu”)
[“smtp.wiu.edu”] is not a symbol

So I’m not sure I understand how to use the send method in this case.
Can anyone offer some insight? Am I headed in the right direction or is
there a better way to do this.

Thanks,
Matt

Hei Matt,

try c.send(k, v)
I haven’t tried that myself but it looks like what you want to
accomplish.

Bye!


Andrea D.

Whoopsie, i’m really sorry. It should be something like:

c.send("#{k}=".to_sym, v)

On Apr 1, 2010, at 11:35 , Andrea D. wrote:

Whoopsie, i’m really sorry. It should be something like:

c.send("#{k}=".to_sym, v)

.to_sym is unnecessary

This did it…thanks for the assistance… :slight_smile:

c.send(“#{k.downcase}=”, “#{v}”)

Every record.attributes value is an Array, even if they are
single-valued. When I store the data into the LdapAccount model…it
just stores the data as a String. Which is fine for single-valued
arrays, but the multi-valued is a problem. I could do the following…

c.send(“#{k.downcase}=”, “#{v.inspect}”)

Which would store every single or multi valued array in the model as a
String like so…
single: [“SOMEVAL”]
multi: [“val1”,“val2”,“val3”,etc…]

But that may be more work when I want to pull that data back out at some
point in the future. Should I store the single valued attributes as a
plain String and the multi-valued attributes as an Array String like
above?

Something like this maybe…

LdapAccount.create(:uid => record.attributes[“uid”].to_s) do |c|
record.attributes.each_pair do |k,v|
# v is an array of single or multi attribute values
if v.size > 1
c.send(“#{k.downcase}=”, “#{v.inspect}”)
else
c.send(“#{k.downcase}=”, “#{v}”)
end
end
end

Any thoughts?

Thanks,
Matt

----- Original Message -----
From: “Ryan D.” [email protected]
To: “ruby-talk ML” [email protected]
Sent: Thursday, April 1, 2010 1:42:56 PM
Subject: Re: Dynamic Method Calls

On Apr 1, 2010, at 11:35 , Andrea D. wrote:

Whoopsie, i’m really sorry. It should be something like:

c.send(“#{k}=”.to_sym, v)

.to_sym is unnecessary

Hmmm…can’t seem to make that happen…

class LdapAccount < ActiveRecord::Base
serialize :objectclass, Array
end

I think because I’m wrapping the value in quotes turning the Array v to
a String when it’s saved in the model…
c.send(“#{k.downcase}=”, “#{v}”)

Produces…
objectclass was supposed to be a Array, but was a String

I can’t take the quotes off though because it doesn’t save correctly in
the database. Using this code, entries end up looking like this when I
don’t wrap v in quotes.
c.send(“#{k.downcase}=”, v)

'—

  • inetLocalMailRecipient
  • person
  • posixAccount
  • sambaSamAccount
  • shadowaccount
  • top

Matt

----- Original Message -----
From: “AMILIN Aurélien” [email protected]
To: “ruby-talk ML” [email protected]
Sent: Thursday, April 1, 2010 3:14:00 PM
Subject: Re: Dynamic Method Calls

You should try to serialize your array instead of saving it as a string
if you are using ActiveRecord try this :
class LdapAccount < ActiveRecord::Base
serialize :mails, Array
end

then when you get the accout from the database :
my_account.mails return an Array

Le 01/04/2010 21:59, Matt M. a écrit :

You should try to serialize your array instead of saving it as a string
if you are using ActiveRecord try this :
class LdapAccount < ActiveRecord::Base
serialize :mails, Array
end

then when you get the accout from the database :
my_account.mails return an Array

Le 01/04/2010 21:59, Matt M. a écrit :

c.send("#{k.downcase}=", v) is the right thing to do and it is normal if
it is saved as :
'—

  • inetLocalMailRecipient
  • person
  • posixAccount
  • sambaSamAccount
  • shadowaccount
  • top

It’s just because it is saved into the yaml format
Just get back the LdapAccount you just saved and you will see that the
objectclass attribute will be an instance of Array

Le 01/04/2010 22:49, Matt M. a écrit :