0

When I run a simple query of Item.where(:id => id) in my ItemHelper class and it returns

[
{
JDPA: null,
_id: "530e45f43f72fb3dee000001",
category: null,
created_at: "2014-02-26T19:52:20Z",
creator: "5170547c791e4b1a16000001",
detail: "Detail",
event_id: "52d958e73f72fb1e1f000001",
image_content_type: null,
image_file_name: null,
image_file_size: null,
image_updated_at: null,
question: null,
section: null,
title: "Title",
updated_at: "2014-02-26T19:52:21Z",
veh1: 5,
veh10: null,
veh2: 5,
veh3: 6,
veh4: null,
veh5: null,
veh6: null,
veh7: null,
veh8: null,
veh9: null,
version: null
}
]

I want to get an array of :veh1..:veh10 as [5, 5, 6, null, ...]. Having a lot of trouble doing this...

I thought of using JBuilder in my helper, but now I've blown things up...

How can I do something as simple as using .only(:veh1..:veh10 and remove the nulls...then I could probably make an array.

Thoughts, comments, am I being dumb?? Should this be easy? I'm a beginner here. :)

My Answer

This feels really sloppy. Is there a better way to do this?? More elegant??

def item_ppu(id)
  item = Item.where(:_id => id)
  newitem = item.map{|i| [i.veh1, i.veh2, i.veh3, i.veh4, i.veh5, i.veh6, i.veh7, i.veh8, i.veh9, i.veh10]}

  h = Hash.new(0)
  newitem[0].each { | v | h.store(v, h[v]+1) }

  f = 2*h[2]#lots more math

  return f
end
Kevin Brown
  • 12,602
  • 34
  • 95
  • 155
  • Is that a JSON representation of what is returned? There is no `null` in Ruby. What is the actual object? – Zach Kemp Feb 26 '14 at 23:04
  • @Zach, Yes, that's the json output. I'm not sure how to go about inspecting objects...My debug method is to change the helper and refresh browser...is that bad? – Kevin Brown Feb 26 '14 at 23:07
  • No, not bad necessarily, but it would be my third choice after tests and using the console. Is this a Mongoid model? – Zach Kemp Feb 26 '14 at 23:11

1 Answers1

1

If this is a Mongoid model, and you're only looking for a single object, you can just use find and then map to the attributes you need:

object = Item.find(id)

You can use values_at to retrieve specific values from the object's attributes hash (in Mongoid, the hash's keys are strings):

keys = (1..10).map {|n| "veh#{n}" } #=> ["veh1", "veh2" ...
values = object.attributes.values_at(*keys)
values.compact # removes the nil values from the array

Taken all together:

object.attributes.values_at(*(1..10).map {|n| "veh#{n}" }).compact

EDIT

In the interest of writing clean, understandable code, here's how I would actually write this in a production app:

class Item
  # whatever goes here

  def ppu
    veh_values.inject {|result, value| # ... some calculation }
  end

  private

  def veh_values
    attributes.values_at(*veh_keys).compact
  end

  def veh_keys
    (1..10).map {|n| "veh#{n}" }
  end
end

This is now an instance method on the Item class, so to call it, your syntax would be:

item.ppu
Zach Kemp
  • 11,736
  • 1
  • 32
  • 46
  • Wow...that's why I always come here to SO. For my personal rails betterment, can you speak to the method I figured out (after a few hours)? Is my method acceptable, or poorly done? – Kevin Brown Feb 26 '14 at 23:29
  • @KevinBrown, You're dealing with a single item inside an array, so it makes more sense to just use the object instead of treating it like an array (`map`, `[0]`, etc). I'm not really sure what's going on with the hash or the `f` variable. But here's what I use as criteria for whether a method is "acceptable": 1 (most important): Can it be easily understood? 2: Does it do what it says it does, without any unexpected side effects? 3: Is it reasonably efficient? The code I gave you is on the edge of being a little too complicated for a single method, so I'll edit my answer. Stand by. – Zach Kemp Feb 26 '14 at 23:46
  • Looks good, thanks. If I'm calling `.ppu` in a loop, though (like in my view) that won't work? What's the best way to do in that case? – Kevin Brown Feb 27 '14 at 15:24