I tried to create a simple login_app using 'Authlogic' gem and i got this error:
NameError in UsersController#create
undefined local variable or method `users' for #<UsersController:0x0000000354ba48>
Extracted source (around line #28):
code:
def create
#user = User.new(params users ) # <- this line
respond_to do |format|
if #user.save
Rails.root: /home/ameex/projects/login_app
Application Trace | Framework Trace | Full Trace
app/controllers/users_controller.rb:28:in `create'
please help me to resolve this
If you are using Rails4,this should work.
class UsersController < ApplicationController
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
else
format.html { render action: "new" }
end
end
end
private
def user_params
params.require(:user).permit(:your_user_attr1,:your_user_attr2,..)
end
end
Have a look at Strong Parameters in these Guides.
To back up Pavan's answer, the error you had was this:
UsersController#create undefined local variable or method `users' for
#
This is a typical problem, and basically means you've referenced a local object which doesn't exist (in your case users). The issue is that now you're trying to call this, Rails cannot find it, leading to the exception
--
Params
As Pavan pointed out, the problem you have is you're calling:
#user = User.create(params users)
The problem here is you're calling a non-existent object, as explained; but what is much more important is your actual syntax is wrong. You're getting confused with two variables inside Rails:
params hash
strong_params method
When you create a new object in Rails 4, you need to tell ActiveRecord which params values you wish to populate the new record with. This is currently done by using strong_params, which essentially whitelists different members of the params hash
The bottom line is when you reference data / objects in Rails, you have to have them available beforehand. Your referencing of params users references neither the relevant params[:key][:value], nor your strong_params method
Hopefully this gives you some more ideas
Related
Edit: it turns out I made a very simple mistake and had a Template that was associated with a LocalTemplate id that no longer existed. If anyone has this problem and thinks that they somehow are unable to unable to associate the id of another model in their update action, make sure that you didn't accidentally delete the parent object causing that id to no longer exist!
The code below, while dramatically simplified did work for me.
I have a Template model in my rails app. It has a method "data" defined in it.
I am able to access this method in the create and show actions with #template.data, however when using the same #template.data in the update action of my controller I get a no method error because I am not showing the correct local template id to it. This line can be found in the model where it reads base_data = YAML.load(local_template.data)
I stored an id of the associated local_template when initially saving a new template, but how can I make sure I reference that id again in the update action so I do not get a no method error?
Here is a simplified version of the Template model and controller
Model:
class Template < ActiveRecord::Base
def data
base_data = YAML.load(local_template.data)
# couldn't pass the correct LocalTemplate here because
# the local_template_id I had in my Template model no
# longer existed. Changing the id to a LocalTemplate
# that did exist fixed the issue.
end
end
Controller:
class TemplatesController < ApplicationController
def index
#business = Business.find(params[:business_id])
#templates = #business.templates.all
end
def new
#business = Business.find(params[:business_id])
#local_templates = LocalTemplate.all
#template = #business.templates.build
end
def create
#business = Business.find(params[:business_id])
#local_templates = LocalTemplate.all
#template = #business.templates.build(template_params)
if #template.save
#template.data #works fine here
redirect_to business_url(#template.business_id)
else
render 'new'
end
end
def show
#business = Business.find(params[:business_id])
#template = #business.templates.find(params[:id])
#template.data #works fine here too
end
def edit
#business = Business.find(params[:business_id])
#local_templates = LocalTemplate.all
#template = #business.templates.find(params[:id])
end
def update
#business = Business.find(params[:business_id])
#template = #business.templates.find(params[:id])
if #template.update_attributes!(pass_template_params)
Api.new.update_template(#template.data.to_json) #this is where I had a problem
redirect_to business_url(#template.business_id)
else
render 'edit'
end
end
end
You are mixing a lot. There is a lot to refactor in your controller...
First of all, your TemplatesController should be about the template resources, but your controller looks more like a BusinessesController. In general your update action for example should look more like:
def update
#template = Template.find params[:id]
#template.attributes = template_params # though this should raise a NoMethodError, because you dind't define it; I'd prefer params[:template] if possible
if #template.save
redirect_to business_url(#template.business_id)
else
#local_templates = LocalTemplate.all
render 'edit'
end
end
Instantiating #business and #local_templates makes non sense, because you don't use it at all. Speed up your responses if you can! :)
Fixed that, there is no need for the overhead of a nested resource in update (as you did).
If saving #template fails for validation reasons, you better should load the business object late by:
#template.business
in your /templates/edit.html.erb partial. Then you also do not need a nested route to your edit action... You see, it cleans up a lot.
As a general guideline you should create as less as possible controller instance variables.
If you cleaned up your controller and views, debugging your data issue will be easier.
I assume:
local_template
in your Template model to be an associated LocalTemplate model object. So it should no issue to call that anywhere if you ensured the referenced object exists:
class Template < ActiveRecord::Base
def data
return if local_template.nil?
YAML.load(local_template.data)
end
end
or validate the existence of the local_template object. or even b
You should confirm #template is not nil, if #template is nil, you can't use data method.
1.9.3-p547 :024 > nil.data
NoMethodError: undefined method `data' for nil:NilClass
from (irb):24
from /Users/tap4fun/.rvm/rubies/ruby-1.9.3-p547/bin/irb:12:in `<main>'
And you should use update_attributes!, it can raise an exception if record is invalid.
You can do like this.
if #template
#template.update_attributes!(template_params)
#template.data
end
I have such a controller action:
def update_grade
#id = params[:id]
#grade = "Grade#{#id}".classify.constantize.find_by_id(params[:grade_id])
# render :text => #grade.grade1.inspect
respond_to do |format|
if #grade.update(:grade1 => 2)
format.html { redirect_to update_grade_homework_path, notice: 'Homework was successfully updated.' }
end
end
end
I am getting "Undefined method `update'" error but #grade is perfectly fine object. I verified it by inspecting it. What am I doing wrong?
ActiveRecord::Base doesn't have an instance method called update. (Well, actually, it does, but it's a private method so you shouldn't be able to call it using #grade.update). You may be looking for update_attributes.
#grade.update_attributes(:grade1 => 2)
(Note that if you're using Rails 3 you'll need to add the line attr_accessible :grade1 to your model or the above code will throw a MassAssignmentSecurityError.)
ActiveRecord does have a class method called update, which you can find in the docs here.
The difference in usage should be clear from this example (say you have a model Grade and you want to set the attribute "foo" to "bar" for the Grade with id 5):
# Using the class method "update":
Grade.update(5, foo: "bar")
# Using the instance method "update_attributes"
#grade = Grade.find_by(id: 5) # Or just Grade.find(5)
#grade.update_attributes(foo: "bar")
That being said, if the error message really does say "Undefined method `update' for nil:NilClass" and #grade really doesn't equal nil, then that is a bizarre error and I can't think of any reason why it might be occurring. Try changing update to update_attributes and let me know if that works.
Working on the Rails Guide Creating a Blog and am stuck at 5.7: Showing Posts.
I have already consulted with this answer:NoMethodError on section 5.7 of Rails Guide, and it solved a different problem for me, but now I am stuck here. It's telling me I never defined the method permit, which I understand, and don't see it defined anywhere, but the guide never had me define it or referenced it needing to be defined. From playing with it and getting some errors back, I gather it is necessary to actually store the post data?
I can get to the point where I submit a post, but when I submit, all I get back is:
NoMethodError in PostsController#create
undefined method `permit' for nil:NilClass
The error message specifies the error occurs in the second line of this code:
def create
#post = Post.new(params[:post].permit(:title, :text))
#post.save
redirect_to #post
My posts_controller file looks like this:
class PostsController < ApplicationController
def new
end
def create
#post = Post.new(params[:post].permit(:title, :text))
#post.save
redirect_to #post
end
def show
#post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:title, :text)
end
end
When I remove .permit(:title, :text) from the create method (as suggested here: Can't create new post), I no longer get an error, but am just served a page that reads:
Title:
Text:
Even though I submitted text.
Please let me know if I need to post more info or if I should have found a fix easily, first time poster, brand new to Rails.
I've been working with this tutorial, and I figured out what the issue was. When you're doing
#post.update(params[:post].permit(:title, :text))
you are calling the permit function on the POST parameter. This would be fine, except that the if statement is reached when the page is loaded for the first time and the form has not been submitted, therefore the :post key is not inside the params hash, causing a nil:nilClass error. If you add a check for :post inside the hash then do the permit inside the if statement as seen below, then everything should work fine.
if params.has_key?(:post)
#post.update(params[:post].permit(:title, :text))
redirect_to #post
else
render 'edit'
end
I figured it out. If you are running Rails version prior to 4.0 (do a "rails --version"), then the guide is wrong... it is evidently providing info that only works in 4.0. The correct statement in the controller file is:
#post = Post.new(params[:post])
Art
When I use version 3.2.13 it don't work
To resolve the problem , remove the portion of " .permit(:title, :text) "
There may be an error in your view. (app/views/posts/new.html.erb) It seems like a parameter :post is not passed to the controller properly.
To prevent undefined method error, you can write like params.require(:post).permit(:title, :text)
So I have a relationship of project to categories, such that a project can have many categories and a category belongs to a project. I have managed to have it working, but now - when I restartded my rails server, it doesn't work. The code I show bellow is what I had before the restarted and after the restart of my rails server, so I think its something to do with the code...
So I am not sure if you need models or just the controller or the form or what, so I have posted the create method from the categories controller as thats where the issue is happening:
def create
#project = Project.find(params[:project_id])
#category = #project.categories.create(params[:category].merge(:user_id => current_user.id))
if #category.save
redirect_to project_tasks_path(#project.id), :flash => {:success => 'Created a Category! Now you can create tasks!'}
else
redirect_to :back, :flash => {:error => 'We could not create an category. You need to enter a name.'}
end
end
It happens on the psychical create line, throwing the error:
RuntimeError in CategoriesController#create
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
Rails.root: /home/adam/Documents/Aptana Studio 3 Workspace/StartPoint
Application Trace | Framework Trace | Full Trace
app/controllers/categories_controller.rb:14:in `create'
Request
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"qbJyilRiMtwOyPDq9HQFO4JME+TPkh/cCEEqPZPxGDw=",
"category"=>{"category"=>"ffffffff"},
"commit"=>"Create Category",
"project_id"=>"2"}
This is thrown upon hitting create. Any ideas or do I need to show more code?
It looks like you don't have a current_user so it is set to nil.
Calling .id on nil will result in this error in Rails.
If your application does not allow anonymous access then you have a problem.
If it does, you should do this:
current_user ||= User.new
To always init current_user to a new User instance.
Your code will still not work as User.new will create a unsaved instance.
respond_to :json, :html
.
.
.
return_hash = {}
return_hash[:result] = "valid"
return_hash[:status] = "#{userName} has successfully registered for tournament #{tourneyID}"
respond_with(return_hash) #<--Throwing expection NoMethodError (undefined method `model_name' for NilClass:Class):
Here's the stack trace...
NoMethodError (undefined method `model_name' for NilClass:Class):
app/controllers/tournaments_controller.rb:48:in `register'
Rendered /Users/myname/.rvm/gems/ruby-1.9.2-p180/gems/actionpack-3.0.5/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.8ms)
Rendered /Users/myname/.rvm/gems/ruby-1.9.2-p180/gems/actionpack-3.0.5/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (151.8ms)
Rendered /Users/myname/.rvm/gems/ruby-1.9.2-p180/gems/actionpack-3.0.5/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (211.1ms)
Thanks so much!
Not sure if it matters, but I should add this is called in response to a POST request
Update:
I have similar code that works fine, it looks like this...
# Store the tourney data
tourney_hash[:tournament_count] = 1
tourney_hash[:tournament_id] = nextTourney.id
tourney_hash[:remaining_time_in_seconds] = remainingTimeInSeconds
respond_with(tourney_hash)
The only difference is this code is called from a GET request, while the problematic code above is called from a POST request
UPDATE:
When I changed this code so that it's called from a GET request instead of a POST request, it works fine. Your thoughts?
UPDATE:
For the time being, I've replaced the statement "respond_with(return_hash)" with "render :json => return_hash.to_json" and it works fine. Not ideal, tho.
due to http://apidock.com/rails/ActionController/MimeResponds/respond_with
respond_with(*resources, &block) public
It means that respond_with method accepts resource(s) while return_hash is a hash, not an ActiveRecord object. So your code is wrong. It won't ever work.
UPD
Why does this work with GET and doesn't work with POST, PUT or DELETE?
I don't know why do you use so strange construction as respond_with(some_hash). What is respond_with method?
respond_with wraps a resource around a responder for default representation
So it is strange to pass not resource but hash.
Now let's understand how it works:
# GET request
respond_with(whatever)
# same as
respond_to do |format|
format.html{ } # will render your_action_name.html.erb
end
BUT!
# POST request
respond_with(whatever)
# is same as
respond_to do |format|
format.html{ redirect_to WHATEVER } # !!!!
end
That's how respond_with works
So you should pass a resource to respond_with but not anything else. So your approach was wrong. And that is why you have got an error. Because to redirect_to return_hash it tries to get its model_name to generate a path.
That's it.
UPD 2
To render json you should:
respond_to do |format|
format.json{ render :json => return_hash.to_json }
end
I believe respond_with is supposed to be used with an ActiveRecord object (or a collection of ActiveRecord objects), not a hash.