lighter
lighter

Reputation: 2806

Rails undefined method `model_name' for nil:NilClass nested routes

I'm a newbie on rails. My rails version is 4.2.6, simple_form_for version is 3.2.1. I want to redirect to the new page after I validated the params is false. And I get the error message.

undefined method `model_name' for nil:NilClass <%= simple_form_for [:account, @station] do |f| %> ...

let me show you. This is my routes.rb

namespace :account do
    resources :stations, expect: [:index]
end

stations_controller.rb

def new
    @lines = Line.where(line_status: 1)
    @station = Station.new
end

def create
    unless check_post_params post_params
        flash[:notice] = "miss params"

        render action: :new # not work
        # render :new # not work
        # render 'new' # not work

        # it work for me, but can I use render?
        #redirect_to '/account/stations/new'
    else
        @station = Station.new(post_params)

        if @station.save
            redirect_to '/account/lines'
        else
            flash[:notice] = 'failed'
            redirect_to 'account/stations/new'
        end
    end
end

private
def post_params
    params.require(:station).permit(...)
end

def check_post_params(post_params)
    if ...
        return false
    else
        return true
    end
end

_form.html.erb

<%= simple_form_for [:account, @station] do |f| %>
    <div class="form-group">
        <%= f.label :line_id, t('line.line_name') %>
        <%= f.input_field :line_id,
            ... %>
<% end %>

The original I open the URL is http://localhost:3000/acoount/stations/new. After I click the submit, and I want to render :new, it will redirect to original URL, but I found the URL become http://localhost:3000/account/stations. The URL's /new is disappear. I have guessed it's about my routes.rb config.

And I tried to use rake routes to check my routes.

$ rake routes
...
POST  /account/stations(.:format) account/stations#create {:expect=>:index]}
new_account_station GET  /account/stations/new(.:format) account/stations#new {:expect=>[:index]}
...

I tried to use render account_stations_new_path and render new_account_station_path, but still not work for me. Thanks your help.

Edit

I know how to modify my code. I should validate my params on my model. And then I should use redirect_to not use render. I will update my code later.


Edit 2

I modified my model.

class Station < ActiveRecord::Base
    belongs_to :line
    has_many :spot_stations

    validates :name, presence: true, uniqueness: { case_sensitive: false }
    validates :line_id, presence: true
    validates ....
end

And I modified my controller.

def new
    # Because this @lines did't exist when I render 'new' on the create method. So I deleted it. And I create a method on the helper.
    # @lines = Line.where(line_status: 1)
    @station = Station.new
end

def create
    @station = Station.new(post_params)

    if @station.save
        redirect_to '/account/lines'
    else
        flash[:notice] = 'failed'
        render 'new'
    end
end

I add a method for getting lines data

module Account::StationsHelper
    def get_lines
        @lines = Line.where(line_status: 1)
    end
end

I will use it on my _form.html.erb

<%= simple_form_for [:account, @station] do |f| %>
    <div class="form-group">
        <%= f.label :line_id, t('line.line_name') %>
        <%= f.input_field :line_id,
                          collection: get_lines,
                          label_method: :line_name,
                          input_html: { class: 'form-control' },
                          value_method: :id,
                          prompt: t('common.please_select') %>
    </div>
    ...
<% end %>

This work great for me. Thanks your help.

Upvotes: 1

Views: 320

Answers (1)

Bartłomiej Gładys
Bartłomiej Gładys

Reputation: 4615

try this:

if @station.save
    redirect_to account_stations
else
    flash[:notice] = 'failed'
    render 'new'
end

as argument for render method you must pass action name, not url.

Upvotes: 1

Related Questions