Devise - undefined local variable or method `current_member' - ruby-on-rails

I am using members as the Devise model. I have placed before_action :authenticate_member! in the application controller.
But when i try to use the following in the views
<%= current_member.inspect %>
Am getting the following error
undefined local variable or method `current_member' for #<#<Class:0x007fe48ad32130>:0x007fe48e389af8>
#<Class:0x007fe48ad32130>#_app_views_brands_members_index_html_erb___144793605481589474_70309807670200
app/views/brands/members/index.html.erb, line 1
<%= current_member.inspect %>
<%= link_to('Logout', destroy_brands_member_session_path, :method => :delete) %>
Member Model - app/model/member.rb
class Member < ActiveRecord::Base
# Include default devise modules. Others available are:
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
acts_as_paranoid
# Associations
belongs_to :company
accepts_nested_attributes_for :company
end
Devise Initialiser
config.default_scope = :member
Controller
class Brand::ApplicationController < ApplicationController
before_action :authenticate_member!
private
end
Members Controller brands/members_controller.rb
class Brands::MembersController < Brand::ApplicationController
def index
end
end
ROUTEs
Rails.application.routes.draw do
# devise_for :members
# Brands Routes
constraints :subdomain => "brands" do
scope :module => "brands", :as => "brands" do
# namespace :brands do
# devise_for :members
devise_for :members, controllers: {
sessions: 'brands/members/sessions',
registrations: 'brands/members/registrations',
confirmations: 'brands/members/confirmations',
passwords: 'brands/members/passwords'
}
get '/members' => 'members#index'
end
end
# API Routes
constraints :subdomain => "api" do
scope :module => "api", :as => "api" do
api_version(
module: "V1",
header: { name: "Accept", value: "application/vnd.skreem+json; version=1" },
defaults: { format: :json }
) do
# devise_for :members
# resources :products
end
end
end
end

Related

How to Remove/Disable Sign Up From Devise

I'm trying to remove/disable the user/sign_up path from Devise. I'm doing this because I don't want random people gaining access to the application. I have it partly working by adding the following in routes.rb
Rails.application.routes.draw do
devise_scope :user do
get "/sign_in" => "devise/sessions#new" # custom path to login/sign_in
get "/sign_up" => "devise/registrations#new", as: "new_user_registration" # custom path to sign_up/registration
end
...
devise_for :users, :skip => :registration
end
However, this breaks <%= link_to "Profile", edit_user_registration_path, class: "btn btn-info btn-flat" %>
which I want to keep so that users can update their profile.
I know it's because of the devise_for :users, :skip => :registration
Is there a solution for this issue?
Running
Devise (4.2.0, 4.1.1, 4.1.0)
Rails 4.2.5
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]
The easiest way is just removing :registerable devise module from the default list defined into your Model (the class name used for the application’s users, usually User).
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
...
end
So you'll have it like this:
class User < ActiveRecord::Base
devise :database_authenticatable,
:recoverable, :rememberable, :trackable, :validatable
...
end
Solution to removing sign_up path from Devise
Enter the following at the beginning of routes.rb
Rails.application.routes.draw do
devise_scope :user do
get "/sign_in" => "devise/sessions#new" # custom path to login/sign_in
get "/sign_up" => "devise/registrations#new", as: "new_user_registration" # custom path to sign_up/registration
end
...After the statement above, add the following below in routes.rb
devise_for :users, :skip => [:registrations]
as :user do
get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
put 'users' => 'devise/registrations#update', :as => 'user_registration'
end
This will remove/disable the user/sign_up path for Devise without breaking edit_user_registration_path
Restart your rails server and it should work.
I just had the same issue. My solution is a mix of these answers.
Comment out or remove :registerable in user.rb:
class User < ActiveRecord::Base
devise :database_authenticatable, #:registerable,
:recoverable, :rememberable, :trackable, :validatable
end
Remove the registration paths from devise_for in routes.rb:
devise_for :users, :skip => [:registrations], controllers: {
sessions: 'users/sessions'
}
Now Devise will skip all of the registration links from their view and also you no longer have the registration paths on your routes.
Redirecting from controller
I solved this issue by redirecting /sign_up to /sign_in from the controller, while preserving the functionality of editing user info. For instance:
In controllers/users/registrations_controller.rb
# GET /resource/sign_up
def new
redirect_to new_user_session_path and return
super
end
In routes.rb, I pointed registrations resource to this controller:
devise_for :users, controllers: {
sessions: 'users/sessions',
registrations: 'users/registrations'
}
So whenever users visit route /sign_up, it'll redirect them to /sign_in. Just remember to use and return after the redirection to prevent multiple render/redirect
Since as is just an alias for devise_scope, you can put all that in just one block.
devise_for :users, skip: [:registrations]
as :user do
get "/sign_in" => "devise/sessions#new" # custom path to login/sign_in
get "/sign_up" => "devise/registrations#new", as: "new_user_registration" # custom path to sign_up/registration
get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
put 'users' => 'devise/registrations#update', :as => 'user_registration'
end
Below code seem to do the trick for me:
Rails.application.routes.draw do
devise_scope :users do #notice "users" here, not "user"
get "/sign_in" => "devise/sessions#new" # custom path to login/sign_in
get "/sign_up" => "devise/registrations#new", as: "new_user_registration" # custom path to sign_up/registration
end
devise_for :users, :skip => [:registrations]
as :user do
get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
put 'users' => 'devise/registrations#update', :as => 'user_registration'
end
...

Devise Current User Can't Get Nested Data to Show in View

I'm trying to make an example app to learn about namespace/scopes/modules
Normally I would user current_user helper but I have Client::Addresses nested in behind and would like to grab say the user's city and just display it on their edit page (devise registration/edit screen)
<%= current_user.?? %>
Using the line below. I also added inverse_of as my understanding it'll reverse the relationship as well but no avail.
<%= #user.addresses.cacity %>
I think this is pretty close #user.id works but adding the rest error reads. Looks like I also dealt with strong params just not sure. I'm doing this to practice namespacing:scopes/modules:
undefined method `cacity' for #<ActiveRecord::Associations::CollectionProxy []>
It would be great to do something like.
<%= current_user.addresses.cacity %>
Here's some additional information with what I got so far, let me know if additional info is needed.
routes.rb
Rails.application.routes.draw do
namespace :client do
resources :subscriptions
end
# Security Devise Setup
devise_for :admins
devise_for :users
# Main Pages
root 'website/page#index'
# Client Sections
resources :users do
scope module: "client" do
root :to => 'dashboard#index'
resources :addresses
end
end
namespace :admin do
root :to => 'panel#index'
end
end
user.rb
class User < ActiveRecord::Base
include Gravtastic
gravtastic
# Devise Settings
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
# Model Relationships
has_many :addresses, :inverse_of => :user, class_name: 'Client::Address'
end
client/address.rb
class Client::Address < ActiveRecord::Base
belongs_to :user, :inverse_of => :addresses
end
#user.addresses
is a collection, and you send a (instance) method cacity to a collection, which, as errors states, do not respond to it.
#user.addresses.first.cacity would work.
You could limit the relation to has_one:
has_one :address #...
Which will allow you to use the following:
#user.address.cacity

Multiple devise user type root routes

I have just set up my STI structure with a Devise User model. I have two user types (business and lender) and would like them to be sent to separate root paths after signing in. My models look like this:
user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :type
end
lender.rb
Class Lender < User
end
business.rb
Class Business < User
end
My routes file looks like:
Lendingloop::Application.routes.draw do
# User route
devise_for :users, skip: [:registrations]
# Lending routes
devise_for :lenders, skip: :sessions
authenticated :lender do
root :to => "LenderAccount#dashboard", :as => "lender_authenticated_root"
end
#Business routes
devise_for :businesses, skip: :sessions
authenticated :business do
root :to => "BusinessAccount#dashboard", :as => "business_authenticated_root"
end
# Error Routes
get "/404", to: 'errors#not_found'
get "/422", to: 'errors#unacceptable'
get "/500", to: 'errors#internal_error'
# Root route
root :to => 'StaticPages#landing'
end
As you can see I have an authenticated do block which I would like to redirect lenders and businesses to their specific root pages. I have a LenderAccount and BusinessAccount controller setup with dashboard actions in them and corresponding views.
When I log in as a lender or a business, I'm redirected to my root_path which is 'StaticPages#landing'. That should only be for non-logged in users.
Update
I went through the devise documentation and added the following to my application_controller.rb file:
def after_sign_in_path_for(user)
if user.type == "Business"
business_authenticated_root_path
elsif user.type == "Lender"
lender_authenticated_root_path
else
root_path
end
end
I am also seeing a strange error in my console when I attempt to go to the dashboard page directly from lender_authenticated_root_path:
Rendered /Users/questifer/.rvm/gems/ruby-1.9.2-p320#rails3tutorial/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/routing_error.erb within rescues/layout (0.7ms)
[2014-04-22 12:31:31] ERROR Errno::ECONNRESET: Connection reset by peer
/Users/bvlaar/.rvm/rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/webrick/httpserver.rb:56:in `eof?'
/Users/bvlaar/.rvm/rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/webrick/httpserver.rb:56:in `run'
/Users/bvlaar/.rvm/rubies/ruby-1.9.2-p320/lib/ruby/1.9.1/webrick/server.rb:183:in `block in start_thread'
Does anyone have an idea as to how I can get these authenticated blocks to handle the proper root redirects?
I got the roots working by changing my routes.rb file to:
routes.rb
root :to => 'business_account#dashboard', :constraints => lambda { |request| request.env['warden'].user.class.name == 'Business' }, :as => "business_root"
root :to => 'lender_account#dashboard', :constraints => lambda { |request| request.env['warden'].user.class.name == 'Lender' }, :as => "lender_root"
Now my two user types can login to their accounts and be directed to their respective controllers and dashboards.
I think I can help. I had a similar problem. In my routes.rb file I created a "home" screen for non-logged in users.
Rails.application.routes.draw do
root "home#index"
devise_for :users
resources :home
resources :dashboard
The home_controller.rb looks like this:
class HomeController < ApplicationController
def index
if user_signed_in?
redirect_to :controller=>'dashboard', :action =>'index'
end
end
end
dashboard_controller.rb looks like this, and is only for logged in users:
class DashboardController < ApplicationController
before_filter :authenticate_user!
def index
end
end
The views for each (home.html.erb & dashboard.html.erb) can then reflect content for visitors or logged in users.
I used this tutorial to sort it out. I don't know if it's overkill or not, this is my first application, but ti seems to be what you are asking for.
http://www.tonylea.com/2012/rails-authentication-with-devise/
Hope that helps.

rails_admin Routing Error

I installed for my app RailsAdmin, but I can't go to the admin panel. After authorization I have routing error:
Routing Error
No route matches [GET] "/admin"
Try running rake routes for more information on available routes.
/config/routes.rb
1.mount RailsAdmin::Engine => '/adminpanel', :as => 'rails_admin'
/config/initializers/rails_admin.rb
1.RailsAdmin.config do |config|
2. config.authorize_with :cancan
3.end
/app/models/ability.rb
1.class Ability
2. include CanCan::Ability
3. def initialize(user)
4. if user.class.to_s == "Admin"
5. can :access, :rails_admin
6. can :manage, :all
7. elsif user.class.to_s == "User"
8. can :manage, :read
9. end
10. end
11.end
Also I have Admin model
/app/models/admin.rb
class Admin < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
# attr_accessible :title, :body
end
But if I add in my routes.rb this:
mount RailsAdmin::Engine => '/admin', :as => 'rails_admin'
I have cyclic forwarding.
Please help me with this problem.
Try putting these two lines at the bottom part of your routes:
mount RailsAdmin::Engine => '/adminpanel', :as => 'rails_admin'
root :to => redirect('/adminpanel')

Devise with OmniAuth for facebook login

I am new to rails and I would like to allow user login/registration to my site with Devise and Omniauth.
So I followed OmniAuth: Overview (https://github.com/plataformatec/devise/wiki/OmniAuth%3a-Overview). But I can't get it working, it is showing this error shown below when I try test it on heroku production.
NoMethodError in Users::OmniauthCallbacksController#facebook
undefined method `find_for_facebook_oauth' for #<Class:0x007f9bc0a3aa30>
& below are my codes which should be the same as OmniAuth: Overview, any help will be much appreciated.
user.rb
class User < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, #:recoverable
:rememberable, :trackable, :validatable, :omniauthable, :omniauth_providers => [:facebook]
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :address, :mobile, :provider, :uid
# attr_accessible :title, :body
has_many :pins, :dependent => :destroy
end
def self.find_for_facebook_oauth(auth, signed_in_resource=nil)
user = User.where(:provider => auth.provider, :uid => auth.uid).first
unless user
user = User.create(name:auth.extra.raw_info.name,
provider:auth.provider,
uid:auth.uid,
email:auth.info.email,
password:Devise.friendly_token[0,20]
)
end
user
end
Devise.rb
# so you need to do it manually. For the users scope, it would be:
# config.omniauth_path_prefix = "/my_engine/users/auth"
config.secret_key = '75f6735f226e8ea0484f2abd55f78efee516306e8a0e69ac2cd68f50ce0f44078af9b3497bf49db3874a523c573b2e22eec01d508f703e32887de8c8f44740cb'
require "omniauth-facebook"
config.omniauth :facebook, "3223424", "52341341341134", :strategy_class => OmniAuth::Strategies::Facebook
{:scope => 'email, offline_access', :client_options => {:ssl => {:ca_file => '/usr/lib/ssl/certs/ca-certificates.crt'}}}
My Gemfiles
gem 'omniauth'
gem 'omniauth-facebook'
gem 'oauth2'
Routes.rb
Dine::Application.routes.draw do
get "home/index"
resources :pins
resources :pin
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
match 'users/:id' => 'users#show', as: :user
root :to => 'pins#index'
get 'about' => 'pages#about'
get 'weekly' => 'pages#weekly'
get 'shop' => 'pages#shop'
get 'service' => 'pages#service'
get 'privacy' => 'pages#privacy'
get 'test' => 'pages#test'
get 'recipies' => 'pages#recipies'
get 'know' => 'pages#know'
get 'give' => 'pages#give'
get 'how' => 'pages#how'
match 'contact' => 'contact#new', :as => 'contact', :via => :get
match 'contact' => 'contact#create', :as => 'contact', :via => :post
match 'inform' => 'inform#new', :as => 'inform', :via => :get
match 'inform' => 'inform#create', :as => 'inform', :via => :post
as :user do
match '/user/confirmation' => 'confirmations#update', :via => :put, :as => :update_user_confirmation
end
devise_for :users, :controllers => { :confirmations => "confirmations" }
end
users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
# You need to implement the method below in your model (e.g. app/models/user.rb)
#user = User.find_for_facebook_oauth(request.env["omniauth.auth"], current_user)
if #user.persisted?
sign_in_and_redirect #user, :event => :authentication #this will throw if #user is not activated
set_flash_message(:notice, :success, :kind => "Facebook") if is_navigational_format?
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
Thanks again guys.
the find_for_facebook_oauth should be in the User class. like:
class User < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable,
:registerable,
:rememberable,
:trackable,
:validatable,
:omniauthable,
:omniauth_providers => [:facebook]
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :address, :mobile, :provider, :uid
has_many :pins, :dependent => :destroy
def self.find_for_facebook_oauth(auth, signed_in_resource=nil)
user = User.where(:provider => auth.provider, :uid => auth.uid).first
unless user
user = User.create(name:auth.extra.raw_info.name,
provider:auth.provider,
uid:auth.uid,
email:auth.info.email,
password:Devise.friendly_token[0,20])
end
user
end
end

Resources