Hi the serailizer in my application looks like this
class ProgressSerializer < ActiveModel::Serializer
attributes :id
has_one :race
end
class RaceSerializer < ActiveModel::Serializer
attributes :id
has_many :progresses
end
The has_one and has_many together gives me error stack level too deep.
Things I tried.
config/initializers/active_model_intializer.rb
ActiveModel::Serializer.setup do |config|
config.embed = :ids
config.include = true
end
Second thing I tried
class RaceSerializer < ActiveModel::Serializer
attributes :id
has_many :progresses , :serializer => ProgressSerializer
end
class ProgressSerializer < ActiveModel::Serializer
attributes :id
has_one :race , :serializer => RaceSerializer
end
Models
class Progress < ActiveRecord::Base
belongs_to :race
end
class Race < ActiveRecord::Base
has_many :progresses
end
Can you share your Model.rb files?
If Progress is main then Races underneath, this one should work.
class ProgressSerializer < ActiveModel::Serializer
attributes :id, :races
has_many :races
end
class RaceSerializer < ActiveModel::Serializer
attributes :id
end
then try to delete has_many :progresses and add has_one :race to Race with attributes :id, :race
Related
I am using Rails 5.0.1, and am really confused about the following problem. I have few models with polymorphic associations.
class Container < ApplicationRecord
has_many :steps, as: 'parent', dependent: :destroy
end
class Step < ApplicationRecord
belongs_to :parent, polymorphic: true
belongs_to :implementation, polymorphic: true
end
class FirstStep < ApplicationRecord
has_one :step, as: 'implementation'
has_many :params, dependent: :destroy
end
class SecondStep < ApplicationRecord
has_one :step, as: 'implementation'
has_many :headers, dependent: :destroy
end
class Param < ApplicationRecord
belongs_to :first_step
end
class Header < ApplicationRecord
belongs_to :second_step
end
A step associates to an implementation (FirstStep, SecondStep). In addition to it, a container can also be a step's implementation. I'm using Active Model Serializers to serialize the model info to JSON. Following is the related code to serializers.
class StepSerializer < ActiveModel::Serializer
attributes :id, :implementation_type, :implementation_id, :active, :position
belongs_to :implementation
end
class FirstStepSerializer < ActiveModel::Serializer
attributes :name, :params_attributes
def params_attributes
object.params.map { |p| ParamSerializer.new(p).attributes }
end
end
class SecondStepSerializer < ActiveModel::Serializer
attributes :id, :title, :headers_attributes
def headers_attributes
object.headers.map { |p| HeaderSerializer.new(p).attributes }
end
end
class ParamSerializer < ActiveModel::Serializer
attributes :id
end
class HeaderSerializer < ActiveModel::Serializer
attributes :id
end
The implementations of step model can have different attributes, as specified in the model. The problem is, when I write
render json: container.steps
it fires N+1 queries to get the results. How do I optimize it?
Edit 1
Inspired by this answer, I tried to separate objects by their implementation_type, and it worked. What I did was:
# my controller action
def index
steps = []
steps += container.steps.where(implementation_type: 'FirstStep').includes(implementation: [:params])
steps += container.steps.where(implementation_type: 'SecondStep').includes(implementation: [:headers])
render json: steps
end
This prevented the N+1 queries for fetching params and headers, but it doesn't work if a step is a container.
Change your FirstStepSerializer and SecondStepSerializer serializer like following
class FirstStepSerializer < ActiveModel::Serializer
attributes :name
has_many :params, :serializer => ParamSerializer
end
class SecondStepSerializer < ActiveModel::Serializer
attributes :id, :title
has_many :headers, :serializer => HeaderSerializer
end
This might help
I have the following relationships (using RoR 3.2.13 and ancestry 2.0.0) and REALLY need some help in configuring how the serializer renders with the MenuHeaderSerializer:
class Menu < ActiveRecord::Base
has_many :menu_headers
end
class MenuHeader < ActiveRecord::Base
has_ancestry # the nested relationship
has_many :items
belongs_to :menu
end
class Item < ActiveRecord::Base
belongs_to :menu_header
end
My serializers are pretty explanatory and look like this:
class MenuSerializer < ActiveModel::Serializer
attributes :id, :name, :menu_headers
has_many :menu_headers
end
class MenuHeaderSerializer < ActiveModel::Serializer
attributes :id, :name, :children # <- this needs to be called and wrapped in a MenuHeaderSerializer; it basically just dumps eveything like to_json
#has_many :items
end
So my call to children should return children using MenuHeaderSerializer. Does that make sense?
I have tried what I think are all of the variations like the following:
class MenuHeaderSerializer < ActiveModel::Serializer
attributes :id, :name, :sub # :children #, :sub
def sub
MenuHeaderSerializer.new(children)
#object.children
end
or trying to force children into using the MenuHeaderSerializer but am just at a loss. Any help would be appreciated.
Perhaps something like:
attributes :id, :name, :children serializer: MenuHeaderSerializer # doesn't work
thx
not sure about Ancestery but you can do
has_many :children, each_serializer: MenuHeaderSerializer
This question pertains to AMS 0.8
I've got two models:
class Subject < ActiveRecord::Base
has_many :user_combinations
has_ancestry
end
class UserCombination < ActiveRecord::Base
belongs_to :stage
belongs_to :subject
belongs_to :user
end
And two serializers:
class UserCombinationSerializer < ActiveModel::Serializer
attributes :id
belongs_to :stage
belongs_to :subject
end
class SubjectSerializer < ActiveModel::Serializer
attributes :id, :name, :description, :subjects
def include_subjects?
object.is_root?
end
def subjects
object.subtree
end
end
When a UserCombination is serialized, I want to embed the whole subtree of subjects.
When I try to use this setup I get this error:
undefined method `belongs_to' for UserCombinationSerializer:Class
I tried changing the UserCombinationSerializer to this:
class UserCombinationSerializer < ActiveModel::Serializer
attributes :id, :subject, :stage
end
In this case I get no errors, but the subject is serialized in the wrong way - not using the SubjectSerializer.
My questions:
Shouldn't I be able to use a belongs_to relation in the serializer?
If not - how can I get the wanted behaviour - embedding the subject tree using the SubjectSerializer?
This is not really elegant but it seems to be working :
class UserCombinationSerializer < ActiveModel::Serializer
attributes :id, :stage_id, :subject_id
has_one :subject
end
I don't really like calling has_one whereas it's actually a belongs_to association :/
EDIT: Disregard my comment about has_one/belongs_to ambiguity, the doc is actually pretty clear about it: http://www.rubydoc.info/github/rails-api/active_model_serializers/frames
In Active Model Serializer 0-10-stable, belongs_to is now available.
belongs_to :author, serializer: AuthorPreviewSerializer
belongs_to :author, key: :writer
belongs_to :post
belongs_to :blog
def blog
Blog.new(id: 999, name: 'Custom blog')
end
https://github.com/rails-api/active_model_serializers/blob/0-10-stable/docs/general/serializers.md#belongs_to
So you could do:
class UserCombinationSerializer < ActiveModel::Serializer
attributes :id
belongs_to :stage, serializer: StageSerializer
belongs_to :subject, serializer: SubjectSerializer
end
What if you try with something like this:
class UserCombinationSerializer < ActiveModel::Serializer
attributes :subject,
:stage,
:id
def subject
SubjectSerializer.new(object.subject, { root: false } )
end
def stage
StageSerializer.new(object.stage, { root: false } )
end
end
I'm somewhat confused by my options for custom validations in Rails 3, and i'm hoping that someone can point me in the direction of a resource that can help with my current issue.
I currently have 3 models, vehicle, trim and model_year. They look as follows:
class Vehicle < ActiveRecord::Base
attr_accessible :make_id, :model_id, :trim_id, :model_year_id
belongs_to :trim
belongs_to :model_year
end
class ModelYear < ActiveRecord::Base
attr_accessible :value
has_many :model_year_trims
has_many :trims, :through => :model_year_trims
end
class Trim < ActiveRecord::Base
attr_accessible :value, :model_id
has_many :vehicles
has_many :model_year_trims
has_many :model_years, :through => :model_year_trims
end
My query is this - when I am creating a vehicle, how can I ensure that the model_year that is selected is valid for the trim (and vice versa)?
you can use custom validation method, as described here:
class Vehicle < ActiveRecord::Base
validate :model_year_valid_for_trim
def model_year_valid_for_trim
if #some validation code for model year and trim
errors.add(:model_years, "some error")
end
end
end
You can use the ActiveModel::Validator class like so:
class VehicleValidator < ActiveModel::Validator
def validate(record)
return true if # custom model_year and trip logic
record.errors[:base] << # error message
end
end
class Vehicle < ActiveRecord::Base
attr_accessible :make_id, :model_id, :trim_id, :model_year_id
belongs_to :trim
belongs_to :model_year
include ActiveModel::Validations
validates_with VehicleValidator
end
I have 3 associated models:
class Brand < ActiveRecord::Base
has_many :car_models
end
class CarModel < ActiveRecord::Base
has_many :production_years
belongs_to :brand
end
class ProductionYear < ActiveRecord::Base
belongs_to :car_model
end
So, how i can make custom filter in ActiveAdmin production_year section, if i want make filtering by Brand? Default filters there: car_model select and year value
Did you try something like this?
ActiveAdmin.register ProductionYear do
filter :brand, :as => :check_boxes, :collection => proc { Brand.all }
end
EDIT oops I didn't notice the complexity of your association, I think if you add this to your ProductionYear class things should work better:
class ProductionYear < ActiveRecord::Base
belongs_to :car_model
has_one :brand, :through => :car_model
end