Dr Nic

map_by_method now increasingly more niftier-er.

Recap on map_by_method magic:

>> p.account.transfers.map_amount # amount method mapped to all Transfers
=> [1878.35, 433.0, 433.0, 433.46, 433.46, 433.46, 433.46, 433.46, 300.0, 300.0]
>> p.account.transfers.map_date.map_to_s # date method mapped to all Transfers, and the Dates mapped into strings
=> ["2003-05-27", "2003-06-23", "2003-06-27", "2003-07-04", "2003-07-11", "2003-07-18", "2003-07-25", "2003-08-08", "2003-09-25", "2003-10-03"]

But if you want the amount and date methods mapped at the same you’ve been plain out of luck, and forced to use the uglier block syntax:

>> p.account.transfers.map {|t| [t.amount, t.date]}

Due to demand-by-inspiration (that is, I just thought of it), you can now use _and_ to join method names together, thusly:

>> p.account.transfers.map_date_and_amount
[[#<Date: 4905573/2,0,2299161>, 1878.35],
 [#<Date: 4905627/2,0,2299161>, 433.0],
 [#<Date: 4905635/2,0,2299161>, 433.0],
 [#<Date: 4905649/2,0,2299161>, 433.46],
 [#<Date: 4905663/2,0,2299161>, 433.46],
 [#<Date: 4905677/2,0,2299161>, 433.46],
 [#<Date: 4905691/2,0,2299161>, 433.46],
 [#<Date: 4905719/2,0,2299161>, 433.46],
 [#<Date: 4905815/2,0,2299161>, 300.0],
 [#<Date: 4905831/2,0,2299161>, 300.0]]
>> p.account.transfers.map_date_and_amount.map_map_to_s
[["2003-05-27", "1878.35"],
 ["2003-06-23", "433.0"],
 ["2003-06-27", "433.0"],
 ["2003-07-04", "433.46"],
 ["2003-07-11", "433.46"],
 ["2003-07-18", "433.46"],
 ["2003-07-25", "433.46"],
 ["2003-08-08", "433.46"],
 ["2003-09-25", "300.0"],
 ["2003-10-03", "300.0"]]

Note the dubious/amusing use of map_map_to_s to apply to_s to the inner arrays. That is, map_to_s is mapped to each inner array.

Want this extended map_by_method magic? Version 0.5 of map_by_method is ready via gem install map_by_method now (or direct download)

Bonus use

Make simple arrays for drop-down lists based on id and a string name field of a list of objects.

>> User.find(:all).map_id_and_firstname
=> [[1, "Glenda"], [2, "Brenda"], [3, "Yas"], [4, "Osborne"], [5, "Gary"], [6, "Anthony"], [7, "Jackie"]]

Debugging use

Some of my Transfer rows had amounts of zero. This was just stupid, but as the initial data was being migrated from a variety of sources I needed to figure out where it was coming from.

“I wonder which account owner(s) this erroneous data comes from?”

> zero_transfers = Transfer.find(:all,:conditions => ['amount < 10 and amount > -10'])
> zero_transfers.map_from_account.map_owner.map_name
["Brenda",
"Brenda",
"Brenda",
"Brenda",
"Brenda"]

And I now knew which files to start cleaning up before re-importing all the data again.

Data investigation in the console/irb becomes almost fun.

Related posts:

  1. map_by_method – the final announcement I don’t really talk about my projects after I release...
  2. map_by_method now works with ActiveRecord associations I was always annoyed that map_by_method was broken for ActiveRecord...
  3. Welcome to the future Welcome to anyone visiting from DHH’s blog and other corners...
  4. [ANN] Generating new gems for graceful goodliness I don’t like you [1]. You don’t share code....
  5. I love “map by pluralisation” [now: map_by_method] Update: this is a gem called map_by_method. The other day...

5 Responses to “map_by_method now increasingly more niftier-er.”

  1. johnpg says:

    Oh crap, I come up with one good idea and you had to beat me to it. :-(

    http://dashing.com/blog/2006/12/09/super_easy_collect_for_activerecord_arrays

    Keep up the great work!

    Cheers,
    John

  2. Dr Nic says:

    @john – dude, we could play “Code Jinx” – for two people who right the same chunk of code :)

  3. Ben says:

    Perhaps I’m being dull, but can’t you just do the first one like:

    p.account.transfers.map(&:amount)

    ?

  4. Dr Nic says:

    @ben: yep that’ll get you the same thing, and I think the Symbol.to_proc solution you’ve got there is going into/has gone into Ruby core itself.

    For me, its too many funny characters (2 brackets, an ampersand, and a colon), and it doesn’t extend to mapping 2+ methods on the objects in the array.

    The upside of the map(&:amount) syntax is you don’t need to invoke to_a on the associations.

    I should get around to fixing that so the association proxy supports the map_by_method idea too.

  5. Avram says:

    Hello,

    I’m having a problem with the map_by_method gem. I don’t understand why, but when I require it from ~/.irbrc, it does not actually get required – *and* any require statements I have after it also seem to have no effect.

    However, when I require it manually from a rails console, it works fine.

    All I am saying in .irbrc is:
    require ‘map_by_method’

    which is exactly the same thing I say in the console when I do it manually, and it works. Any help would be appreciated.