2015-10-29 25 views
6

我有2個Rails模型:Book and Category,其中一本書belongs_to一個類別,一個類別has_many書籍。在Rails中缺少觸摸選項has_many關係

類別名稱顯示在每本書的頁面中,頁面被緩存。

如果我改變了一個類別名稱(比如說,從'科幻'改爲'科幻小說'),那麼所有相應的書頁都將陳舊,並且需要「觸摸」書本才能觸發HTML重新生成。

這似乎有道理,能夠做到:

class Category << ActiveRecord::Base 
    has_many :books, touch: true 
end 

the option is unavailable,我猜是因爲touch機制將實例化的每個對象,這可能會導致主要性能命中has_many關係。

爲了避免這種情況,我使用原始的SQL語句如下:

class Category << ActiveRecord::Base 
    has_many :books 
    after_update -> { 
    ActiveRecord::Base.connection.execute "UPDATE books SET updated_at='#{current_time_string}' WHERE category_id=#{id})" 
    } 
end 

,這是相當可怕的。 有沒有更好的方法?

回答

5

關於has_many關聯,您不能使用touch,它只適用於belongs_to,這是事實。

如果我正確理解你想要的內容,Book模型中touch:true的答案將不起作用,因爲當您更改Category模型並且視圖不會重新生成時,Book對象將不會更新。

所以我認爲你的解決方案是最好的。 (您也可以使用books.update_all(updated_at: Time.now)

+1

你說得對:1)當類別改變時,我確實需要更改所有書籍; 2)update_all更直接,不實例化模型;直接發送到DB的SQL查詢可避免性能問題。 – Giuseppe

+0

但這會觸發緩存更新? – user1262904

0

在ActiveRecord中實際上有一個觸摸選項用於關係。與你所期望的語法唯一的區別是,它是belongs_to的一個選項:

class Book << ActiveRecord::Base 
    belongs_to :categories, touch: true 
end 

文檔:http://apidock.com/rails/ActiveRecord/Persistence/touch

+1

首先,按照慣例,它應該是「類別」(單數)。當一本書被創建/更改時,會做什麼更新類別,這與我所需要的相反,即當父母更改時觸摸所有的孩子。 – Giuseppe

0

只有在belongs_to方法,它應該在你的本本型號。所以你仍然可以使用它。

+0

Lol,同時回答,其他答案有更好的解釋:)。 –

+0

感謝哥們:p – Caillou