I have this code that brings one vacancy from my model Vacancy and then render in json the attributes according to the serializer VacancyDetailSerializer:
Controller
vacancy = Vacancy.find(params[:id])
render json: vacancy, serializer: VacancyDetailSerializer,
include: [:restaurant]
The thing here is that in the include: [:restaurant] I want to specify a custom serializer the way I did with vacancy, because right now is taking the serializer of RestaurantSerializer, but I don't want to take that file, is there a way to do it with the include? Maybe is here in the controller, or maybe in the serializer?
If you have belongs_to :restaurant association in the VacancyDetailSerializer, then serializer for this association can be specified:
class VacancyDetailSerializer < ActiveModel::Serializer
belongs_to :restaurant, serializer: AnotherRestaurantSerializer
end
Or it can be overridden by providing a block:
class VacancyDetailSerializer < ActiveModel::Serializer
belongs_to :restaurant do
AnotherRestaurantSerializer.new(object.restaurant)
end
end
Or a custom association serializer lookup can be implemented.
Related
I'm a newbie in ruby and I'm stuck on this strange error.
I'm getting stack level too deep when ever I hit this controller although only one of my object has a serializer.
I have got the following controller
def get_class
#class_sections = ClassSection.all
#class_sections = ClassSection.filter_by_class(#class_section.school_class.id).limit(nil)
if #class_sections.present?
render json: {
class_sections: ActiveModel::Serializer::CollectionSerializer.new(#class_sections, each_serializer: AdminClassSectionSerializer),
class: #class_section.class
}
else
render json: {message: "no Class Section found", status: 400}, status: 400
end
end
My Serializer:
class AdminClassSectionSerializer < ActiveModel::Serializer
attributes :id, :section, :faculty
belongs_to :faculty
belongs_to :section
end
class, faculty and section don't have a serializer but still it is giving me stack level too deep. Am I missing something here?
I am working on a backend of an application written in Sinatra.
It has a route "/notifications"
which renders all the notifications in JSON.
I want to change the json structure and wrote some custom serializer and it is failing now.
the error i get is
"{"message":"undefined method `read_attribute_for_serialization' for nil:NilClass"}"
I have a file called webservice/notification.rb
which selects a notification serializer.
the code is something like this
serializer = NotificationSerializer
json serialize(notifications, root: :notifications, each_serializer: serializer)
The NotificationSerializer is something like this.
class NotificationSerializer < Serializer
attributes :id, :tag, :event, :time, :read
has_one :reference, polymorphic: true, include: true
The reference here can be a lot of things.
the notification model defines reference as
def reference
company || contact || deal || invitation || meeting || todo || reference_email || reference_user ||
contact_import_job
end
now all of these models in reference have there Serializer implements in directory Serializer/*
I want to make custom Serializers for all of these which will render limited information.
how can I call my custom Serializer for things inside reference.
I wrote a custom serializer for notifications and called it like this inside my refernce function and it worked.
...|| UserNotificationSerializer.new(reference_user) || ...
but if i do the same for my other models i get the error given above.
what would be the correct way to call my custom serializers.
A good way to do it is to write an instance method on the model:
class Notification < ActiveRecord::Base
def public_attributes # or call it whatever
attributes_hash = attributes
# in activerecord, the attributes method turns a model instance into a hash
# do some modifications to the hash here
return attributes_hash
end
end
then say you're returning json in a controller:
get '/some_route' do
#notifications = Notification.all # or whatever
serialized_notifications = #notifications.map(&:public_attributes)
# For a single record, you could do #notification.public_attributes
json_data = serialized_notifications.to_json # a serialized array of hashes
content_type :json
return json_data
end
I'm very new to ruby and can not understand this situation.
I'm using active_model_serializers to generate model and serializer.
Now after runing
$ rails g resource post title:string body:string
two files was generated.
app/model/post.rb
app/serializers/post_serializer.rb
So far so good.
But why is the model object (post.rb) empty and has no properties?
class Post < ActiveRecord::Base
end
And why the serializer object contains the properties I defined for a model object? I mean serializer -> component which DO serialization
class PostSerializer < ActiveRecord::Base
attributes :id, :title, :body
end
As per documentation in Active Model serializers
The attribute names are a whitelist of attributes to be serialized.
Active Model serializers are means to selectively transform your model into JSON as per API needs, instead of emitting all the attributes of the Active Model model.
Hence, the attributes are explicitly listed in Active Model Serializer classes
I'm trying to migrate an old database using DataMapper and I am having an issue with a many to many relation.
I have a Post and Tag model that both go through an anonymous resource. I can set the repository name in the post and tag models, but not the auto-generated PostTag model (as far as I know). Is there a way to make all of them use the same repository name (:legacy)?
Cheers,
Tom
You can just create a normal DM model for the "middle" resource to be able to define the repository name, such as
model PostTag
include DataMapper::Resource
def self.default_repository_name; :legacy end
belongs_to :post, :key => true
belongs_to :tag, :key => true
end
and in both of those parents, define the connection with a :through. For example,
model Post
# other definitions ...
has n, :post_tags
has n, :tags, :through => :post_tags
end
I want to implement before_validaton callback in a separate class so that it can be reused by multiple model classes.
Here in callback i want to strip field passed as parameter but i am not sure how to pass parameter to callback class. Also i want to pass this as reference rather than by value(not sure if this concept is in Ruby Rails). I am following the link http://guides.rubyonrails.org/active_record_validations_callbacks.html#callback-classes
Here is code which is not completely correct, please help for same
class StripFieldsCallback
def self.before_validation(field)
field = field.strip
end
end
class User < ActiveRecord::Base
validates_uniqueness_of :name, :case_sensitive => false
validates_length_of :name, :maximum => 50
before__validation StripFieldsCallback(name)
end
If i define method in model in itself rather than defining in separate callback class code is like this (which works fine)
class User < ActiveRecord::Base
validates_uniqueness_of :name, :case_sensitive => false
validates_length_of :name, :maximum => 50
before__validation :strip_blanks
protected
def strip_blanks
self.name = self.name.strip
end
end
Of course it is not good to replicate methods in all of models so i want to define method in callback classes.
You may do this or use normalize_attributes gem
module StripFieldsCallback
def before_validation_z(field)
write_attribute(field, read_attribute(field).strip) if read_attribute(field)
end
end
class User < ActiveRecord::Base
include StripFieldsCallback
before_validation lambda{|data| data.before_validation_z(:name)}
end