简体   繁体   中英

JSON with full hierarchy in Rails

I have an hierarchical structure in my app:

  • Environment has Containers
  • Container has Items
  • Item has expression

so my Model code looks like:

class Environment < ActiveRecord::Base
  has_many :containers, :dependent => :destroy

  def as_json(options = {})
    super(options.merge(include: :containers))
  end

end

class Container < ActiveRecord::Base
  has_many :items, :dependent => :destroy
  belongs_to :environment

  def as_json(options = {})
    super(options.merge(include: :items))
  end

end

class Item < ActiveRecord::Base
  has_many :expressions, :dependent => :destroy
  belongs_to :container

  def as_json(options = {})
    super(options.merge(include: :expressions))
  end

end

class Expression < ActiveRecord::Base
  belongs_to :item

def as_json(options = {})
  super()
end

end

In a regular get of a record I usually need only one hierarchy below the desired record, that's why in the as_json I merge only one hierarchy down (get Environment will return a collection of containers but those containers will not have Items)

My Question:

Now what I need is to add a method to the controller that allows full hierarchy response ie GET /environment/getFullHierarchy/3 will return: environment with id=3 with all its containers and for every container all it's Items & for every Item all it's expressions. without breaking the current as_json

I'm kinda new to Rails, wirking with Rails 4.2.6 & don't know where to start - can anyone help?

Sure it goes something like this hopefully you get the idea.

EnvironmentSerializer.new(environment) to get the hierarchy json.

lets say environments table has columns environment_attr1 , environment_attr2

class EnvironmentSerializer < ActiveModel::Serializer
  attributes :environment_attr1, :environment_attr2 , :containers

  # This method is called if you have defined a 
  # attribute above which is not a direct value like for
  # a rectancle serializer will have attributes length and width
  # but you can add a attribute area as a symbol and define a method
  # area which returns object.length * object.width
  def containers
     ActiveModel::ArraySerializer.new(object.containers,
           each_serializer: ContainerSerializer)
  end
end

class ContainerSerializer < ActiveModel::Serializer
   attributes :container_attr1, :container_attr2 , :items
   def items
     ActiveModel::ArraySerializer.new(object.items,
        each_serializer: ItemSerializer)
   end
end



   class ItemSerializer < ActiveModel::Serializer
   ... 
   end

   class ExpressionSerializer < ActiveModel::Serializer
   ... 
   end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM