2016-06-13 49 views
1

我在我的應用程序有一個層次結構完整的層次:JSON在Rails的

  • 環境具有集裝箱
  • Container都有項目
  • 項目已表達

所以我的模型代碼看起來如:

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 

定期得到一個記錄我通常只需要一個層次低於所需的記錄,這就是爲什麼在as_json我合併只有一個層次結構(獲取環境將返回一個容器的集合,但這些容器將不具有項目)

我的問題:

現在我需要的是一個方法添加到控制器,允許即GET /environment/getFullHierarchy/3完整的層次響應將返回:環境ID = 3的所有容器和每一個容器中的所有它是每個項目&將所有它的表達式沒有打破目前as_json

我有點新的Rails,用Rails敲詐4.2.6 &不知道從哪裏開始 - 任何人都可以幫忙嗎?

+1

嘗試https://github.com/rails-api/active_model_serializers – sethi

+0

感謝@sethi,能否請您解釋一下我如何使用這個寶石?文檔沒有明確指出,你可以在我的示例中顯示這一點嗎? – yossico

回答

2

當然,它會像這樣,希望你有這個想法。

EnvironmentSerializer.new(environment)獲取層次結構json。

可以說,環境表中的列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 
+0

這顯然可以寫得更好 – sethi

+1

你也可以用'has_many:containers,serializer:ContainerSerializer'和'has_many:items,serializer:ItemSerializer'替換'containers'和'items'方法。我相信這會有相同的效果,並且會更加活躍一些ActiveModelSerializer-ish。 – Dan

+0

這看起來非常有希望,但我怎樣才能保持我原來的行爲 - 當調用index時 - 只會沿着平行線回退一級,控制器如何看待這兩個序列化器? – yossico