0

How can I use #map to hide an attribute if it's nil?

Conditions aren't working inside a block, so I tried this:

account_info = some_db_request
account_info.fields.map do |field|
                    {
                        id: field.id,
                        hidden: field.hidden
                        size: field.size
                    }
account_info
=> "{\"email\":\"admin@test.com\",\"name\":\"admin@test.com\",\"roles\":[\"admin\",\"user\"],\"fields\":[{:id=>3, :hidden=>"",size=>80},{:id=>3, :hidden=>"true",size=>80}],\"redirect_to\":[]}"
then I convert output in json

I expected:

"fields": [
        {
            "id": 3, # if hidden = ''
            "size": 90
        },
        {
            "id": 4,
            "hidden": "true", if hidden = 'true'
            "size": 190
        }]

But got:

"fields": [
        {
            "id": 3,
            "hidden" = ''
            "size": 90
        },
        {
            "id": 4,
            "hidden": "true" if hidden = 'true'
            "size": 190
        }]

How can I get the expected output?

QWD666
  • 129
  • 6
  • Can you post valid Ruby code? When you copy the code you've posted and try to run it, it will throw an error. Can you also include an example and the desired result from that example after calling the method you need ? – Viktor Oct 22 '19 at 08:22
  • You have two `hidden:` keys in your hash – is that a typo? – Stefan Oct 22 '19 at 08:45
  • Where does that `if hidden = ''` / `if hidden = 'true'` in your output come from? And why do you expect the output to leave out a field although you explicitly specify it in the return value of `map`? – Stefan Oct 22 '19 at 08:48
  • What does "Conditions aren't working inside a block" mean? A block is just arbitrary normal standard Ruby code, there is nothing special about it. Why would conditions not work in it? Try, e.g. `(0..).each do |n| p n if n.even? end` – Jörg W Mittag Oct 22 '19 at 08:53

1 Answers1

3

A quick and dirty fix is to just compact the hash after:

account_info.fields.map do |field|
  {
    id: field.id,
    hidden: field.hidden
    size: field.size
  }.compact!
end

or

account_info.fields.map do |field|
  {
    id: field.id,
    hidden: field.hidden
    size: field.size
  }.reject{|k,v| v.nil?}
end

Or finally without assigning any nil values in the first place:

account_info.fields.map do |field|
  h = Hash.new
  h[:id] = field.id if !field.id.nil?
  h[:hidden] = field.hidden if !field.hidden.nil?
  h[:size] = field.size if !field.size.nil?
  h
end
Mark
  • 6,112
  • 4
  • 21
  • 46
  • Well, I thought there were elegant solutions, but apparently will have to do through reject – QWD666 Oct 22 '19 at 08:43
  • I think the first is the least ugly but yeah, you would expect Rails to offer something nicer – Mark Oct 22 '19 at 08:48
  • In your 2nd example, `hash_with_nils` is actually an array (of hashes). You'd have to call `reject` on the inner hash, i.e. that within `map`. But there's no advantage over `compact` in this case. – Stefan Oct 22 '19 at 09:06
  • And there's a minor difference between the first and last example: `compact` only removes `nil` values whereas `if field.hidden` would also omit `false` values. You'd have to explicitly test for `if field.hidden.nil?` to make them equivalent. – Stefan Oct 22 '19 at 09:13