Rails 4 - Remove “created_at” and “updated_at” fro

2020-02-29 04:36发布

When I want to remove these datas from one resource I do:

@teams = Team.all

render json: @teams, :except => [:created_at, :updated_at],

My doubt is when I have many includes like these:

@teams = Team.all

render json: @teams, :include => [:stadiums, :scores, :links, :rounds]

How do I remove from all of them?

2条回答
爱情/是我丢掉的垃圾
2楼-- · 2020-02-29 05:11

Correction: You can do something like

render json: @teams.to_json(:except => [:created_at, :updated_at], :include => { :stadiums => { :except => [:created_at, :updated_at]}, ... })

There is no simple way of doing this without iterating over the relevant models, obtaining the attributes hash and selecting the desired attributes.

Such use cases are often solved elegantly using json templating DSLs like jbuilder or rabl.

To illustrate this using jbuilder:

Jbuilder.encode do |json|
  json.array! @teams do |team|
    json.name team.name
    json.stadiums team.stadiums do |stadium|
      json.name stadium.name
      # Other relevant attributes from stadium
    end
    # Likewise for scores, links, rounds
  end
end

Which would produce the output as:

[{
  name: "someteamname",
  stadiums: {
    name: "stadiumname"
  },
  ...
}, {...},...]

If you find this too verbose for your use case, as @liamneesonsarmsauce has pointed out in the comments another solution is to use ActiveModel Serializers

Using this approach you can specify a serializer class for each of your models, listing the allowed attributes which would become a part of json response. For example

class TeamSerializer  < ActiveModel::Serializer
  attributes :id, :name # Whitelisted attributes

  has_many :stadiums
  has_many :scores
  has_many :links
  has_many :rounds
end

You can define similar serializers for associated models as well.

Since associations are seamlessly handled in a way that is already familiar to rails developers, unless you require much customization of the generated json response, this is a more succinct approach.

查看更多
可以哭但决不认输i
3楼-- · 2020-02-29 05:15

How 'bout adding to models/application_record.rb

# Ignore created_at and updated_at by default in JSONs 
# and when needed add them to :include
def serializable_hash(options={})
  options[:except] ||= []
  options[:except] << :created_at unless (options[:include] == :created_at) || (options[:include].kind_of?(Array) && (options[:include].include? :created_at))
  options[:except] << :updated_at unless (options[:include] == :updated_at) || (options[:include].kind_of?(Array) && (options[:include].include? :updated_at))

  options.delete(:include) if options[:include] == :created_at
  options.delete(:include) if options[:include] == :updated_at
  options[:include] -= [:created_at, :updated_at] if options[:include].kind_of?(Array)

  super(options)
end

then use it like

render json: @user
# all except timestamps :created_at and :updated_at

render json: @user, include: :created_at
# all except :updated_at

render json: @user, include: [:created_at, :updated_at]
# all attribs

render json: @user, only: [:id, :created_at]
# as mentioned

render json: @user, include: :posts
# hurray, no :created_at and :updated_at in users and in posts inside users

render json: @user, include: { posts: { include: :created_at }}
# only posts have created_at timestamp

So in your case, your code remains the same

@teams = Team.all
render json: @teams, :include => [:stadiums, :scores, :links, :rounds]

and yeah, you get them all without :created_at and :updated_at. No need to tell rails to exclude that in every single model, hence keeping the code real DRY.

查看更多
登录 后发表回答