I have the following classes in my model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
has_one :list
end
and
class List < ActiveRecord::Base
belongs_to :user
end
Now I want to create a new list button on my list/show page where I can create a new list for a current_user.
def new
#list = List.new
end
def create
#list = current_user.list.build(params.require(:list).permit(:title))
if #list.save
redirect_to #list, notice: "List was saved successfully."
else
flash[:error] = "Error creating list. Please try again."
render :new
end
end
But something goes wrong in my create function. I makes sense cause also when I open rails c and try:
u = User.first => validated user
u = List.new
I get the error that list is not method for u (my user). What goes wrong?
You didn't provide information about error, but I guess interpreter complains about calling build method on nil. It's because you call:
#list = current_user.list.build(params.require(:list).permit(:title))
but current_user.list returns nil. You should have this instead:
#list = current_user.build_list(params.require(:list).permit(:title))
Documentation for has_one method
Related
I have a User model:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_one :profile, dependent: :destroy
after_create :build_profile
end
So when the user registers, there profile is created and they are redirected to the edit_profile_page
class RegistrationsController < Devise::RegistrationsController
protected
def after_sign_up_path_for(resource)
edit_profile_path(current_user)
end
end
In my profile model I'm trying to set some validation
class Profile < ApplicationRecord
belongs_to :user
...
validates :name, presence: true
end
Im also using the friendly_id gem
profile_controller.rb
def set_profile
#profile = Profile.friendly.find(params[:id])
end
The error I'm getting is when I register a new user is:
Couldn't find Profile with 'id'=6
This only happens when I try to apply the validates :name, presence: true, without this my application works fine. I need a way to validate the name after the user is registered, after the profile model is created.
Im also getting the error at this line:
def set_profile
#profile = Profile.friendly.find(params[:id])
end
build_profile in after_create builds a profile but it doesn't persist it. It's not created in the database.
Better might be...
def after_sign_up_path_for(resource)
new_profile_path
end
In your controller
def new
#profile = current_user.build_profile
...
end
def create
#profile = current_user.build_profile
if #profile.update_attributes(profile_params)
...
end
...
end
Hello everyone I am new to rails and for some reason I keep getting an error
undefined method 'user' for nil:NilClass.
I have pasted an image of the error on the bottom and I posted the code below.
Image Error
# registeredapps_controller.rb
class RegisteredappsController < ApplicationController
def create
#registeredapp = Registeredapp.new(registeredapp_params)
#registeredapp.user = current_user
unless RegisteredappPolicy.new(current_user, #registeredapp).create?
flash[:alert] = "not authorized"
redirect_to user_registeredapps_path(current_user.id)
end
if #registeredapp.save
flash[:notice] = "You successfully registered your app."
redirect_to user_registeredapp_path(current_user.id, #registeredapp.id)
else
flash.now[:alert] = "There was an error registering your app. Please try again."
render :new
end
end
Policies (using Pundit Gem)
# registeredapp_policy.rb
class RegisteredappPolicy
def initialize(user, registeredapp)
#registeredapp = registeredapp
#user = user
end
def create?
if #user.present?
#user = #registerdapp.user
else
false
end
end
Here are my models
# models/user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
def avatar_url(size)
gravatar_id = Digest::MD5::hexdigest(self.email).downcase
"http://gravatar.com/avatar/#{gravatar_id}.png?s=#{size}"
end
has_many :registeredapps
end
# models/registeredapp.rb
class Registeredapp < ApplicationRecord
belongs_to :user
has_many :events
end
Your issue is that the instance variable #registeredapp is mispelled in the RegisteredappPolicy class under the create? method.
It currently is
def create?
if #user.present?
#user = #registerdapp.user
else
false
end
end
whereas the variable defined in the initialize is #registeredapp you're missing an e
#registerdapp is nil
#user = #registerdapp.user
use try
#user = #registerdapp.try(:user)
or
def create?
if #user.present? && #registerdapp.present?
#user = #registerdapp.user
else
false
end
end
NOTE: Also you are missing one end for if else in create? method
Rails convention usually is to have the model name like:
User
And its corresponding table name like:
users
In your ActiveRecord::Registeredapp you have :user, check if you shouldn't have :users.
I have a devise model called members i am using devise confirmable. Upon confirm i want to send a welcome email to the User
class Member < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable
# Methods
# Override devise confirm! message
def confirm!
welcome_email
super
end
# Private Methods
private
def welcome_email
MemberMailer.welcome_email(self).deliver
end
end
My MemberMailer resides in mailers/brands/member_mailer.rb
class Brands::MemberMailer < ApplicationMailer
# Send Welcome Email once Member confirms the account
def welcome_email(member)
#member = member
mail(to: #member.email, subject: "Welcome to Skreem! Now you Rock!")
end
end
But upon confirming through the mail Link the confirm! is not being overridden and I am not getting any error or email.
Add this to your Member model:
def after_confirmation
welcome_email
end
For more info check after_confirmation
#Pavan thanks for pointing this.
Your welcome_email should be:
def welcome_email
Brands::MemberMailer.welcome_email(self).deliver
end
I am very new to Ruby on Rails and have setup Devise for authentication. I have an existing model that I created prior to adding Devise. That model is called Article. I believe I have done everything I need to do in order to use the association=(associate) method that "assigns an associated object to this object. Behind the scenes, this means extracting the primary key from the associate object and setting this object’s foreign key to the same value" which is exactly what I need to do.
Here is Devise's User model:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
has_one :article
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
Here is my Article model:
class Article < ActiveRecord::Base
belongs_to :user
validates :name, presence: true, length: { minimum: 5 }
end
Here is my migration:
class AddUserRefToArticles < ActiveRecord::Migration
def change
add_reference :articles, :user, index: true
end
end
Here is my create method from my articles_controller.rb:
def create
#article.user = current_user
#article = Article.new(post_params)
if #article.save
redirect_to #article
else
render 'new'
end
end
And here is what happens when my controller runs:
NoMethodError in ArticlesController#create
undefined method `user=' for nil:NilClass
The highlighted code is #article.user = current_user. I was at least glad to know that I wrote that line of code similar to the popular answer in the Devise how to associate current user to post? question that I saw on here before posting this one.
I know I'm making a rookie mistake. What is it?
A new User instance needs to be assigned to #article before you can access any of the instance's attributes/associations. Try the following:
#article = Article.new(post_params) # Assign first
#article.user = current_user # Then access attributes/associations
The code posted in the question yields a nil:NilClassexception because the user association is being invoked on #article, which is nil because nothing has yet been assigned to it.
I override devise's confirm! method to send a welcome message to my users:
class User < ActiveRecord::Base
devise :invitable, :database_authenticatable, :registerable, :recoverable,
:rememberable, :confirmable, :validatable, :encryptable
# ...
# Devise confirm! method overriden
def confirm!
UserMailer.welcome_alert(self).deliver
super
end
end
With devise_invitable when the user accept the invitation and set his password the confirm! method is never triggered, is it possible to force it? How does devise_invitable confirms the User?
Or maybe I can override the accept_invite (or whatever its called) method the same way?
I want that invited users remain unconfirmed, and then confirmed upon accepting the invitation.
Thanks, any help very appreciated!
Original Source
UPDATE
Looking through devise_invitable model I found the two methods who may be causing this misbehavior:
# Accept an invitation by clearing invitation token and confirming it if model
# is confirmable
def accept_invitation!
if self.invited? && self.valid?
self.invitation_token = nil
self.save
end
end
# Reset invitation token and send invitation again
def invite!
if new_record? || invited?
#skip_password = true
self.skip_confirmation! if self.new_record? && self.respond_to?(:skip_confirmation!)
generate_invitation_token if self.invitation_token.nil?
self.invitation_sent_at = Time.now.utc
if save(:validate => self.class.validate_on_invite)
self.invited_by.decrement_invitation_limit! if self.invited_by
!!deliver_invitation unless #skip_invitation
end
end
end
class User < ActiveRecord::Base
devise :invitable, :database_authenticatable, :registerable, :recoverable,
:rememberable, :confirmable, :validatable, :encryptable
# ...
# devise confirm! method overriden
def confirm!
welcome_message
super
end
# devise_invitable accept_invitation! method overriden
def accept_invitation!
self.confirm!
super
end
# devise_invitable invite! method overriden
def invite!
super
self.confirmed_at = nil
self.save
end
private
def welcome_message
UserMailer.welcome_message(self).deliver
end
end
I tried benoror's answer and at first it appeared to work - but when you a user accepts the invitation and fills in the form as invalid it will actually override the token invalidating the invitation.
Instead, a callback is available to do this:
class User < ActiveRecord::Base
devise :invitable, :database_authenticatable, :registerable, :recoverable,
:rememberable, :confirmable, :validatable, :encryptable
after_invitation_accepted :send_welcome_email
def send_welcome_email
end
end