Reputation: 43
I've been trying to get my first Rails code to work for a while now and I still can't seem to get it to work. My latest problem is that I keep getting the following error
'NoMethodError in MessageController#create".
I see that I am trying to pass nil for some variables as shown in the next line
"undefined method `message' for #<Message mess: nil, user: nil>"
However my parameters are passed correctly as I can see in the bottom of the error screen. My code is below. Any help is appreciated.
Controller
class MessageController < ApplicationController
def new
@message = Message.new
end
def create
@message = Message.new(user_params)
@message.mess=params[:mess]
@message.user=params[:user]
if @message.save
redirect_to "http://itworks.com"
else
redirect_to "http://myspace.com"
end
end
private
def user_params
params.require(:message).permit(:mess, :user)
end
end
View
<%= form_for @message, url: {action: "create"}, html: {class: "nifty_form"} do |f| %>
<%= f.text_field :mess %><br />
<%= f.text_field :user %><br />
<%= f.submit "Create" %>
<% end %>
Upvotes: 3
Views: 489
Reputation: 76774
Strong Parameters
Firstly, you need to read up on Strong Parameters
With Rails 4, to prevent mass assignment, you need to create new ActiveRecord objects using a private method to assign the parameter values you need:
#app/controllers/messages_controller.rb
Class MessagesController < ApplicationController
def create
@message = Message.new(message_params)
@message.save
end
private
def message_params #-> you can call this method what you like :)
params.require(:message).permit(:mess, :user)
end
end
This will set the params for your ActiveRecord object from this params hash:
params {
"message" => {
"mess" => "value",
"user" => "value"
}
}
This should be passed by your form as it stands; however, if you started to use something like form_tag
, you'll end up without the message
param, thus preventing the strong params method from working correctly.
--
Form
Your form can be simplified:
<%= form_for @message, html: {class: "nifty_form"} do |f| %>
If you populate the form_for
with an ActiveRecord object, Rails should extract the path automatically for you; not that it matters for your error, as your form is sending the request to the create
action anyway
--
Method
The no method error
is derived from calling a method on an object which either doesn't exist, or does not support the method (unsurprisingly).
In respect to debugging this issue, you basically need to look for where you may be calling .message
on the object. This is typically in a view or something (if not in the controller)
With the only reference to .message
being in the strong params
method you have, I would recommend trying this:
def create
@message = Message.new(user_params)
if @message.save
redirect_to "http://itworks.com"
else
redirect_to "http://myspace.com"
end
This will make the action conventional, which should give it the best chance of working.
--
Association
The other problem you may have is the ActiveRecord association in your Message
model. ActiveRecord associations are defined in the model to give your objects the ability to append associative data
The error you have could come from something like this:
#app/models/message.rb
Class Message < ActiveRecord::Base
belongs_to :message #-> won't work
end
Upvotes: 4
Reputation: 459
You have a couple of naming problems:
class MessagesController < ApplicationController
#Primarily, you want MessagesController, not MessageController. Plural.
def new
@message = Message.new
end
def create
#you should call 'message_params' not 'user_params' as a
#parameter in your call to Message.new
@message = Message.new(message_params)
# these two lines need to be commented out, as they overwrite the attributes
# in @message with nil
# @message.mess=params[:mess]
# @message.user=params[:user]
if @message.save
redirect_to "http://itworks.com"
else
redirect_to "http://myspace.com"
end
end
private
#again, message_params, because these are the params that are permitted via
#a form to the message controller (and therefore model), though this wasn't
#technically a problem. You can name your methods anything you want in Ruby.
#this name is just clearer.
def message_params
params.require(:message).permit(:mess, :user)
end
end
You can remove the :url => {:action => 'create'} on your call to form_for, as a new record will always get routed to create by f.submit. This allows you to use the same form for editing and creating.
Upvotes: -2