Using devise current_user - ruby

I have a user and an address for example and the relation is as follows:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_one :address
end
class Address< ActiveRecord::Base
belongs_to :user
end
Now when I create an address object, I want to be able to pass through the current_user id and save it to the address model, so in my controller I have
before_filter :authenticate_user!
def new
#address= current_user.address.new
end
def create
#address= current_user.address.new(address_params)
if #address.save
redirect_to root_path, notice: 'Address Successfully Created'
else
render action: 'new'
end
end
private
def address_params
params.require(:address).permit(:id, :user_id, :add_1, :add_2, :add_3)
end
I can't access the new action at the moment, as the error I am getting is
undefined method `new' for nil:NilClass
What am I missing?

I think you should do it like this:
def new
#address = current_user.build_address
end
And same in create action
More info here

Related

Calling a Associated Controller Method Not Working

I have 3 models of User, Role and UserRole with their respective controllers as UsersController, RolesController and UserRolesController.
I have a method in the UserRoles controller which I would want to access through the Users controller but I keep having errors as explained below.
I have tried various means of even moving the method def self.add_roles_to_user(user, role) from the UsersRoles controller into the UserRole model and call it but I keep having the same error.
I have gone through lots of similar questions and various blogs, including those on this platform such as Calling a method from controller, and others but to no good results.
class UserRole < ApplicationRecord
# many-to-many association using join table with roles and user
belongs_to :user, inverse_of: :user_roles
belongs_to :role, optional: true, inverse_of: :user_roles
end
class User < ApplicationRecord
has_many :user_roles, inverse_of: :user
has_many :roles, through: :user_roles
end
class Role < ApplicationRecord
# table associations between role and user
has_many :user_roles, inverse_of: :role
has_many :users, through: :user_roles
end
class UserRolesController < ApplicationController
def self.add_roles_to_user(user, role)
if ! user.nil?
if role.length > 0
role.each do |sel_role|
#u_role = UserRole.new
#u_role.user_id = user_id
#u_role.role_id = sel_role.role_id
#u_role.save
end
end
end
end
end
class Users::RegistrationsController < Devise::RegistrationsController
def create_user
respond_to do |format|
if #user.save
# add roles
UserRoles.add_user_roles(params[:user], params[:role])
end
end
end
end
I am calling the add_uer_to_role method in the User controller when I am adding or creating a new user.
What I have noticed is that I keep getting different errors based on how I call the method.
For example, I expect to have no errors when I call the method like; UserRoles.add_roles_to_user(params[:user], params[:role]) but it gives the error NameError (uninitialized constant Users::RegistrationsController::UserRoles):
Hoping a good samaritan will come to my aid as soon as possible. Thanks in advance
If it is a common function, you can define it in application controller and call it. Else you can define in helper.
Please verify Calling a method from another controller
You can use that function as a module and use it:
# lib/common_stuff.rb
module CommonStuff
def common_thing
# code
end
end
# app/controllers/my_controller.rb
require 'common_stuff'
class MyController < ApplicationController
include CommonStuff
# has access to common_thing
end

Devise Override RegistrationController issue with resource.active_for_authentication?

I want to override this controller, in this moment the create method, I already made a little change on it
class RegistrationsController < Devise::RegistrationsController
def create
unless session[:invitation_token].blank?
super
else
redirect_to new_user_session_path and return
end
end
end
after following the flow of sign up the resource is created in the database like the super class define it
def create
build_resource
if resource.save
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_navigational_format?
sign_up(resource_name, resource)
respond_with resource, :location => after_sign_up_path_for(resource)
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
expire_session_data_after_sign_in!
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
respond_with resource
end
end
but in some way there is a problem with the method active_for_authetication?
Is throwing false and I can't figure out why I checked all the gem and it says that the method is overridden by other modules the normal definition is
def active_for_authentication?
true
end
but I don't use any of the modules that override it so for some reason it seems like devise its not being able to succeed that validation but the user is stored in the database and I'm signed in after registration.
This is my configuration for register a user.
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, :username
end
This is my Initializer for devise
Devise.setup do |config|
config.mailer_sender = "please-change-me-at-config-initializers-devise#example.com"
require 'devise/orm/active_record'
config.case_insensitive_keys = [ :email ]
config.strip_whitespace_keys = [ :email ]
config.skip_session_storage = [:http_auth]
config.stretches = Rails.env.test? ? 1 : 10
config.password_length = 6..15
config.reset_password_within = 6.hours
config.sign_out_via = :delete
end

ActiveModel::MassAssignmentSecurity::Error in ApiUsersController#create

I am not able to create new api_user. Everytime I try to create it I get
Can't mass-assign protected attributes: utf8, authenticity_token, api_user, commit, action, controller
here's my model api_user.rb
class ApiUser < ActiveRecord::Base
attr_accessible :api_key, :count, :email, :name, :organization
end
controller api_users_controller.rb
class ApiUsersController < ApplicationController
#skip_before_filter :verify_authenticity_token
def new
#api_user = ApiUser.new
end
def create
#api_user=ApiUser.create(params)
render :text=>"#{#api_user.id}"
end
def destroy
#api_user=ApiUser.find(params[:id])
#api_user.destroy
render :text=>"Deleted successfully"
end
end
I am using Ruby 1.9.2 and Rails 3.2.3
In order to create the ApiUser, you should use only the correct params:
#api_user=ApiUser.create(params[:api_user])
not all the paramshash

Rails 3 - Devise: users route

I am using devise with CanCan. I am using my user model.
My user index page is localhost:3000/users (It is enabled just for :administrator role).
The problem is that CanCan (or Devise) is not checking for authorization on this route. All other routes (i.e. localhost:3000/tasks) are being checked. i.e. If I logout of the system and type the users index page it displays its content. If I type the tasks route it redirects me to the login screen (correct behaviour).
I think that this is happening because of Devise's routes.
My simplified User model is:
class User < ActiveRecord::Base
has_and_belongs_to_many :roles
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :name, :role_ids, :role, :email, :password, :password_confirmation, :remember_me
def role?(role_check)
self.roles.each do |role|
return true if (role.name.eql? role_check.to_s.humanize )
end
return false
end
def role=(role_id)
self.roles.clear
self.roles << Role.find(role_id)
end
def role
self.roles.first unless self.roles.length == 0
end
end
My Routes are the following:
devise_for :users
resources :users
devise_for :users, :controllers => { :registrations => "users/registrations" }
My ability.rb is the following (I havenĀ“t defined yet, it is allowing all):
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user
if user.role? :administrator
can :manage, :all
elsif user.role? :department_header
can :manage, :all
elsif user.role? :staff
can :manage, :all
end
end
end
How can I fix this?
Thanks!
My problem was on the following line:
load_and_authorize_resource :only => [:show,:new,:destroy,:edit,:update]
I have to include :index

"undefined method" for a rails model

I am using Devise with rails and i want to add a method "getAllComments", so i write this :
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 :email, :password, :password_confirmation, :remember_me, :city, :newsletter_register, :birthday, :postal_code,
:address_complement, :address, :lastname, :firstname, :civility
has_many :hotels_comments
class << self # Class methods
def getAllComments
true
end
end
end
And in my controller :
def dashboard
#user = current_user
#comments = #user.getAllComments();
end
And when i go to my url, i got
undefined method `getAllComments' for #<User:0x00000008759718>
What i am doing wrong?
Thank you
Because getAllComments is a class method and you are attempting to access it as an instance method.
You either need to access it as:
User.getAllComments
or redefine it as an instance method:
class User < ActiveRecord::Base
#...
def getAllComments
true
end
end
def dashboard
#user = current_user
#comments = #user.getAllComments
end
As I can see, you make getAllComments as class method through addition it to eigenclass. And you try to call this method from instance.
Content of class << self means class method. It could be shortened as def self.getAllComments
You should call it User.getAllComments and not #user.getAllComments
The getAllComments() method that you wrote is a class method
So the correct way to call the methods is
#comments = User.getAllComments
But if you really want to scope the getAllComments to the current user, I recommend you write an instance method
class User < ActiveRecord::Base
..
def getAllComments
// comments implementation
end
So that way you can access the getAllComments method like so:
#user = current_user
#comments = #user.getAllComments

Resources