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.
Related
New web developer here, and I think I may be missing some very fundamental knowledge. Given the code
> def create
> #post = Post.new(post_params)
> if #post.save
> redirect_to #post
> else
> render "new"
> end
end
after saving the post, it redirects to show page, due to this "redirect_to #post", how can I do the same thing with "redirect_to: action => "show", :id => 5" I have to pass the ID now, how to retrieve the ID from #post object?
so only I can pass the Id to redirect page.
can I stop the compiler here, like debugger in js?
To answer your question of "I may be missing some very fundamental knowledge" yes, you might be. An object in Rails like #post is usually a database record. You can access any of it's columns in the DB by using the column name as a method:
#post.id
returns:
5 #or whatever the post id is.
If your post table has a column of "title" you can access it with
#post.title
returns:
"This is an awesome post"
I would highly recommend you view some Ruby and some Rails tutorials. Everything in Ruby is an object. Rails uses a lot of conventions so you can do things without having to write code for it, it's already there for you. When you get into Rails ActiveRecord Relations you'll see that relations expand this to give you related table information as methods. For Example:
Post.rb
...
belongs_to :user
User.rb
...
has_many :posts
Gives you methods like:
#post.user #returns the user object with all of its info
#post.user.username #returns the value of that column for that user
#post.user.posts #returns an array of Post objects that belong to the owner of that post.
Ruby has a pry-byebug gem for debugging. It's a combination REPL (Pry) and core debugger (byebug) that work very powerfully together.
Getting the id of a successfully saved ActiveRecord model is just #post.id, however the rails methods like redirect_to will take the object itself just fine, as #Beartech has mentioned, above. The documentation shows a variety of ways to use it, for convenience:
redirect_to action: "show", id: 5
redirect_to #post
redirect_to "http://www.rubyonrails.org"
redirect_to "/images/screenshot.jpg"
redirect_to posts_url
redirect_to proc { edit_post_url(#post) }
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
I have a bit of an odd issue. I have a projects controller where I am creating a new project related to a company and created by the logged in user (current_user), here is my create action.
def create
#project = #company.projects.build(params[:project].merge!(:user => current_user))
##project.user = current_user
if #project.save
#debugger
flash[:notice] = "Project has been created."
redirect_to [#company, #project]
else
flash[:alert] = "Project has not been created."
render :action => "new"
end
end
The above code breaks on the redirect to the project show page with the following error:
undefined method `email' for nil:NilClass
%b
Created by
= #project.user.email # <-- errors, not sure why
So I know everything else is saving except the user who created that project. If I remove the .merge! in my create method and do it in two steps it works perfectly fine, like so:
def create
#project = #company.projects.build(params[:project])
#project.user = current_user
....
How come using merge! would not work? I would have thought that merging the user into the object would be perfectly fine. What is the right (or preferred) way to go about this?
Thanks
I've figured it out. It was a mass assignment issue. I had attr_accessible :title, :description, :account_number, :account_executive in my code, disabled it to allow mass assignment and it worked fine.
I have a form where I have an administrator creating new users. The form uses the User model I created (login, password, first_name, etc...). For the last field on the form, I want to have a checkbox that doesn't need to be stored as part of the User record, but it is needed for the controller. This will control if the newly created user will receive a welcome email or not. This is in Rails 3.0.3.
def create
#user = User.new(params[:user])
if #user.save
if #user.send_welcome_email
UserMailer.welcome_email(#user).deliver
end
redirect_to(admin_users_url, :notice => "User #{#user.name} was successfully created.")
else
render :action => "new"
end
end
In my view (haml) I am trying to access it like this:
%p
Send Welcome Email?
= f.check_box :send_welcome_email
I tried to make this an attr_accessible: :send_welcome_email but the controller does not recognize it. I get an
undefined method 'send_welcome_email' for #<User:0x00000100d080a8>;
I would like it to look like this:
What is the best way to get this working?
What you want is not attr_accessible, but attr_accessor. That's it.
However, your code will look nicer if you move the email sending code to an observer.
Since you're not saving it on the user, you can use check_box_tag instead of f.check_box and access it with params[:send_welcome_email]. Although even the way you have it, I think you could access it as params[:user][:send_welcome_email].
As an alternative to attr_accessor, you can always remove it from the parameters first:
def create
send_welcome_email = params[:user].delete(:send_welcome_email)
#user = User.new(params[:user])
if #user.save
UserMailer.welcome_email(#user).deliver if send_welcome_email
redirect_to(admin_users_url, :notice => "User #{#user.name} was successfully created.")
else
render :action => "new"
end
end
You may have to make sure that the parameter is successfully transformed into a boolean; otherwise the condition will always be true (0 is true in Ruby).
I am at an absolute loss as to what I am doing wrong with the following code. I am trying to implement a messaging system within my application, but want it to be handle different types of messages. In this case, I want to create a "request" message of ':message_type => 1'.
Instead of using forms as I usually have, I want to make this instance the moment the link is clicked. Here is how I have it set up in the show erb file for "user":
<%=link_to "Send friend request", :action=>"request", :controller => "messages", :id => #user.id %>
and in the controller:
def request
#message = Message.new(:sender_id => current_user.id,:user_id => params[:id],:message_type => 1)
if #message.save
flash[:notice] = 'Message was successfully created.'
redirect_to message_path(#message)
else
redirect_to message_path(#message)
end
end
This results in the following error message: undefined method `rewrite' for nil:NilClass with the trace looking like
c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.3.5/lib/active_support/whiny_nil.rb:52:in `method_missing'
c:/ruby/lib/ruby/gems/1.8/gems/actionpack-2.3.5/lib/action_controller/base.rb:634:in `url_for'
(eval):16:in `message_path'
app/controllers/messages_controller.rb:11:in `request'
I have used map.resources :messages in the routes.rb file, and done the appropriate :has_many and :belongs_to associations in the models of user and message.
EDIT: Something else to note is that the save IS succeeding, as once the root address is manually inputted into the address bar, the "flash" notice is shown saying that the save was made. Using the development console it is indeed there, so there's something messed up with the redirect.
You might want to rename the action, I am quite sure that request means something in the controller.
Why dont you rename the action from request to create, and see if it helps.
So the code will be:
In the view
<%=link_to "Send friend request", :action=>"create", :controller => "messages", :id => #user.id %>
In the controller
def create
#message = Message.new(:sender_id => current_user.id,:user_id => params[:id],:message_type => 1)
if #message.save
flash[:notice] = 'Message was successfully created.'
redirect_to message_path(#message)
else
redirect_to message_path(#message)
end
end
Check your logs more closely, and you'll probably find that your save is failing. Not sure which line is #11, but I would guess that it's in your else block, which tries to build a path for a #message object with a nil ID (it hasn't been saved).