Search code examples
ruby-on-railsrubyformsfields-for

How to get value of a single attribute from a fields_for submission when using strong parameters? Rails 4


I apologize if the title to the question may come off a bit confusing, but I am sincerely having a difficult time putting it into better words.

I am trying to access a single attribute within a fields_for submission in the controller.

My form looks like this:

= form_for @match, :url => matches_search_path, remote: true do |f|
      = f.select :sport_id, options_from_collection_for_select(Sport.all, "id", "name"), {:prompt => "Select Sport..."}, class: "form-control"
      = f.fields_for @match.build_location do |g|
        = g.text_field :zip, :class => "form-control", :value => @user.location.zip, :placeholder => "Zip"
      = f.text_field :max_players, :class => "form-control", :placeholder => "Player Limit (in total)"
      = f.submit "Search", :class => "btn btn-info"

And the MatchesController like so:

class MatchesController < ApplicationController
before_filter :current_user

def index
    @match = Match.new
    @user = current_user
end

def new
    @match = Match.new
    @match.build_location
end

def create
    @user = User.find(session[:user_id])
    @match = @user.matches.build(match_params)

    if @match.save
        redirect_to :root, :notice => "Match created."
    else
        render :new, :alert => "Failed to create match."
    end
end

def search
    # Get all matches for the searched sport
    @results = Match.sport_id(match_params[:sport_id])

    #This is where the problem is:
    @coordinates = Geocoder.coordinates(match_params[:location][:zip])

    @results = @results.select {|result| result.location.distance_from(@coordinates)}

    respond_to :js
end

private def match_params
    params.require(:match).permit(:sport_id, :name, :description, :choose_teams, :keeping_score, :max_players, :time, location_attributes: [:address, :city, :state, :zip])
end
end

And the route is fine:

# Matches
resources :matches
post 'matches/search', as: :matches_search

The form submits an ajax call to the search method in the MatchesController just fine. The problem is that I get:

undefined method `[]' for nil:NilClass

at the line

@coordinates = Geocoder.coordinates(match_params[:location][:zip])

I tried googling the problem but the closest to this problem I found was here, where when trying to access a "hash within a hash" is to use:

params[:outer_hash][:inner_hash]

which did not work when I used params[:location][:zip], match_params[:location][:zip] or match_params[:location_attributes][:zip].

I verified that the information from the form is being sent to the controller. I just can't seem to access it properly.

What exactly am I doing wrong?

Edit:

Here's the response from the form: (I blocked out the authenticity_token)

{"utf8"=>"✓", "authenticity_token"=>"XXXXXXXXXXXXXXXXXXXXXXX", 
"match"=>{"sport_id"=>"4", 
"location"=>{"zip"=>"11211"},
"max_players"=>""},
"commit"=>"Search"}

Solution

  • What I think is happening is that your match_params are not letting in the location params (I'm guessing a match has_one location). Change the line:

    @coordinates = Geocoder.coordinates(match_params[:location][:zip])
    

    to:

    @coordinates = Geocoder.coordinates(params[:match][:location][:zip])
    

    OR better yet, change your match_params to:

    params.require(:match).permit(:sport_id, :name, :description, :choose_teams, :keeping_score, :max_players, :time, location: [:address, :city, :state, :zip])