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?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With