30

It's a pain to write codes like this all the time in jbuilder.json template:

json.extract! notification, :id, :user_id, :notice_type, :message, :resource_type, :resource_id, :unread, :created_at, :updated_at

So I'd like to code like this;

json.extract_all! notification

I've found I can do it like the following codes, but they are still a bit lengthy to me.

notification.attributes.each do |key, value|
  json.set!(key, value)
end

Is there any better way?

chikaram
  • 700
  • 1
  • 7
  • 18
  • 1
    Maybe this is a bit simpler, `json.extract! notification, *notification.attributes.keys` But if Jbuilder has a method like this, I want to use it instead. – chikaram Apr 12 '14 at 07:45

6 Answers6

56

Maybe you can use json.merge!.

json.merge! notification.attributes

https://github.com/rails/jbuilder/blob/master/lib/jbuilder.rb#L277

zato
  • 741
  • 8
  • 4
  • Thanks! This is exactly what I want!! Only, my Rails version is 4.0 so I should upgrade it to 4.1 first. – chikaram May 03 '14 at 10:50
  • I just tried to use this method with Rails 4.1 but unfortunately it doesn't seem to be merged into 4.1. So I decided to wait a little more. – chikaram Jun 18 '14 at 07:22
  • Are you using the latest version of jbuilder? Try `bundle update jbuilder`. – zato Jun 18 '14 at 07:39
  • Oh jbuilder is only a gem and has nothing to do with Rails versions as of now. The method worked fine with jbuilder 2.1.1! Thank you for your trouble. – chikaram Jun 20 '14 at 16:49
  • 1
    Beware revealing sensitive attributes. Add a `reject` to filter one or more out: `json.merge! user.attributes.reject {|k, v| k == 'encrypted_password' }` – bjnord Sep 14 '17 at 19:51
  • Works great in jbuild 2.11, Rails 7rc – Carson Cole Nov 09 '21 at 18:59
11

I'm using jbuilder 1.5.0 and merge! didn't work but I found an alternative syntax:

json.(notification, *notification.attributes.keys)
jvalanen
  • 2,809
  • 1
  • 16
  • 9
  • 1
    As @Dakuan said, this obeys `JBuilder.key_format` setting, which is necessary if you're converting your keys from snake_case to camelCase. According to [this railscast](http://railscasts.com/episodes/320-jbuilder?language=en&view=asciicast) I believe this syntax won't work in some versions of ruby, in which case the working syntax is `json.extract! notification, *notification.attributes.keys` – abl Jul 29 '15 at 16:43
3

Adding more to @uiureo 's answer

Suppose your Notification has some type of image uploaders (e.g. carrierwave,paperclip)

Then below version will not return you uploader object, so how do you get the image url?

json.merge! notification.attributes

notification.attributes is hash conversion of object, it will return mounted uploader column value but not the url.

sample response

notification: Object {
   title: "hellow world"
   img: "sample.png"
}

Instead try this

json.merge! notification.as_json

This will return mounted column as another object in which you can query for url.

sample response

notification: Object {
   title: "hellow world"
   img: Object {
       url: "https://www.example.com/sample.png"
   }
}
Rahul Singh
  • 3,417
  • 2
  • 25
  • 32
0

You may look at json.except!

json.except! @resource, :id, :updated_at

json.except! @resource

https://github.com/chenqingspring/jbuilder-except

user2091375
  • 109
  • 1
  • 3
0

In case if you want to exclude any of the attributes. Ex: created_at and updated_at

json.merge! notification.attributes.reject{ |key, _| key.in?(['created_at', 'updated_at']) }
Jak
  • 2,893
  • 3
  • 19
  • 33
0

This is how I do it

json.property  do
  Property.column_names.each do |name|
     json.set! name, @property.try(name)
  end

  # has_ones:
  json.contact @property.contact
end

It's easy to see what's happening, add logic to omit fields etc doing it this way.

Will
  • 4,498
  • 2
  • 38
  • 65