title: Rails 4: issues with strong parameters and passing data
body: <p>Good day, community.</p>
  
  <p>First of all, I'm a newbie in Rails. I did some thing with it in College 4 years ago, and now I decided to get back on it. Lots of things changed in version 4.</p>
  
  <p>Anyway, I am experiencing issues with strong parameters. Here's what I have:</p>
  
  <p>I'm using Ruby 2.1, Rails 4.1.</p>
  
  <p>I am trying to create a form for a hockey match with parameters (id, team_a, team_b, arena, date, score_a, score_b). team is a table (id, name) and arena is a table (id, name).</p>
  
  <p>When I pass the parameters from form to the controller, the json parameters seem to be okay. But, when it is converted into match_params it is missing some values from parameters from other table. For example, I am passing arena_id: 12, but it shows arena_id: as blank.</p>
  
  <p>I've spent over 5 days on this thing. Any help appreciated. </p>
  
  <p>Some of the code is bellow. Let me know if you need me to provide more information...</p>
  
  <p><strong>migration data</strong>   </p>
  
  <pre><code>class CreateMatches &lt; ActiveRecord::Migration
    def change
      create_table :matches do |t|
        t.references :team_a,     default: 1 # unknown
        t.references :team_b,     default: 1 # unknown
        t.references :arena,    default: 1 # unknown
        t.datetime :date
        t.integer :score_a
        t.integer :score_b
        t.timestamps
      end
      add_index :matches, :team_a_id
      add_index :matches, :team_b_id
      add_index :matches, :arena_id
    end
  end
  
  class CreateTeams &lt; ActiveRecord::Migration
    def change
      create_table :teams do |t|
        t.string :name, null: false
        t.timestamps
      end
    end
  end
  
  class CreateArena &lt; ActiveRecord::Migration
    def change
      create_table :arena do |t|
        t.string :name, null: false
        t.timestamps
      end
    end
  end
  </code></pre>
  
  <p><strong>match.rb (model)</strong></p>
  
  <pre><code>class Match &lt; ActiveRecord::Base
    belongs_to :team_a, :class_name =&gt; 'Team'
    belongs_to :team_b, :class_name =&gt; 'Team'
    belongs_to :arena
  end
  </code></pre>
  
  <p><strong>team.rb (model)</strong></p>
  
  <pre><code>class Team &lt; ActiveRecord::Base
    has_many :matches
  
    accepts_nested_attributes_for :matches
  end
  </code></pre>
  
  <p><strong>arena.rb (model)</strong></p>
  
  <pre><code>class Arena &lt; ActiveRecord::Base
    has_many :matches
  
    accepts_nested_attributes_for :matches
  end
  </code></pre>
  
  <p><strong>matches_controller.rb</strong></p>
  
  <pre><code>class MatchesController &lt; ApplicationController
    before_action :set_match, only: [:show, :edit, :score, :update, :destroy]
  
    include ActionView::Helpers::DateHelper
  
    def index
      # some code
    end
  
    def show
      # some code
    end
  
    def new
      @match = Match.new
      @teams = Team.all.order("name ASC")
      @arenas = Arena.all.order("name ASC")
    end
  
    # GET /matches/1/edit
    def edit
      # some code
    end
  
    def create
  
      puts YAML::dump(match_params)  # Checking passed params. Output is bellow
  
      @match = Match.new(match_params)  
  
      respond_to do |format|
        if @match.save
          format.html { redirect_to @match, notice: 'Match was successfully created.' }
          format.json { render action: 'show', status: :created, location: @match }
        else
          format.html { render action: 'new' }
          format.json { render json: @match.errors, status: :unprocessable_entity }
        end
      end
    end
  
    def update
    end
  
    def destroy
    end
  
    private
    # Use callbacks to share common setup or constraints between actions.
    def set_match
      @match = Match.find(params[:id])
    end
  
    # Never trust parameters from the scary internet, only allow the white list through.
    def match_params
      params.require(:match).permit(:date, :score_a, :score_b, team_a_id: [:id, :name], team_b_id: [:id, :name], arena_id: [:id, :name])
    end
  
    public
  end
  </code></pre>
  
  <p><strong>teams_controller.rb</strong></p>
  
  <pre><code>class TeamsController &lt; ApplicationController
    before_action :set_team, only: [:show, :edit, :update, :destroy]
  
    layout :false
  
    def index
      @teams = Team.all
    end
  
    def show
    end
  
    def new
      @team = Team.new
    end
  
    def edit
    end
  
    def create
      @team = Team.new(team_params)
  
      respond_to do |format|
        if @team.save
          format.json { render action: 'show', status: :created, location: @team }
          format.html { redirect_to @team, notice: 'Team was successfully created.' }
        else
          format.html { render action: 'new' }
          format.json { render json: @team.errors, status: :unprocessable_entity }
        end
      end
    end
  
    def update
      respond_to do |format|
        if @team.update(team_params)
          format.json { head :no_content }
          format.html { redirect_to @team, notice: 'Team was successfully updated.' }
        else
          format.html { render action: 'edit' }
          format.json { render json: @team.errors, status: :unprocessable_entity }
        end
      end
    end
  
    def destroy
      @team.destroy
      respond_to do |format|
        format.html { redirect_to teams_url }
        format.json { head :no_content }
      end
    end
  
    private
    # Use callbacks to share common setup or constraints between actions.
    def set_team
      @team = Team.find(params[:id])
    end
  
    # Never trust parameters from the scary internet, only allow the white list through.
    def team_params
      params.require(:team).permit(:name)
    end
  end
  </code></pre>
  
  <p><strong>arenas_controller.rb</strong></p>
  
  <pre><code>class ArenasController &lt; ApplicationController
    before_action :set_arena, only: [:show, :edit, :update, :destroy]
  
    layout false
  
    def index
      @arena = Arena.all
    end
  
    def show
    end
  
    def new
      @arena = Arena.new
    end
  
    def edit
    end
  
    def create
      @arena = Arena.new(arena_params)
  
      respond_to do |format|
        if @arena.save
          format.json { render action: 'show', status: :created, location: @arena }
          format.html { redirect_to @arena, notice: 'Arena was successfully created.' }
        else
          format.html { render action: 'new' }
          format.json { render json: @arena.errors, status: :unprocessable_entity }
        end
      end
    end
  
    def update
      respond_to do |format|
        if @arena.update(arena_params)
          format.json { head :no_content }
          format.html { redirect_to @arena, notice: 'Arena was successfully updated.' }
        else
          format.html { render action: 'edit' }
          format.json { render json: @arena.errors, status: :unprocessable_entity }
        end
      end
    end
  
    def destroy
      @arena.destroy
      respond_to do |format|
        format.html { redirect_to arenas_url }
        format.json { head :no_content }
      end
    end
  
    private
    # Use callbacks to share common setup or constraints between actions.
    def set_arena
      @arena = Arena.find(params[:id])
    end
  
    # Never trust parameters from the scary internet, only allow the white list through.
    def arena_params
      params.require(:arena).permit(:name)
    end
  end
  </code></pre>
  
  <p><strong>matches/_match.html.erb</strong></p>
  
  <pre><code>&lt;%= form_for(@match, html: {role: 'form', class: 'form-horizontal'}) do |f| %&gt;
      &lt;% if @match.errors.any? %&gt;
          &lt;div id="error_explanation"&gt;
            &lt;h2&gt;&lt;%= pluralize(@match.errors.count, "error") %&gt; prohibited this match from being saved:&lt;/h2&gt;
  
            &lt;ul&gt;
              &lt;% @match.errors.full_messages.each do |msg| %&gt;
                  &lt;li&gt;&lt;%= msg %&gt;&lt;/li&gt;
              &lt;% end %&gt;
            &lt;/ul&gt;
          &lt;/div&gt;
      &lt;% end %&gt;
  
      &lt;%= f.label 'Home Team' %&gt;
      &lt;%= f.collection_select :team_a_id, @teams, :id, :name, {prompt: true}, {class: ''} %&gt;
  
      &lt;%= f.label 'Visitor Team' %&gt;
      &lt;%= f.collection_select :team_b_id, @teams, :id, :name, {prompt: true}, {class: ''} %&gt;
  
      &lt;%= f.label 'Arena' %&gt;
      &lt;%= f.collection_select :arena_id, @arenas, :id, :name, {prompt: true}, {class: ''} %&gt;
  
      &lt;%= f.label 'Date' %&gt;
      &lt;%= f.datetime_select :date, class: 'form-control' %&gt;
  
      &lt;%= f.submit value: 'Submit' %&gt;
  
   &lt;% end %&gt;
  </code></pre>
  
  <p>And here's what I am getting in console after dumping data: </p>
  
  <pre><code>Started POST "/matches" for 127.0.0.1 at 2014-05-06 18:24:20 -0700
  Processing by MatchesController#create as HTML
  Parameters: {"utf8"=&gt;"✓", "authenticity_token"=&gt;"0RJjnpczVkp2unG9VITyHYC89ThgELn5kVE2wYRymBU=", "match"=&gt;{"team_a_id"=&gt;"24", "team_b_id"=&gt;"27", "arena_id"=&gt;"21", "date(1i)"=&gt;"2014", "date(2i)"=&gt;"5", "date(3i)"=&gt;"6", "date(4i)"=&gt;"18", "date(5i)"=&gt;"24"}, "commit"=&gt;"Update"}
  User Load (0.5ms)  SELECT  `users`.* FROM `users`  WHERE `users`.`id` = 1  ORDER BY `users`.`id` ASC LIMIT 1
  --- !ruby/hash:ActionController::Parameters
  date(1i): '2014'
  date(2i): '5'
  date(3i): '6'
  date(4i): '18'
  date(5i): '24'
  team_a_id:
  team_b_id:
  arena_id:
     (0.2ms)  BEGIN
    SQL (1.5ms)  INSERT INTO `matches` (`created_at`, `date`, `arena_id`, `team_a_id`, `team_b_id`, `updated_at`) VALUES ('2014-05-07 01:24:20', '2014-05-07 01:24:00', NULL, NULL, NULL, '2014-05-07 01:24:20')
     (0.2ms)  COMMIT
  Redirected to http://localhost:3000/matches/90
  Completed 302 Found in 13ms (ActiveRecord: 2.4ms)
  </code></pre>