Filter the model attributes before issuing json

Hey guys, I need to output my model as json and everything is going well. However, some attributes must be “decorated” by filtering them using some helper methods, such as number_to_human_size. How can i do this?

In other words, let's say that I have an attribute with a name bytes, and I want to pass it through number_to_human_size, and this result will be output in json.

I would also like to "crop" what will be output as json, if possible, since I only need some attributes. Is it possible? Can someone please give an example? I would be very grateful.

Preliminary search results hint at something relative as_json, but I cannot find a tangible example regarding my situation. If this is really a solution, I would really appreciate an example.

Research . It seems I can use the options to_jsonto explicitly indicate which attributes I want, but I still need to figure out how to “decorate” or “filter” certain attributes by passing them through a helper before they are displayed as json.

Will I create a partial for one json model, so _model.json.erb, and then create another one for the action that I use, and inside that just make it partial with a collection of objects? It looks like a bunch of hoops to slip through. I am wondering if there is a more direct / raw way to change the json representation of the model.

+3
source share
2 answers

Your model can override the method as_jsonthat Rails uses when rendering json:

# class.rb
include ActionView::Helpers::NumberHelper
class Item < ActiveRecord::Base
  def as_json(options={})
    { :state => state, # just use the attribute when no helper is needed
      :downloaded => number_to_human_size(downloaded)
    }
  end
end

Now you can call render :jsonin the controller:

@items = Item.all
# ... etc ...
format.json { render :json => @items }

Rails will call Item.as_json@items for each member and return a JSON-encoded array.

+7
source

I have solved a solution to this problem, but I do not know how much better it is. I would appreciate understanding.

@items = Item.all

@response = []

@items.each do |item|
  @response << {
      :state => item.state,
      :lock_status => item.lock_status,
      :downloaded => ActionController::Base.helpers.number_to_human_size(item.downloaded),
      :uploaded => ActionController::Base.helpers.number_to_human_size(item.uploaded),
      :percent_complete => item.percent_complete,
      :down_rate => ActionController::Base.helpers.number_to_human_size(item.down_rate),
      :up_rate => ActionController::Base.helpers.number_to_human_size(item.up_rate),
      :eta => item.eta
  }
end

respond_to do |format|
  format.json { render :json => @response }
end

Basically, I build a hash on the fly with the values ​​I want, and then render them. This works, but as I said, I'm not sure if this is the best way.

+1
source

Source: https://habr.com/ru/post/1782528/


All Articles