I have a one to many relationship between 1 user and many challenges. I am using rails 4 with Devise
I would like to list the challenges for the current user.
So far I have
#challenge = User.find(current_user.id).challenges
and I've also tried
#challenge = User.find(current_user).challenges
and I also tried #challenge = current_user.challenges
but it doesn't work. I get the error "undefined methodeach' for nil:NilClass"` which usually means #challenge isn't being passed over to the view Have I made some kind of syntax error?
if I do User.find(1).challenges in the rails console it works fine so presumably I'm not using current_user.id correctly
It looks like when you are trying to access the page user is not logged in and hence current_user is set to nil.
current_user.challenges will do the job of fetching all challenges associated to this user. You can use user_signed_in? method from devise before calling this code to ensure current_user is always available.
Related
So I have this application, where you create a user and then you can add movies and shows into a database. Like a bad version on IMDB?
Now.. I have this controller: https://github.com/Veske/form/blob/ryhm/app/controllers/movies_controller.rb
I have set up routes for movies and also it has all the necessary view files.. but when I attempt to go on a page to edit one of the movies: http://whatever.com/shows/1/edit for example, it gives me a error:
Couldn't find User with id=1
def correct_user
#user = User.find(params[:id])
redirect_to root_url unless current_user?(#user)
end
end
params
{"id"=>"1"}
Now.. why is it thinking that the param I throw at it, is a #user param when I have a update and edit controller made specially for Movies?
You don't seem to understand routes. The context in which you are using params[:id] is the movies controller, hence, the id would be the movie id. At the same time, you're authenticating (?) with the same param, giving you the error.
For basic authentication you could use the session hash, and for a more advanced one there are lots of gems, being devise the most popular.
PS: use rake routes to check your available routes and its URL params.
Your shows_controller.rb file calls correct_user before running the edit action you are calling, and it is specifically looking for a user on line 70. So it would make sense that you are getting this error if there is no user with an ID of 1.
Why is it thinking that the param I throw at it, is a #user param when I have a update and edit controller made specially for Movies?
Because you have a before_action filter at the top of your controller that is being called on the edit action.
You get into the correct_user method, which is using finding a user based on params[:id] . To test that this is your actual problem, you might want to try to change line 68 in your controller to:
#user = User.last #quick fix
The above could be used as a quick fix -you shouldn't get that error you posted about any more, as long as your user is signed in. If this allows you to avoid the error, you then need to concern yourself with properly assigning this User#id value when this correct_user method is called by your controller.
This is a MoviesController, so the params[:id] is actually the movie_id, i.e., the number "1" in your url "http://whatever.com/shows/1/edit". Not the user_id. So it throws the exception at line #user = User.find(params[:id]).
I went through your code but can't find where the correct user_id should come from. The Movie model doesn't belongs_to user. You should check out where the user come from.
The code in question is in the create action of the Article controller.
I want each new article created to belong to the currently signed in User.
I checked that there is a user_id column in the Articles table and the correct association statements are in both models.
When I try and submit the form for a new Article, I get this error:
undefined method 'article' for nil:NilClass
in reference to this line of code:
#article = #current_user.article.new(article_params)
Am I using current_user incorrectly? How would one go about making the new item belong to the currently signed in user?
You should use current_user method:
#article = current_user.articles.new(article_params)
#current_user instance variable isn't set (thus it evaluates to nil) until current_user is called.
current_user is basically a convenience method/variable which takes the user id from the session hash and grabs that user (which is the current user that is active on that specific request)
so, when you want to have something only on the current user, just called current_user
however, there are some things you should watch out
make sure that the current user is logged in.
so make sure that when calling current_user.article.new(params) that current_user isn't nil, or it will throw an exception
when you want something to be only on that specific logged in user make sure to do as you did in the question
such as:
current_user.articles instead of Article.where(user_id: ...)
this will help you avoid problems in the future, and it may be faster in some situations
and 3. I think it should be current_user.articles.new(...)
It should be current_user, not #current_user.
current_user is a method, not an instance-variable.
I needed to access the current_user in my another model. I googled and found a few solutions and tried this.
But just one difference: I didn't set the User.current_user in the controller. WHY?
Like in the answer I followed I'm not adding data to my second model from views but by rendering data via a url (with open-uri, it's csv data I'm fetching).
So in my second model I do:
Person.create(username: User.current_user.username)
It gives:
NoMethodError: undefined method `username' for nil:NilClass
which isn't working (which is obvious I guess). In console when I do User.current_user it shows:
1.9.3p448 :002 > User.current_user
=> nil
I think why it isn't working is because I'm accessing the User.current_user directly from model and model cannot get the current_user unless it is given that. (right?)
But this would definitely work if I access it via a login page and set the User.current_user in the controller.
But as I'm directly fetching the data from url, I'm directly making new entries for my Person model in model itself.
So how do I set the User.current_user?
Is there any workaround for this? Edit's for the question's title are required.
current_user is available by default as a helper method within Devise. From the documentation:
# For the current signed-in user, this helper is available:
current_user
The current_user isn't accessed directly via the model, per se, but rather, though the Devise module, which looks up the User object that is logged into the current session, and then returns to current_user.
Thus, the current user isn't accessed via User.current_user (there is no current_user method on User, as the error message is saying). You access it purely by invoking the current_user helper method within a controller or view.
UPDATE:
You're well advised to keep your controller and model layers separate. One way of doing what you've proposed is to create a class function on the Person model wherein you explicitly pass the username of your User object from within your controller:
# in your controller
Person.create_with_username(:username => current_user.username)
# app/models/person.rb
def self.create_with_username(username)
self.create(username)
end
So yesterday I asked a question about getting the projects for a current user. Well I ran into an issue. See that thread here. So today I was working on displaying categories and tasks for the user along with any discussions. when I loaded up the page to view this I got:
NoMethodError in UsersController#show
undefined method `projects' for #<User:0xad5823f4>
Rails.root: /home/adam/Documents/Aptana Studio 3 Workspace/StartPoint
Application Trace | Framework Trace | Full Trace
app/controllers/users_controller.rb:25:in `show'
Request
Parameters:
{"id"=>"4"}
This is currently whats in my users#show method:
def show
#projects = current_user.projects
#tasks = current_user.tasks
#categories = current_user.categories
#discussions = current_user.discussions
end
the table names are projects, tasks, categories and discussions. I have no problem using this any where else so why am I seeing this error?
if you need more code I can show it. the error is pretty clear but again I use this type of call else where to display project specific information such as a projects categories or tasks. could it be something with my relationship between a user and categories, discussions, tasks and so on? because I do have user_id in each table that is listed in the show method, among others.
Also I thought of this, this morning since were on this topic: current_user seems wrong because if I click on Bobs profile I will see all my stuff no? should it not be something more specific to the users id?
Have you established the association in each model?
class User < ActiveRecord::Base
has_many :projects
end
Also be sure that current_user is actually a User object and not some thin proxy.
Generally you need to distinguish between the session user and the displayed user. This is why names like current_user are harmful. I'd recommend using session_user to refer to the logged in user and #user to refer to the user being displayed.
Some login systems define only a current_user method, but to alias this isn't hard. It's just defective by design in that case.
I am building a little application in Rails and what I am trying to do now is authenticate a user.
So I got this method in the controller class:
def login
if #user = User.authenticate(params[:txt_login], params[:txt_password])
session[:current_user_id] = #user.id
redirect_to root_url
end
end
Here is the definition of authenticate method (inside the User model class):
def self.authenticate(username, password)
#user = User.where(["username = ? AND password = ?", username, password])
return #user
end
The problem is that I get an error message saying:
undefined method `id' for #<ActiveRecord::Relation:0x92dff10>
I confirm that the user I was trying to log in really exists in the database (besides it tries to get the id of a user and this instruction is wrapped inside an if in case 0 users are returned from the authenticate method).
Why am I obtaining this error message? Knowing that when I change the User.where by User.find it works fine!
Thank you!
User.where("some_conditions") will return an array of User objects ( in simple terms ) , A User.find can return an array or a single object.( I am not sure because i don't see how you are using it )
As far what you see is ActiveRecord::Relation, this is what is returned when we call a find or a where or a order method on Rails 3 Models.
Also, You are storing password as a plain string which is a bad idea, you should use some available rails authentication plugins like Devise or Authlogic.