0
votes

Before I changed a view layout, Rails show my login view properly. But after the change, I have got an error message below.

undefined method `model_name' for NilClass:Class

Before the change, "app/views/layouts/application.html.erb"were applied to my login view.

and I wanted to change layout only on my login view. So, "I made app/views/layouts/login.html.erb" and put some code on the controller. def login render :layout => 'login' end

I guess the error must come from the code,which includes @member.

{:action => 'login'}) do |f| %>

But I don't understand why. Could you give me some advise?

☆members controller

def login
    render :layout =>'login'
    @msg = "get"
    @member = Member.new

if request.post? then
  @member = Member.new(params[:member])
  record = Member.find_by_user(params[:member][:user])
  if record == nil then
    @msg = "record is nil."
    @member.errors.add('user',"not registrated!")
  else
    if record.pass != params[:member][:pass] then
      @msg = "password is wrong."
      @member.errors.add('pass','password is wrong!')
    else 
      @msg = "good!"
      @member = record
      session[:login] = record
      redirect_to '/members/' + record.id.to_s
    end
  end
end

end

☆layouts/login.html.erb

<!DOCTYPE html>
<html>
<head>
  <title>XXXX</title>
   <%= stylesheet_link_tag    "application", media: "all" %>
    <%= javascript_include_tag "application" %>
    <%= csrf_meta_tags %>
    <link href="css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
 <%= render 'layouts/exheader'%> 
<div class= "container">
 <%= yield %>
</div>
<div class="container">
<%= render 'layouts/footer' %>
</div>
</body>
</html>

☆login.html.erb(members)

    <div class="span4">
        <div class="login_form">
            <h4>Login</h4>
            <%= form_for(@member, :url => {:action => 'login'}) do |f| %>
                <% if @member.errors.any? %>
                    <div id="error_explanation">
                        <h2><%= pluralize(@member.errors.count, "error")%>
                        prohibited this member from being saved:</h2>
                        <ul>
                            <% @member.errors.full_messages.each do |msg| %>
                            <li><%=msg %></li>
                            <% end %><%# do |msg|%>
                        </ul>
                    </div>
                <% end %><%#  if%>
                <div class="field">
                    <%= f.label :user %>
                    <%= f.text_field :user %>
                </div>
                <div class="field">
                    <%= f.label :pass %>
                    <%= f.password_field :pass %>
                </div>
                <div class="actions">
                    <%= f.submit :value => "login" %>
                </div>
            <% end %><%# do |f|%>
        </div><!-- login form -->   
    </div><!--span4 for login -->   

1
At which line does the error occur?Tamer Shlash
This line. <%= form_for(@member, :url => {:action => 'login'}) do |f| %> <%# if @member.errors.any? %>Kuniharu Aramaki

1 Answers

1
votes

Rails will immediately start rendering the view when a render occurs. So in your code, you have placed render :layout => 'login' at the very beginning of the action, and consequently the view was rendered before executing any action code; thus, all instance variables like @member and @msg haven't yet been declared, their values are nil while rendering the views. So

<%= form_for(@member, :url => {:action => 'login'}) do |f| %>
  <%# if @member.errors.any? %>

Complains that @member, which is a nil, has no method model_name.

Ultimately you should only place render at the end of your controller code. Maybe like this:

def login
  @msg = "get"
  @member = Member.new

  if request.post?
    @member = Member.new(params[:member])
    record = Member.find_by_user(params[:member][:user])
    if record.nil?
      @msg = "record is nil."
      @member.errors.add('user',"not registrated!")
    else
      if record.pass != params[:member][:pass]
        @msg = "password is wrong."
        @member.errors.add('pass','password is wrong!')
      else
        @msg = "good!"
        @member = record
        session[:login] = record
        redirect_to '/members/' + record.id.to_s
        return
      end
    end
  end
  render :layout =>'login'
end