简体   繁体   中英

How do I run methods on respond_with json data in Rails?

I had a model which returns some parameters and includes parameters from other models as follows:

def as_json(options = {})
  camelize_keys(super(options.merge(:only => [:id, :userId], include:{ 
    comments: { only: [:test, :id] },
    valediction: { only: [:name, :text, :hidden, :order] }
  })))
end

def camelize_keys(hash)
  values = hash.map do |key, value|
    [key.camelize(:lower), value]
  end
  Hash[values]
end

Now I have moved the code to my controller because different controller actions need to return different parts of the model. (index should just return valediction, but show should return comments and valediction)

The new controller:

  def index
    respond_with(displayed_user.microposts.all, include: {
      valediction: { only: [:name, :text] }
    })
  end

  def show
    respond_with(displayed_user.microposts.find(params[:id]), include: {
      comments: { only: [:test, :id] },
      valediction: { only: [:name, :text, :hidden, :order] }
    })
  end

But I'm very new to rails and I don't know how to put the camelize_keys function in so that it works.

You could move the method to a class method in the model, eg

#class methods
class << self
  def camelize_keys(hash)
    values = hash.map do |key, value|
      [key.camelize(:lower), value]
    end
    Hash[values]
  end
end

Now you can call this from anywhere like

MyModel.camelize_keys(some_hash)

Doing complex JSON formatting in your controllers / and or models usually leads to bloat and is a pain to test.

A good solution for this is using the ActiveModel::Serializer (AMS) gem. Its included in Rails 5 but you can easily add it to a Rails 4 project by adding it to the gemfile:

# See rubygems.org for latest verstion!
gem 'active_model_serializers', '~> 0.9.3' 

Then run bundle install and restart your rails server.

With AMS you create serializer classes which define how your model data should be represented in JSON, XML etc. A serializer is basically a class that takes a model instance (or an array of models) and returns a hash (or an array of hashes) when you call .serializable_hash .

But Rails will take care of that part automatically for you.

class MicropostSerializer < ActiveModel::Serializer
  attributes :id, :user_id
  has_many :comments
  has_many :valedictions
end

class CommentSerializer < ActiveModel::Serializer
  attributes :test, :id
end

class ValedictionSerializer < ActiveModel::Serializer
  attributes :name, :text, :hidden, :order
end

In your controller you can simply call:

def index
  render json: displayed_user.microposts.all
end

But wait, what about camelize_keys ?

Unless you have to support some weird legacy client that needs camelized keys there are very few reasons to do this. Most large API's use snakecase (Facebook, Google etc.) and Rails 5 is moving towards the JSONAPI spec which uses snakecase.

From your code sample it seems that some of your rails model attributes (and the db columns backing them) use camelcase. You should change the DB column with a migration as soon as possible.

If you HAVE to support a legacy database you can use alias_attribute:

class Pet < ActiveRecord::Base
  alias_attribute :ownerId, :owner_id
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM