Player.rb
class Player < ApplicationRecord
belongs_to :user
has_many :player_games, dependent: :destroy, inverse_of: :player
has_many :games, :through => :player_games
validates :firstname, presence: true, length: { minimum: 3, maximum: 88 }
validates :lastname, presence: true, length: { minimum: 3, maximum: 88 }
validates :user_id, presence: true
accepts_nested_attributes_for :player_games, reject_if: :reject_posts, allow_destroy: true
def reject_posts(attributes)
attributes['game_id'].to_i == 0
attributes['score'].blank?
attributes['time'].blank?
end
def initialized_player_games # this is the key method
[].tap do |o|
Game.all.each do |game|
if g = player_games.find { |g| g.game_id == game.id }
o << g.tap { |g| g.enable ||= true }
else
o << PlayerGame.new(game: game)
end
end
end
end
end
players_controller.rb
class PlayersController < ApplicationController
before_action :set_player, only: [:edit, :update, :show, :destroy]
before_action :require_user, except: [:index, :show]
before_action :require_same_user, only: [:edit, :update, :destroy]
before_filter :process_player_games_attrs, only: [:create, :update]
def process_player_games_attrs
params[:player][:player_games_attributes].values.each do |game_attr|
game_attr[:_destroy] = true if game_attr[:enable] != '1'
end
end
.......Рельсы has_many: через, кокон
private
# Use callbacks to share common setup or constraints between actions.
def set_player
@player = Player.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def player_params
params.require(:player).permit(:id, :firstname, :lastname, player_games_attributes: [:id, :game_id, :score, :time, :enable, :_destroy])
end
def require_same_user
if current_user != @player.user and !current_user.admin?
flash[:danger] = "You can edit or delete only your own player"
redirect_to root_path
end
end
end
_form из 'ИГРОК'
<%= form_for(@player, :html => {class: "az-form", role: "form"}) do |player_form| %>
<%= player_form.label :firstname, class: "az-form__label" %> <br/>
<%= player_form.text_field :firstname, class: "az-form__input", placeholder: "Firstname of player", autofocus: true %>
<%= player_form.label :lastname, class: "az-form__label" %> </br>
<%= player_form.text_field :lastname, class: "az-form__input", placeholder: "Lastname of player" %>
<%= player_form.fields_for :player_games, @player.initialized_player_games do |builder| %>
<% @game = builder.object.game %>
<%= render 'result_fields', f: builder %>
<div class="links">
<%= link_to_add_association 'add result', player_form, :player_games, :partial => 'players/result_fields' %>
</div>
<hr>
<% end %>
<div class="text-center">
<%= button_tag(type: "submit", class: "az-form__submit") do %>
<%= player_form.object.new_record? ? "Create player" : "Update player" %>
<% end %>
</div>
<% end %>
_result_fields.html.erb
<div class="nested-fields">
<%= f.hidden_field :game_id, :value => @game.id%>
<div class="row">
<div class="col-md-12">
<label class="az-form__label az-form__label--unable js-az-form__checkbox" data-check="<%= @game.id %>">
<%= f.check_box :enable %>
<%= @game.title %>
</label>
</div>
</div>
<div class="row">
<div class="col-md-6">
<%= f.label :score,
class: "az-form__label", :data => {:check => @game.id } %> </br>
<%= f.number_field :score, step: :any, :data => {:check => @game.id },
class: "az-form__input az-form__input--disabled",
placeholder: "Score for '#{@game.title}'", disabled: true %>
</div>
<div class="col-md-6">
<%= f.label :time,
class: "az-form__label", :data => {:check => @game.id } %> </br>
<%= f.number_field :time, step: :any, :data => {:check => @game.id },
class: "az-form__input az-form__input--disabled",
placeholder: "Time for '#{@game.title}'", disabled: true %>
</div>
</div>
<div class="row">
<div class="col-md-12">
<%= link_to_remove_association "remove result", f %>
</div>
</div>
</div>
Вопрос:
Когда редактировать «игрок» имеют доступ только один результат за игру, не может изменить других, конфликт с методом «initialized_player_games», но если я удалить этот метод из формы работает хорошо, но не может создать другую игру, если не создавать в новом действии, как я могу правильно изменить этот метод?
Ваш метод работает отлично, теперь я пытаюсь перестроить форму с помощью 'sample_form', кстати у меня есть ошибка на 'f.collection_select: game_id, Game.all.map {| g | [g.name, g.id]} '->' Неверное количество аргументов ', поэтому я удалил этот оператор if, и он работает сейчас –
Я написал этот код в качестве примера, не тестировал его. Я исправил определение 'collection_select'. Если вам вообще не нужно устанавливать игру, вам не нужен выбор, мне казалось, что это действительно важно, чтобы выбрать игру, для которой нужно добавить счет. Но это был всего лишь пример (и вы могли бы использовать любой из альтернативных способов создания опции выпадающего списка). – nathanvda