I have integrated devise in a pre-existing "User" Model. Here it is how it looks like
User.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
include AstroModels::Users::Validation
when i browse any authentication page. i get following error
ActionView::Template::Error (undefined method `[]' for nil:NilClass):
I have debug it using <%resource.inspect%> , i get following error,
<#User not initialized>
on the following line
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
Also, i tried a stack overflow answer by changing
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
to
**<%= form_for(resource_name, :as => resource, :url => session_path(resource_name)) do |f| %>**
But doesn't seem work. Just for info i'm integrating devise in an application that uses rails4.
For just more iinfor i have following in my application helper file.
def resource_name
:user
end
def resource
#resource ||= User.new
end
def devise_mapping
#devise_mapping ||= Devise.mappings[:user]
end
Any suggestion/workaround would be great help thanks.
In my case i was inheriting my custom User Model with ActiveRecord::Base class and by ActiveRecord::Base when we inherit any class with it we can not have our own initialize method in that custom model. So i commented out initialize method in my custom model and the error was gone.
Hope it will help you.
You didn't mention routes.rb or the views you need to create a session, which initializes user. Have you completed those tasks? You should start with the Devise installation generator to add in the code including initializers:
rails generate devise:install
routes.rb has to include devise_for that is set for your application. An example, not necessarily complete for you:
Sampleapp::Application.routes.draw do
root :to => "home#index"
devise_for :users, :controllers => {:registrations => "registrations"}
resources :users
end
You can access the views in the Devise gem, or you can copy them to your own application so they can be customized like this:
rails generate devise:views
This will provide app/views/devise views as well as app/views/layouts needed to login and create a session, among others.
Related
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
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.
Situation:
I have an Account model which is a devise model and I'm looking to disable users from being able to register themselves. There is a similar question on SO already but the proposed answer is just not working for me and it also does not have any templates in the answer.
Here's my setup:
registrations/edit.html.erb
<%= form_for resource, as: resource_name, url: account_registration_path(resource_name), html: { method: :patch } do |f| %>
...
<% end %>
I had to change the url: from registration_path to account_registration_path for the form to even render.
The problem is I cannot submit the form without it throwing an error. It errors out with:
ActionController::UnknownFormat in Devise::RegistrationsController#update
routes.rb
devise_for :accounts, skip: [:registrations]
as :account do
get "accounts/edit" => 'devise/registrations#edit', as: 'edit_account_registration'
patch "accounts" => 'devise/registrations#update', as: 'account_registration'
#delete "account" => 'devise/registrations#destroy', as: 'destroy_account_registration'
end
Is it possible to somehow set this up in such a way that the url paths for editing the profile are identical to the ones devise supplies when registrations is not disabled?
I still want users to be able to edit/cancel their account, just not register.
In your devise model (Account), you can remove (or comment out) the registerable plugin from the devise modules section. An example of what it could look like before would be this:
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
And after:
devise :database_authenticatable, #:registerable,
:recoverable, :rememberable, :trackable, :validatable
You can read more about that module here.
If you just want the register ability removed, here is another workaround. You can create your own DeviseRegistrationsController, like is demonstrated here, and then in the new action, just set a redirect to the root URL. You can also delete the view (if you have generated them).
My sessions_controller is as follows:
class SessionsController < ApplicationController
require 'omniauth-facebook'
require 'omniauth'
def create
#user = User.find_or_create_from_auth_hash(auth_hash)
self.current_user = #user
redirect_to '/'
end
protected
def auth_hash
request.env['omniauth.auth']
end
end
So... it's THERE isn't it?
Here's my users.rb file:
class User < ActiveRecord::Base
acts_as_voter
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
# attr_accessible :title, :body
has_many :posts
has_many :tasks
end
And my routes file:
LiquidAdmin::Application.routes.draw do
devise_for :users
get '/auth/:provider/callback', to: 'sessions#create'
resource :sessions, :only => :create
get "home/bandwall"
get "home/index"
root :to => "home#index"
So where's the problem? "auth_hash" is clearly defined... The SessionsController is loading... so why is it complaining about no method for find_or_create_from_auth_hash?
In Rails 3.2, the method you'll want to use is called first_or_create:
User.where(auth_hash: auth_hash).first_or_create
According to the Rails 3.2 release notes:
Add first_or_create, first_or_create!, first_or_initialize methods to
Active Record. This is a better approach over the old
find_or_create_by dynamic methods because it's clearer which arguments
are used to find the record and which are used to create it.
Given this, the following is made possible through the query:
User.where(auth_hash: auth_hash).first_or_create(foo: 'bar') # Assuming no other User entries exist
#=> #<User id: 1, auth_hash: "your_auth_hash", foo: "bar">
User.where(auth_hash: auth_hash).first_or_create(foo: 'baz')
#=> #<User id: 1, auth_hash: "your_auth_hash", foo: "bar">
Given that this question is based on OmniAuth, I think a better answer would be:
#user = User.where(auth_hash).first_or_create
or if in Rails version greater than 4.1.14
#user = User.where(uid: auth_hash[:uid], provider: auth_hash[:provider]).first_or_create
auth_hash is not a field in the User model, but rather a Hash of fields that could be on the User model.
I'm using Devise 1.5.1 in a Rails 3.0.3 app. It works well, with one exception: The signout link gives me this error:
Routing Error
uninitialized constant UsersController
The link that leads to this is:
<%= link_to('Logout', destroy_user_session_path, :method => :delete) %>
I haven't created an app/controllers/user_controller.rb file, but my understanding that this wasn't necessary when using Devise, correct?
In case it's relevant, my routes.rb file looks like:
Su::Application.routes.draw do
get "group/create"
devise_for :users
resources :users
resources :payers
resources :payments
resources :categories
resources :groups
match "adduser", :to => "groups#adduser"
root :to => "pages#home"
end
...and app/models/user.rb looks like:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :first_name, :email, :password, :password_confirmation, :remember_me, :group_id
end
I have googled and searched on SO extensively, but to no avail. How should I troubleshoot something like this?
In your routes file, you have
devise_for :users
which serves for the routes for Devise, but
resources :users
is a generic CRUD route, which makes Rails to think that in your app, you have Users Controller, and that you are doing something with the Users model in your model.
The error tells that you don't have a Users Controller and that's true, but it's looking for it because of the route.
So, either delete the line or add a Users Controller if you want to do something with the Users model.
If anything is not clear, post it as a comment.