Reputation: 123
I have nested form for my GameDate model and RefereeStat model. They are connected with has_many association. Without nesting, both models are saving. But in nested form, my app won't save them. I suspect that the problem is in form, probably in association with showcase controller, but I can't figure it out.
This is output from console:
Started POST "/game_dates" for 127.0.0.1 at 2016-03-24 20:38:07 +0100 Processing by GameDatesController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"umpbTCZekqIU/g6uVdlde9fSubutgLk0Qrbb0e5GCdn3qj4/C0tmlxl/akxaM1Vmr6v8dNB8b88ATpRN8v1U2g==", "game_date"=>{"date(1i)"=>"2016", "date(2i)"=>"3", "date(3i)"=>"24", "referee_stats_attributes"=>{"0"=>{"games_count"=>"3", "showcase_id"=>"10"}}}, "commit"=>"Create Game date"} User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]] (0.4ms) BEGIN (0.3ms) ROLLBACK Showcase Load (0.8ms) SELECT "showcases".* FROM "showcases" Rendered game_dates/_form.html.haml (22.4ms) Rendered game_dates/new.html.haml within layouts/application (23.9ms)
Rendered layouts/_header.html.haml (0.7ms) Rendered shared/_flash.html.haml (0.2ms) Completed 200 OK in 148ms (Views: 138.5ms | ActiveRecord: 2.2ms)
This is GameDate model:
class GameDate < ActiveRecord::Base
validates :date, presence: true
has_many :referee_stats
accepts_nested_attributes_for :referee_stats, :reject_if => :all_blank
end
Game date controller:
class GameDatesController < ApplicationController
before_action :authenticate_user!
before_action :user_is_admin
def new
@game_date = GameDate.new
@game_date.referee_stats.build
end
def create
@game_date = GameDate.new(game_date_params)
if @game_date.save
redirect_to showcases_path
flash[:success] = "Game date created"
else
render 'new'
end
end
def show
@game_date = GameDate.find(params[:id])
end
def destroy
@game_date = GameDate.find(params[:id]).destroy
redirect_to root_url
flash[:success] = "Game date deleted"
end
private
def game_date_params
params.require(:game_date).permit(:date, referee_stats_attributes: [ :games_count, :showcase_id ])
end
def user_is_admin
unless current_user.admin?
flash[:error] = "You don't have permission to perform this action!"
redirect_to root_url
end
end
end
Referee stat model:
class RefereeStat < ActiveRecord::Base
validates :games_count, presence: true, numericality: {
only_integer: true,
greater_than_or_equal_to: 0 }
validates :showcase_id, presence: true
validates :game_date_id, presence: true
belongs_to :showcase
belongs_to :game_date
end
Form:
.container
.row
.col-md-6.col-md-offset-3
= simple_form_for @game_date do |f|
= f.error_notification
%h2.text-center Game date
= f.input :date
= f.simple_fields_for :referee_stats do |r|
%h3.text-center Referee statistics
= r.input :games_count
= r.association :showcase, label_method: :name, value_method: :id, include_blank: false
= f.button :submit, class: "btn btn-primary btn-sm"
Upvotes: 0
Views: 131
Reputation: 2183
I looked into your git code and found solution :
You are not passing game_date_id from the game_date new form and it failing at game_date_id presence validation and not allowing you to save record so, its better to use association name validation to ensure presence of record.
Actually, presence validator for foreign key don’t care about record existence. It means that you are able to pass game_date_id from form.
Change the following line in referee_stat.rb & it will work for you :
validates :game_date_id, presence: true
replace with
validate :game_date
OR
validates :game_date, presence: true, if: -> {game_date_id.present?}
Validating foreign key and the association itself are explained at this blog.
Upvotes: 1
Reputation: 4049
Currently your referee_stats_attributes
are passed like such:
"referee_stats_attributes"=>{"0"=>{"games_count"=>"3", "showcase_id"=>"10"}}
But they should be passed like this:
"referee_stats_attributes"=>[{"games_count"=>"3", "showcase_id"=>"10"}]
The id "0"
is not needed; Rails magic will auto-create this for you. You only need to pass an id if you're updating, and even then, it should be passed like so:
"referee_stats_attributes"=>[{"id" => 1, "games_count"=>"3", "showcase_id"=>"10"}]
I have not used simple_form_for
so can't comment on the syntax, because it looks OK... but check the HTML output, your <input>
for the child objects should look like this:
<input name="referee_stats[][games_count]" ... />
<input name="referee_stats[][showcase_id]" ... />
Upvotes: 0