ruby on rails undefined method 'username' in view - ruby-on-rails

users_controller.rb
class UsersController < ApplicationController
def index
render_404
end
def show
#user = User.where(:username => params[:username])
render_404 if !#user
end
end
basically i want to get each user data based on their username because later i want to include one more table which has meta-data for each user but i keep getting the following error
undefined method `username' for #<ActiveRecord::Relation:0x007fb5dbc52ea0>
Extracted source (around line #1):
1: <%= #user.username %> profile page

#user = User.where(:username => params[:username]).first try this or #user = User.find_by_username(params[:username]). Where returns AR::Relation, not an ActiveRecord object.

Related

NoMethodError in UserController#register undefined method `save' for nil:NilClass

Trying to learn ruby on rails following Michael Hartl's tutorial, when I try to go to the registration page in the book I get this:
NoMethodError in UserController#register
undefined method `save' for nil:NilClass
here is the code from the user_controller.rb file:
class UserController < ApplicationController
def index
#title = "RailsSpace User Hub"
end
def register
#title = "Register"
if request.post? and params[:user]
#user = User.new(user_params)
end
if #user.save
flash[:notice] = "User #{#user.screen_name} created!"
redirect_to :action => "index"
end
end
private
def user_params
# Add the user attributes that you sent with post (form) to the permit
method.
params.require(:user).permit(:name, :screen_name)
end
end
It's complaining about line 11 where it says: if #user.save I'm just following the tutorial I don't know what's going on.
Try to understand what the error message is saying. You're trying to call .save on #user but where you are calling it, #user may not be defined. The problem is you can't call .save on a nil object so it throws NoMethodError.
You're logic is incorrect so you must first make sure #user is instantiating a new User instance. It should be more like this:
def register
#title = "Register"
if request.post? && params[:user]
#user = User.new(user_params)
if #user.save
flash[:notice] = "User #{#user.screen_name} created!"
redirect_to :action => "index"
else
# handle erorrs here
flash[:alert] = "Please fix errors: #{#user.errors.full_messages.inspect}"
redirect_to :back #this may need to change depending, just an example.
end
end
end
NoMethodError in UserController#register undefined method 'save' for nil:NilClass
The error is thrown because you are calling save on a nil; and it is because nil object does not have this method. the save is a instance method belonging to ActiveRecord::Base class.
The reason #user is nil is because #user is an instance variable in the UserController class which you have not given it any value. Any variable starting with # inside a class is an instance variable in Ruby.
To solve this problem, you should set a value to #user, and in this case it should be a User instance. You can either create a new user object by doing #user = User.new(user_params) or you fetch a record from the Database by doing #user = User.find(<some_id>)

Rails Create article with other user not current_user

I would like to create an article with other user not current_user and for that I'm saving in a session the id to the other user and I recover this id with a collection in the view to this point everything work fine but when I'm trying to use my helper :selected_user into my articles controller with a if sentence doesn't work here is my code:
def new
if selected_user.present?
#article = selected_user.articles.build state: :step1
render_wizard
else
#article = current_user.articles.build state: :step1
render_wizard
end
end
so, I'm asking if the selected_user.present? I would like to create the article with this user_id but else I would like to create it with the current_user
my create method is:
def create
if selected_user.present?
step = :step1
#article = selected_user.articles.build article_params_step1
#article.state = step.to_s
if #article.save
redirect_to wizard_path(next_step, article_id: #article)
else
render_wizard
end
else
step = :step1
#article = current_user.articles.build article_params_step1
#article.state = step.to_s
if #article.save
redirect_to wizard_path(next_step, article_id: #article)
else
render_wizard
end
end
end
so, yeah when I run my view the controller jump to the else section.
just for clarify my selected_user not return nil but here is the implementation:
selections_controller.rb:
class SelectionsController < ApplicationController
before_action :authenticate_user!
def create
session[:selected_user_id] = params[:user][ :user_id]
redirect_to root_path
end
end
and in my application_controller.rb:
helper_method :selected_user
def selected_user
#selected_user ||= User.find(session[:selected_user_id])
end
and in the view:
<%= form_tag( { :controller => "selections", :action => "create" } , :class => "navbar-form navbar-left") do %>
<%= collection_select(:user, :user_id, User.all, :id, :name, prompt: "Escoge cliente")%>
<%= submit_tag 'Enviar' %>
<% end %>
if I try create an article without select an user from my collection appear this error:
Couldn't find User with 'id'=
but when I select my user from the collection everything works fine. so just I want when I don't select nothing create with the current_user.
Thanks for your time !
Regards !
The reason why you were seeing the error
Couldn't find User with 'id'=
when you haven't selected a user was that the session[:selected_user_id] was nil and your old selected_user with following code was throwing the error.
def selected_user
#selected_user ||= User.find(session[:selected_user_id])
end
User.find method expects either a single id or an array of ids. If you give a single id and if it finds the relevant record in the database then it will returns that instance. If you give an array of ids and if it finds those relevant records in the database, then it will return array of those instances. But if you pass nil to it, then it will through the error Couldn't find User with 'id'= as it won't find a relevant record.
But your updated selected_user implementation:
def selected_user
#selected_user ||= session[:selected_user_id] && User.find_by_id(session[:selected_user_id])
end
is working because, first you are checking for the existence of session[:selected_user_id] value and second you are using User.find_by_id instead of User.find.
User.find_by_id either returns a single instance of the record if it finds it in the database or will return nil if it doesn't find the record. It will never through an error.
Refer to ActiveRecord#find and ActiveRecord#find_by for more info.
I'm not sure why is working and what is the different but my solution for the problem it was to add this to my selected_user method:
def selected_user
#selected_user ||= session[:selected_user_id] && User.find_by_id(session[:selected_user_id])
end
and with that I don't have the nil error and entry to the if statement without errors.

undefined method `errors' for nil:NilClass for displaying Rails validation errors

I am getting an undefined method 'errors' for nil:NilClass error when attempting to display errors in a view from validations in Rails. I followed this example Rails validation error messages displays the error messages and array, taking its answer into account.
An example of a validation I have in the user model is:
validates_length_of :dog_name, minimum: 0, maximum: 30, message: 'cannot have more than 30 characters'
View code
<% if #user.errors.any? %>
<div id="errorExplanation">
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
Users Controller
class UsersController < ApplicationController
#before_action :logged_in_user, only: [:index, :edit, :update, :destroy,
#:following, :followers]
before_filter :requireLogin
#before_action :requireDog
def requireLogin
if session[:user_id] == nil
redirect_to "/"
end
end
def requireDog
#user = User.find(session[:user_id])
if(#user.dog_name == "Empty")
redirect_to "users/new/"
end
end
def index
#users = User.all
end
def show
#user = User.find(params[:id])
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def new
#user = User.new
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
def update
#user = User.find(params[:id])
if #user.update_attributes(profile_params)
redirect_to action: "show"
# Handle a successful update.
else
render 'edit'
end
end
def following
#title = "Following"
#user = User.find(params[:id])
#users = #user.following.paginate(page: params[:page])
render 'show_follow'
end
def followers
#title = "Followers"
#user = User.find(params[:id])
#users = #user.followers.paginate(page: params[:page])
render 'show_follow'
end
def going
#title = "Going"
#user = User.find(params[:id])
#users = #user.going.paginate(page: params[:page])
render 'show_gather'
end
def create
#user = User.new(profile_params)
if #user.save
redirect_to '/users'
else
render 'new'
end
end
private
def profile_params
params.require(:user).permit(:dog_name, :photo, :dog_breed, :dog_gender, :dog_age)
end
end
In other examples the user model/controller did not need to be further modified. The user does indeed exist. Am I missing something in the model or controller?
Firstly, you'd be better switching to the new validates methods:
#app/models/user.rb
class User < ActiveRecord::Base
validates :dog_name, length: { in: 0..30, message: 'cannot have more than 30 characters'}
end
-
Secondly, instead of setting #title each time - why don't you just use action_name?
Each time you load an action, the controller_name and action_name variables are set by default, to be used either in your controller or views. Why not just use the action_name variable in your view?
#app/views/layouts/application.html.erb
<title><%= action_name if controller_name == "Users" %></title>
To answer your question, the error is caused because you're trying to invoke a method on a non-existent variable:
for nil:NilClass
Ruby has a funny way of posting exceptions for undeclared variables -- instead of outwardly saying the variable doesn't exist, it invokes it under the NilClass class.
As a developer, you're then expected to read the message of undeclared method and surmise that it's the variable which isn't set...
The fix for your problem is therefore to find why the variable is not set:
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new profile_params
redirect_to users_path if #user.save
end
end
The above should give you the ability to save the user, else it will re-render the new action (and show the error).
I think the problem you have is that you're explicitly loading the new action on validation problems, which will prevent it appending the required data.

No Method Error

I am getting a NoMethodError in Users#show undefined method 'name' for nil:NilClass on the following code.
Show view:
<% provide(:title, #user.name) %>
<div class="row">
...
Users controller:
class UsersController < ApplicationController
def new
#user = User.new
render :layout => false
end
def create
#user = User.new(user_params)
if #user.save
flash[:success] = "Welcome to the BluePlaque Explorer!"
redirect_to #user
else
render 'new'
end
end
def show
#user = User.find(params[:id])
end
private
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :password,
:password_confirmation)
end
def login
render :layout => false
end
end
The show view what displays user's profile page after successful registration. Cannot see what causes it.
NoMethodError in Users#show undefined method 'name' for nil:NilClass
Apart from the apparent fact you don't have a .name method for your User model, there is another problem highlighted by this error... that your #user variable is not set.
Rails/Ruby doesn't handle "undeclared" variables in the expected way; it assigns them to nil:NilClass - it messes up developer's minds because they think the method is the error, when really, it's the lack of #object to call the method on.
The bottom line is that you need the following:
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
#user = User.find params[:id]
end
end
This will set your #user variable, with which you'll be able to call .name or whatever:
#app/views/users/show.html.erb
<%= #user.first_name %>
--
Now... a cool trick for you:
#app/models/user.rb
class User < ActiveRecord::Base
def name
first_name + " " + last_name
end
end
This will allow you to call #user.name if #user is set!
You always have able to use try if not sure about presense
<% provide(:title, #user.try(:name)) %>

Passing parameters into model

Rails 3.0.3
ruby 1.9.2p0
The Problem:
I have a Users table which has many items, the item(s) in turn therefore belongs to the Users.
In my model item.rb i attempt to save the item along with the value for the user.id so i have:
self.User_ID = #user.id
this however give me the error
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
this is causing some confusion that it can't find this as in the show.html.erb that 'wraps' this page <%= #user.id %> displays the correct ID on the page
Many thanks in advance
** EDIT **
The Shorten action is the action upon which i want to parameter to be passed
class ItemsController < ApplicationController
def redirect
#item = Item.find_by_shortened(params[:shortened])
if #item
#redirect_to #item.original
redirect_to #item.original
else
redirect_to :shorten
end
end
def shorten
#host = request.host_with_port
#user = current_user
You need to load the #user model in every action that will require access to it. Having it render properly in the show action will not guarantee it is loaded in the update action.
Usually you need to have something like this in your controller:
class UsersController < ApplicationController
before_filter :load_user, :except => [ :index, :new, :create ]
# ...
protected
def load_user
#user = User.find(params[:user_id] || params[:id])
rescue ActiveRecord::RecordNotFound
render(:text => 'Record not found')
end
end

Resources