![](/img/trans.png)
[英]How can I update my view with sorted lists of movies after button press in Rails?
[英]Rails: How can I incrementally add items to a sorted list in one view
我正在嘗試為音樂家創建一個清單應用程序。 用戶可以上載歌曲曲目,並從這些歌曲列表中選擇歌曲,以填充特定表演的設置列表。
參見圖片: setlist_screenshot 。 單擊左側歌曲上的箭頭圖標,應將歌曲添加到右側的可排序列表中。
有問題的模型:
class Setlist < ActiveRecord::Base
belongs_to :organization
# join between Set Lists & Arrangements(songs)
has_many :items, -> { order(position: :asc) }
has_many :arrangements, through: :items
end
-
class Item < ActiveRecord::Base
# join between Set Lists & Arrangements(songs)
belongs_to :arrangement
belongs_to :setlist
acts_as_list scope: :setlist
end
-
class Arrangement < ActiveRecord::Base
belongs_to :song
belongs_to :organization
has_many :attachments
# join between Set Lists & Arrangements(songs)
has_many :items
has_many :setlists, through: :items
end
基本上,一個清單有很多安排(通過歌曲)到項目(聯接表),而且安排(歌曲)當然可以在許多清單上。
我在視圖中用於添加歌曲的按鈕的代碼是:
<%= link_to(organization_setlists_path(:arrangement_id => song.arrangements.first.id, setlist_id: @new_set.id, remote: true), method: "post", class: "secondary-content" )
這是對setlists控制器的create動作的發布請求(包括針對歌曲的編曲ID和Setlist.new的歌曲的參數,在新動作中進行),如下所示:
class SetlistsController < ApplicationController
before_action :authenticate_user!
def new
if @new_set.nil?
@new_set = Setlist.create
@new_item = Item.new
end
end
def create
@arrangement = Arrangement.find(params[:arrangement_id])
@new_item = Item.new
@new_item.setlist_id = Setlist.find(params[:setlist_id])
@new_item.arrangement_id = @arrangement.id
if @new_item.save
flash[:message] = "Song Sucessfully Added!"
else
flash[:message] = "Something Went Wrong"
end
end
理想情況下,在每次單擊添加/箭頭按鈕之后,我希望為相同的列表創建(遠程)新項,直到用戶完成創建該列表為止。 為了顯示在右側,我有:
<% if @new_set && @new_set.items.count >=1 %>
<ul>
<% @new_set.items.each do |item| %>
<li class="center-align"><%= item.arrangement.title %></li>
<% end %>
</ul>
<% else %>
<p class="center-align">Add Songs From The List On The Left</p>
<% end %>
最終,用戶應該能夠完成該操作,並根據需要繼續創建另一個設置列表。
除了我在這里沒有做的事情之外,我真的不知道該怎么做。 問題是:
首先,創建動作實際上是在創建一個項目,並為新項目分配外鍵用於安排,而不是出於某些原因而不是設置列表,即使從鏈接名稱正確傳遞了設置列表ID也是如此。
另外,每次刷新頁面時,我在新操作中所擁有的內容都會生成一個新的設置列表,因此添加的每個項目都將進入一個設置列表,然后生成一個空白的設置列表,因此右側不會出現任何內容。
最后,這看起來似乎一團糟。 任何人都有更好的設計策略來實現這一目標? 任何幫助將不勝感激!!!
這里的主要問題是您的控制器違反了約定。
當用戶POST到/setlists
時,您的SetlistController
應該創建一個Setlist
。
如果要創建新的子記錄,則可以發布到/setlists/:setlist_id/items
。 這將由ItemsController
處理。
# routes.rb
resources :setlists, shallow: true do
resources :items
end
class ItemsController < ApplicationController
respond_to :html
before_action :find_setlist!, only: [:create, :index]
def create
@item = @setlist.items.build(item_params)
@item.save
respond_with @item
end
# ...
private
def find_setlist!
@setlist = Setlist.includes(:items).find!(params[:setlist_id])
end
def items_params
params.require(:item)
.permit(
:arrangement_id
)
end
end
<% @arrangements.each do |a| %>
<%= button_to 'Add to set', setlist_items_path(@setlist),
arrangement_id: a.id, remote: true
%>
<% end %>
一種替代方法是使用accepts_nested_attibutes_for :items
來使Setlist
也接受項目的參數。
此處的主要區別在於,當將其他項目添加到現有清單時,將使用以下示例:
PATCH /setlist/:id
params: {
item_attributes: [
{
arrangement_id: 2
},
{
arrangement_id: 3
}
]
}
真正的好處是用戶可以執行多個操作(例如添加/刪除),而您只需要將單個setlist推送到數據庫以更新狀態,而不是對每個子記錄使用多個POST / DELETE調用。
class Setlist < ActiveRecord::Base
belongs_to :organization
# join between Set Lists & Arrangements(songs)
has_many :items, -> { order(position: :asc) }
has_many :arrangements, through: :items
accepts_nested_attributes_for :items, allow_destroy: true
end
class SetlistsController < ApplicationController
respond_to :html
before_action :set_setlist, only: [:show, :edit, :update, :destroy]
def new
@setlist = Setlist.new
@setlist.items.build
end
def create
@setlist = Setlist.new(setlist_params)
@setlist.save
respond_with @setlist
end
def update
@setlist.update(setlist_params)
@setlist.items.build
respond_with @setlist
end
# ...
private
def set_setlist
@setlist = Setlist.includes(:items).find(params[:id])
end
def setlist_params
params.require(:setlist)
.permit(
:foo, :bar # attributes for the list
items_attributes: [ :position, :arrangement_id, :_destroy ]
)
end
end
支持此操作的基本表單設置如下所示:
<%= form_for(@setlist) do |f| %>
<%= fields_for :items do |item| %>
<%= item.number_field :postition %>
<%= item.collection_select(:arrangement_id, @setlist.organization.arrangements, :id, :name) %>
<%= item.checkbox :_destroy, label: 'Delete?' %>
<% end %>
<% end %>
當然,這只是一個普通的舊式同步HTML表單-添加AJAX功能和拖放重新排序等有點超出范圍。
請注意,這些解決方案不是排他性的。 您可以輕松地在應用程序中同時擁有兩個選項(嵌套屬性和指定的控制器),這取決於您的要求是否既需要單獨處理子記錄,又或者希望將其作為API的一部分提供。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.