我有一個應用程序可以從可用於指定頁面佈局的小部件選擇中創建頁面(稱爲活動頁面)。我正在研究加載和編輯活動頁面內容的功能,更改內容並更新該頁面的相關條目。頁面上特定小部件的順序存儲在名爲page_display_order的列中。頁面顯示順序在整個活動頁面中是唯一的,因爲兩個小部件不能位於頁面上的相同位置。這是在更新頁面時有時會引發錯誤的列。更新嵌套屬性時,Rails作用域唯一性約束會引發錯誤
我爲屬於廣告系列網頁控件模型是這樣的:
class CampaignPagesWidget < ActiveRecord::Base
belongs_to :campaign_page, inverse_of: :campaign_pages_widgets
belongs_to :widget_type
has_one :actionkit_page
validates_presence_of :content, :page_display_order, :campaign_page_id, :widget_type_id
# validates that there are not two widgets with exactly same content on the same campaign page
# and that the page display order integer is unique across the widgets with that campaign page id
validates_uniqueness_of :page_display_order, :content, :scope => :campaign_page_id
end
這是怎樣的小部件數據從頁面請求時在編輯頁面(在campaign_pages_controller.rb)更新讀取。它首先找出它是哪種類型的小部件(存儲在小部件的表格和模型中),然後使用頁面編輯中指定的小部件的內容填充對象,並將其推送到指定嵌套屬性的數組中更新活動頁面時更新:
@campaign_page = CampaignPage.find params[:id]
@widgets = @campaign_page.campaign_pages_widgets
permitted_params = CampaignPageParameters.new(params).permit
widget_attributes = []
params[:widgets].each do |widget_type_name, widget_data|
# widget type id is contained in a field called widget_type:
widget_type_id = widget_data.delete :widget_type
widget = @widgets.find_by(widget_type_id: widget_type_id)
widget_attributes.push({
id: widget.id,
widget_type_id: widget_type_id,
content: widget_data,
page_display_order: i})
i += 1
end
permitted_params[:campaign_pages_widgets_attributes] = widget_attributes
@campaign_page.update! permitted_params.to_hash
redirect_to @campaign_page
在某些情況下這種更新和預期的重定向,在其他時候,它引發以下錯誤:
ActiveRecord::RecordInvalid in CampaignPagesController#update Validation failed: Campaign pages widgets page display order has already been taken, Campaign pages widgets is invalid
我是新來的Ruby和Rails和我將非常感謝關於我可能做錯的建議以及我應該如何做得更好。對於如何做Rails方式我沒有很好的訣竅,我知道我必須重構控制器中的代碼。
更新:僅當存在多個小部件時纔會引發該錯誤。事情工作正常,如果我註釋範圍的唯一性約束。它真正地更新現有的條目而不是創建新條目,所以這不成問題。
謝謝您的解釋!這確實是問題所在。自從我更新小部件以來,我簡單地用'page_display_order:widget.page_display_order'替換了'page_display_order:i'。 –