我有一个嵌套的表单,如下所示,我希望使用一个复选框来记录我想要更新的记录。我已经检查了html,我正在为每条记录注册正确的索引。示例属性和复选框的html如下所示:
<input id="game_game_rosters_attributes_0_game_id" name="game[game_rosters_attributes][0][game_id]" type="hidden" value="127">
<input id="add_0" name="add[0]" type="checkbox" value="false">
现在,我认为我应该通过检查具有相同索引的复选框是否具有"true"的值来确定我想要更新的game_roster_attributes
。但我不确定如何在我的games_controller中做到这一点。rb,因为它目前被设置为质量分配我的attr_accessible变量与@game.update_attributes()
…
games_controller.rb
def update
@game = Game.find(params[:id])
respond_to do |format|
if @game.update_attributes(params[:game])
format.html { redirect_to @game, notice: 'Game was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit"}
format.json { render json: @game.errors, status: :unprocessable_entry }
end
end
end
嵌套形式
<%= form_for @game do |f| %>
# @game fields for editing here...
<% roster_options.each.with_index do |option, index| %>
<%= f.fields_for :game_rosters, option do |fields| %>
<%= fields.object.player.full_name %>
<%= fields.hidden_field :player_id %>
<%= fields.hidden_field :game_id %>
<%= check_box_tag 'add[' + index.to_s + ']', false %>
<% end %>
<% end %>
<% end %>
game.rb
class Game < ActiveRecord::Base
attr_accessible :date, :game_rosters_attributes
has_many :game_rosters
has_many :players, :through => :game_rosters
accepts_nested_attributes_for :game_rosters, allow_destroy: true
end
game_roster.rb
class GameRoster < ActiveRecord::Base
attr_accessible :active, :winner, :player_id, :game_id, :placement
belongs_to :game
belongs_to :player
end
game_controller.rb
def new
@game = Game.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @game }
end
end
def edit
@game = Game.find(params[:id])
@game_roster = GameRoster.joins(:player).where(game_id: params[:id]).order('winner DESC, placement DESC')
@options = SeasonRoster.where("season_id = (?) AND NOT EXISTS ( SELECT * FROM game_rosters INNER JOIN games ON games.id = game_rosters.game_id WHERE game_rosters.player_id = season_rosters.player_id AND games.id = (?))", @game.season_id.to_s, @game.id.to_s)
@roster_options = Array.new
@options.each do |o|
c = GameRoster.new
c.player_id = o.player_id
c.challenge_id = params[:id]
c.winner = false
@roster_options.push(c)
end
end
我不确定你的要求。我假设您只想保存那些选中"add"字段的花名册,并删除其余的花名册。
roster.rb
class Roster < ActiveRecord::Base
attr_accessor :add
end
game.rb
class Game < ActiveRecord::Base
before_save :mark_rosters_for_removal
def mark_rosters_for_removal
rosters.each do |roster|
unless roster.add
roster.mark_for_destruction
end
end
end
end
嵌套形式<%= form_for @game do |f| %>
# @game fields for editing here...
<% roster_options.each.with_index do |option, index| %>
<%= f.fields_for :game_rosters, option do |fields| %>
<%= fields.object.player.full_name %>
<%= fields.hidden_field :player_id %>
<%= fields.hidden_field :game_id %>
<%= fields.check_box :add, false %>
<% end %>
<% end %>
<% end %>
我会使用before_save并使用params散列来检查复选框是否被选中。然后使用.delete方法删除参数散列的那一部分。然后@game.update_attributes()
将只更新仍然在散列中的花名册(谁的复选框被选中)。
嵌套形式
<%= form_for @game do |f| %>
# @game fields for editing here...
<% roster_options.each.with_index do |option, index| %>
<%= f.fields_for :game_rosters, option do |fields| %>
<%= fields.object.player.full_name %>
<%= fields.hidden_field :player_id %>
<%= fields.hidden_field :game_id %>
<%= check_box_tag :add, false %> #Notice change!!!!!
<% end %>
<% end %>
<% end %>
game.rb
class Game < ActiveRecord::Base
before_save :check_for_deletion
...
def check_for_deletion
index = 0
roster = params[:game][:game_rosters_attributes]
while !roster["#{index.to_s}"].nil?
if roster["#{index.to_s}"][:add] == "true" # Or "checked" or whatever. I forget the actual value
roster.delete "#{index.to_s}"
end
index += 1
end
end
end
你可能需要根据你的params哈希值来做一些调整。我已经尽力想明白了。我也不是100%的"#{index。To_s}"可以工作(或者它甚至可能是多余的)。但这应该给你一个良好的开端。
似乎你正在添加所有玩家到游戏中,然后在更新时删除他们,如果"添加"未选中。
如果是这种情况,那么你可以为_destroy添加一个复选框,它将为你处理,就像你在game.rb中的game_rosters中添加了"allow_destroy: true"标志一样。
注意,它现在是一个"删除"复选框,而不是一个"添加"复选框。
嵌套形式:<%= form_for @game do |f| %>
# @game fields for editing here...
<% roster_options.each.with_index do |option, index| %>
<%= f.fields_for :game_rosters, option do |fields| %>
<%= fields.object.player.full_name %>
<%= fields.hidden_field :player_id %>
<%= fields.hidden_field :game_id %>
<%= fields.check_box :_destroy, false %>
<% end %>
<% end %>
<% end %>
来自Rails嵌套表单指南:
"不要忘记更新控制器中的白名单参数,使其包含_destroy字段"
http://guides.rubyonrails.org/form_helpers.html nested-forms
因此,在花了一些时间离开问题并回到它之后,我找到了一个足够简单的解决方案。我最终只是反转了我在此期间一直使用的:_destroy复选框。
<%= fields.check_box :_destroy, {}, '0', '1' %>
基本上,我只是颠倒了复选框通常表示的值。您可以在下面看到我编辑嵌套表单以使用此方法的地方。
嵌套形式<%= form_for @game do |f| %>
# @game fields for editing here...
<% roster_options.each.with_index do |option, index| %>
<%= f.fields_for :game_rosters, option do |fields| %>
<%= fields.object.player.full_name %>
<%= fields.hidden_field :player_id %>
<%= fields.hidden_field :game_id %>
<%= fields.check_box :_destroy, {}, '0', '1' %>
<% end %>
<% end %>
<% end %>