5

我寫了一個gem,允許將Google Spreadsheets轉換爲Rails模型。這個過程的順序包括創建所有模型,然後連接它們的關聯,然後保存所有的模型。它支持所有可用的關聯類型,並且在任何情況下都可以禁止一個,創建模型,建立關聯,然後保存模型正常工作。唯一的例外是:通過使用未保存的模型建立一個通過vs有很多

我有一個簡單has_one, through協會(屬性訪問略去了):

class Left < ActiveRecord::Base 
    has_many :middles, dependent: :destroy 
    has_many :rights, through: :middles 
end 

class Right < ActiveRecord::Base 
    has_one :middle, dependent: :destroy 
    has_one :left, through: :middle 
end 

class Middle < ActiveRecord::Base 
    belongs_to :left 
    belongs_to :right 
end 

我發現一些不一致的行爲取決於哪一方是由該協會的任務:

分配從右至左:

left = Left.new 
right = Right.new 
left.rights << right 
left.middles #[] 
right.middle #nil 
left.save! 
left.middles # <Middle theme_id: 1, archive_resource_id: 1 > 

分配從右至左:

left = Left.new 
right = Right.new 
right.left = left 
left.middles #[] 
right.middle <Middle theme_id: nil, archive_resource_id: nil > 
right.save! 
right.middle # <Middle theme_id: nil, archive_resource_id: 1 > 

這種行爲似乎很不一致。爲什麼是這樣?爲什麼這種方式工作而不是其他方式?有沒有辦法與兩個未保存的記錄建立這種關係?

我明白,顯而易見的解決方案是建立關係之前保存一切,但如上所述,我需要的車型當協會建立,而在所有其他類型的關聯,那裏是未保存在這方面沒有問題。

+0

如果'''Left'''和'''Right'''車型也從'''的ActiveRecord ::繼承基地'''? 爲什麼'''左'''''has_many:right'''?也許它應該是'''has_many:rightS'''或'''has_one:right'''? – freemanoid

+0

@freemanoid對不起,是的,他們是(修正問題)。 – Undistraction

+2

'''has_many:middleS'''和'''has_many:rightS''' – freemanoid

回答

-1

我認爲這可能是工作,但不立即更新。當您調用您的關聯方法時,請嘗試通過true。防爆。 right.middle(true)。這將迫使Rails返回到數據庫來獲取記錄,而不是檢查緩存,這是陳舊的。儘管如此,不要在新記錄上做這件事,因爲你會在內存中吹走關聯的對象。

爲了避免強制重裝,設置你的協會inverse_of

class Left < ActiveRecord::Base 
    has_many :middles, dependent: :destroy, inverse_of: :left 
    has_many :rights, through: :middles 
end 

class Right < ActiveRecord::Base 
    has_one :middle, dependent: :destroy, inverse_of: :right 
    has_one :left, through: :middle 
end 

class Middle < ActiveRecord::Base 
    belongs_to :left, inverse_of: :middles 
    belongs_to :right, inverse_of: :middle 
end 

inverse_of使得model知道相關的模型對自身的關係,這使得它成爲「智能」關於堅持和加載關聯對象。

+0

不幸的是''通過'關聯不支持'inverse_of':參見:http://stackoverflow.com/questions/7436173/activerecord-inverse-of-does-not-work-on-has-many-through- on-the-join-model-on – Undistraction

+0

呃,是的。抱歉。天色已晚。 – Kaleidoscope

+0

沒問題。投票下來,所以很明顯這個答案是不正確的。 – Undistraction

0

按照Rails的API文檔(link) -

如果您正在使用的連接模型belongs_to的,這是一個好主意, 設置:inverse_of選項上belongs_to的,這將意味着該 下面的例子可以正常工作(其中電子標籤是一種的has_many:通過 協會):

因此該協會成立了由@Kaleidoscope是逸岸正確的。

+0

也許這是真的,如果你正在使用'build',但正如問題中所概述的,我沒有使用'build',而是'new',然後''save'。 @萬花筒的回答不正確,因爲他在另一方向使用了'inverse_of':'has_one:middle,dependent::destroy,inverse_of::right' – Undistraction

0

我認爲它沒有工作,因爲你有

的has_many - HAS_ONE

左派之間的權利,而不是

的has_many關係 - belongs_to的

另一方面

belongs_to的:左,通過:中間

是不可能的。所以,你應該使用委託getter和都由你自己寫setter方法,像這樣

class Right < ActiveRecord::Base 
    has_one :middle, dependent: :destroy 
    delegate :left, to: :middle 

    def left=(left) 
    #logic 
    end 
end 
+0

使用'has_many,through'或'has_one, through'?兩者都有明確的記錄。 – Undistraction