给定索引值,如何在Rails控制器中仅更新这些值?



我有一个嵌套的表单,如下所示,我希望使用一个复选框来记录我想要更新的记录。我已经检查了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 %>

相关内容

  • 没有找到相关文章

最新更新