1

假設以下關係:如何使Rails/ActiveRecord在使用as_json時包括在內?

Blog的has_many Posts的has_many Comments HAS_ONE Author

如果我要得到所有Blogs所有Posts,我可以這樣寫:

Blog.all.as_json(:include => :posts) 

然而,這將導致N + 1查詢。

所以不是我需要寫:

Blog.includes(:posts).all.as_json(:include => :posts) 

預期其中一期工程,但不是很乾,尤其是當你有嵌套包括。

例如:

Blog.includes(
    :posts => { 
     :comments => :author 
    } 
).all.as_json(
    :include => { 
     :posts => { 
      :include => { 
       :comments => { 
        :include => :author 
       } 
      } 
     } 
    } 
) 

,當我需要查詢在多個地點此相同的JSON格式,這個問題變得更糟。

我想過把as_json關係格式類方法,像這樣:

class Blog < ActiveRecord::base 
... 
    def self.include_all_json_format 
    :include => { 
     :posts => { 
      :include => { 
       :comments => { 
        :include => :author 
       } 
      } 
     } 
    } 
    end 
... 
end 

解決了查詢多個位置的這個JSON格式的問題,因爲我可以那麼就使用:

Blog.includes(
    :posts => { 
     :comments => :author 
    } 
).all.as_json(
    Blog.include_all_json_format 
) 

但當然Blog.includes()需要爲它關係哈希不同的格式,所以這樣的:

Blog.includes(
    Blog.include_all_json_format 
).all.as_json(
    Blog.include_all_json_format 
) 

不起作用。

我可以把Blog.includes()關係散列放在第二個類方法中,但是有兩個方法聲明相同包含結構不是DRY。


我現在能想到的是使用上述Blog.include_all_json_format方法,然後編寫可以反過來說,關係散列到通過Blog.includes()期望的格式(轉換器方法的唯一想法基本上只是剝出:include鍵),所以它可以被稱爲:

Blog.includes(
    MyConverter(Blog.include_all_json_format) 
).all.as_json(
    Blog.include_all_json_format 
) 

但後來情況就變得複雜時,我想在我的as_json格式使用:only:except


我該如何幹這些包括起來,最好只聲明關係格式一次?

也許有一些方法來使用命名的範圍或一些寶石?

任何幫助,非常感謝。

+0

你可以嘗試[deep_pluck](https://github.com/khiav223577/deep_pluck)來烘乾它。 – 2017-03-30 13:24:01

回答

0

可以重寫as_json方法模型

例如

class Blog < ActiveRecord::Base 

    def as_json 
    super(:include => :posts) 
    end 
end 

那麼你的控制器看起來應該像

render json: @blogs

建議

您可以使用JBuilder,Rabl,AMS或其他模板庫,以便將響應構建在控制器/模型邏輯之外。這樣做肯定會幹掉你的代碼。

+0

感謝您的回覆。重寫'as_json'將與Blog.all.as_json(:include =>:posts)相同,但是,是正確的?因此仍然會產生低效率的N + 1查詢。我會檢查這些圖書館,謝謝。 – Marc 2013-03-09 20:47:32

+0

我認爲整個問題是,你應該從你的控制器邏輯中分離你的「視圖」模板。就像'@blog = Blog.includes(:posts).all'然後'render json:@ blog'一樣,不用調用as_json,但仍然按照我向你展示的方式覆蓋它,將會幹掉它並防止N + 1查詢。 – 2013-03-09 21:23:37