I defined a helper class as below
module SessionsHelper
def current_user
#current_user= User.find_by_fbid(session[:fbid])
end
def sign_in(user)
session[:fbid] = user.fbid
#current_user = user
end
def signed_in?
!current_user.nil?
end
end
I included the Helper Class in my Application Controller
class ApplicationController < ActionController::Base
protect_from_forgery
include SessionsHelper
end
The sign in method gets called from Session Controller
class SessionsController < ApplicationController
def create
user = User.find_or_create_by_fbid(params[:user][:fbid])
user.update_attributes(params[:user])
sign_in(user)
redirect_to user_path(user)
end
end
However I am not able to access 'current_user' variable from users#show view.
<% if signed_in? %>
<p>
<b>Current User:</b>
<%= current_user.name %>
</p>
<% end %>
It says : undefined method `name' for nil:NilClass
Can anyone please advise ?
The method current_user does not get called at all from index.
Putting include SessionsHelper in your controller includes those module methods in the controller, so they are accessible in your controller methods. You want the helper methods available in your views, so you need to use helper SessionsHelper in your application controller.
That being said, I do agree with Jits that the methods you have in SessionsHelper really do belong in the controller instead of in a helper.
Generally you should have methods like current_user defined in your application_controller and then make them available as helpers in the views. This way the controllers have access to them (and trust me, you will most likely need access to things like that). Example:
def current_user
..
end
helper :current_user
What helped me:
Define methods to use in the controller in helper files
Define methods to use in the view in the relevant model file
Example
Suppose you had this in user_helper.rb
def something
2 + 2
end
simply move that code into
models/user.rb
and it will be accessible in the view without any further effort.
Related
I'm learning rails.
I'm build a simple test application, with a simple authentication scheme.
I'm using a user.role field to group the users.
In my Application Helper i have:
module ApplicationHelper
def current_user
if session[:user_id]
#current_user ||= User.find(session[:user_id])
else
#current_user = nil
end
end
def user_identity
current_user.role if current_user
end
end
Now, in my app, i can use current_user in all controllers as expected, but instead user_identity is not visible.
why?
The application_helper is used mainly to access methods in views - I don't believe it's available in a controller.
The reason your 'current_user' method appears to work is that I'm assuming you're using Devise - when you call 'current_user' it is using the Engine's method rather than your own.
To solve this, write out a new module:
module MyHelper
def current_user
if session[:user_id]
#current_user ||= User.find(session[:user_id])
else
#current_user = nil
end
end
def user_identity
current_user.role if current_user
end
end
And in the controller you're using:
class MyController < ApplicationController
include MyHelper
bla bla bla...
end
Any methods defined in MyHelper will now be available in MyController, as we've included the module in the controller
Helper modules are mixed into the view context (the implicit self in your views) - not controllers.
So you can call it from the controller with:
class ThingsController < ApplicationController
# ...
def index
view_context.user_identity
end
end
Or you can include the helper with the helper method:
class ThingsController < ApplicationController
helper :my_helper
def index
user_identity
end
end
But if you're writing a set of authentication methods I wouldn't use a helper in the first place. Helpers are supposed to be aids for the view.
Instead I would create a concern (also a module) and include it in ApplicationController:
# app/controllers/concerns/authenticable.rb
module Authenticable
extend ActiveSupport::Concern
def current_user
#current_user ||= session[:user_id] ? User.find(session[:user_id]) : nil
end
def user_identity
current_user.try(:role)
end
end
class ApplicationController < ActionController::Base
include Authenticable
end
Since the view can access any of the controllers methods this adds the methods to both contexts.
So I have an Admin namespace, and a sessions controller within it.
There was also a admin/sessions_helper.rb made when I generated the controller, so I've been putting some methods in that, however I don't seem to be able to call them. Is this down to the namespace?
Error
undefined local variable or method `sign_out' for #<Admin::SessionsController:0x007fe2b2f55680>
def destroy
sign_out
redirect_to admin_path
end
end
sessions_controller.rb
class Admin::SessionsController < AdminController
...
def destroy
sign_out
redirect_to admin_path
end
end
admin/sessions_helper.rb
module Admin::SessionsHelper
...
def sign_out
self.current_user = nil
cookies.delete(:remember_token)
end
end
Note that I'm not including the helper anywhere, because in the docs it says that all helpers are included by default.
Helpers are not available in the controller. Helpers are designed to be mixed into the view context.
There are workarounds to make the helper available to both the view and the controller, but it should actually make sense. The sign_out method you defined would not make sense at all in the view.
I suggest you to define it in the AdminController (that looks to be the base controller all admin controller inherits from).
module AdminController
...
private
def sign_out
self.current_user = nil
cookies.delete(:remember_token)
end
end
Be sure to flag it as private or Rails could potentially use it as a controller action.
A nice way to call helper methods from a controller without including the module is with view_context:
class Admin::SessionsController < AdminController
def destroy
view_context.sign_out
redirect_to admin_path
end
end
But I agree with #simone-carletti, this doesn't feel like a helper method.
I am having a action in application controller
def is_customer_logged_in?
!!session[:customer_id]
end
And in my view am trying to access the application_controller action like this
<% unless is_customer_logged_in? %>
some functions
<% end %>
The above code is a partial layouts.
This is the error message I am facing
undefined method `is_customer_logged_in?' for #<#<Class:0xb51a5300>:0xb5616484>
You can define it to be a helper method and you should be able to access that method in the view.
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def is_customer_logged_in?
!!session[:customer_id]
end
helper_method :is_customer_logged_in?
end
try helper_method: is_customer_logged_in?
I'm trying give a "Welcome Message" to my users with that:
#welcome_controller.rb
class WelcomeController < ApplicationController
def hi
#current_user
if (#current_user)
#welr = '¡Bienvenido' + current_user + ' a nuestra web!'
else
#weli = "¡Bienvenido invitado, no dude en registrarse!"
end
end
end
#hi.html.erb Only the call
<%= hi %>
When I initialize my server the controller give me this message:
undefined local variable or method `hi' for
I have tried many wways of repairing this but I can't.
You need to define hi as a helper_method in your controller. Something like
class WelcomeController < ApplicationController
helper_method :hi
def hi
# your stuff here...
end
end
See http://apidock.com/rails/AbstractController/Helpers/ClassMethods/helper_method for more info
That's not how you use controller methods. In Rails, methods defined on a controller are used to 'set up' the data needed for a particular view, or to handle a given request. They're not supposed to be called directly by a view.
For what you're trying to do, you need to add a helper method to WelcomeHelper. So, assuming you want http://yourapp.dev/welcome/ to output the message above, this is what you'd need:
# app/controllers/welcome_controller.rb
class WelcomeController < ApplicationController
def index
# Explicitly defining the `index` method is somewhat redundant, given
# that you appear to have no other logic for this view. However, I have
# included it for the sake of example.
end
end
# app/views/welcome/index.html.erb
<%= greeting %>
# app/helpers/welcome_helper.rb
class WelcomeHelper
# All methods in WelcomeHelper will be made available to any views
# that are part of WelcomeController.
def welcome
if (#current_user)
# You may need to change this to something like `#current_user.name`,
# depending on what #current_user actually is.
'¡Bienvenido' + #current_user + ' a nuestra web!'
else
"¡Bienvenido invitado, no dude en registrarse!"
end
end
end
This article may help you :
Ruby on Rails: Accessing Controller Methods from Your View
Just write:
<% #controller.hi %>
I created a helper method for some simple calculation. This helper method will just return an integer. I need the helper in both controllers and views.
Unfortunately, it work well in views but not in controllers. I get the undefined local variable or method error. How can I fix it?
Thanks all
In order to use same methods in both controller and views Add you method in application_controller.rb and make it helper methods.
For example
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
#protect_from_forgery # See ActionController::RequestForgeryProtection for details
helper_method :current_user
def current_user
session[:user]
end
end
Now you can use method current_user in both controllers & views
I use a following solution. Because I think helper's methods shoud be stored in an appropriate helper module.
module TestHelper
def my_helper_method
#something
end
end
class SomeController < ApplicationController
def index
template.my_helper_method
end
end