Devise - Is it possible to some users not need confirmation? - ruby-on-rails

What I need if some user has an attribute, this will not need to be confirmed.
I've seen a couple of post about this but I cannot understand it (i'm kinda newbie in Rails).
In my user.rb
def confirmation_required?
if self.name == 'Joe'
false
end
end
I tried that out but nothing happens, is like always is false. I saw another post with this code:
def confirmation_required?
!confirmed?
end
#Put your conditions and job's done !
but how can I access to user data from my user.rb (model) Note that the user comes from HTTP Post request.
Can somebody help me?
Thanks
EDIT
Also I could just re-write Devise::RegistrationsController to something like this:
class RegistrationsController < Devise::RegistrationsController
def create
super do
if resource.name == 'Joe'
resource.skip_confirmation!
resource.save
end
end
end
end
Do you think this could solve it?
Thanks.

In your user model you can conditionally call skip_confirmation! in your before_save callback
class User < ActiveRecord::Base
before_save :skip_confirm # arbitrary method name
def skip_confirm
if self.name == 'Joe'
skip_confirmation!
end
end
end
or, you can use a block on before_save
class User < ActiveRecord::Base
before_save -> do
if self.name == 'Joe'
skip_confirmation!
end
end
end

Related

Using scopes in my Pundit policy (Rails 5)

How to use scopes, defined in the model, in my Pundit policy?
In my model I have a scope:
scope :published, ->{ where.not(published_at: nil )}
And in my Pundit policy I have
class CompanyPolicy < ApplicationPolicy
def index?
true
end
def create?
user.present?
end
def new?
true
end
def show?
true
end
def update?
user.present? && user == record.user
end
end
How can I use my scope in the Pundit policy? I would like to show it only if it's "published", something like this, which doesn't work at the moment:
class CompanyPolicy < ApplicationPolicy
def show
record.published?
end
end
Scopes are Class methods, you can't call them on instances.
You have to define a published? instance method too:
def published?
published_at.present?
end
You could use the scope if you ask if the record exists on the given scope with:
User.published.exists?(user.id)
And it will return true if the scope includes the user id, but I wouldn't recommend that, it requires an extra query to the database to get something that you can know from the user instance you already have.

Rails - validation inside decorator

I'm struggling with some kind of issue. I have a rails model (mongoid).
class User
include Mongoid::Document
include ActiveModel::SecurePassword
validate :password_presence,
:password_confirmation_match,
:email_presence,
field :email
field :password_digest
def password_presence
end
def email_presence
end
def password_confirmation_match
end
end
My goal is to call validations depends on which decorator I will use. Let's say I've got two decorators:
class PasswordDecorator < Draper::Decorator
def initialize(user)
#user = user
end
end
def RegistraionDecorator < Draper::Decorator
def initialize(user)
#user = user
end
end
So now when I create/save/update my user object inside RegistraionDecorator I would like to perform all validation methods.
RegistraionDecorator.new(User.new(attrbiutes))
But when I will do it inside PasswordDecorator I want to call for example only password_presence method.
PasswordDecorator.new(User.first)
When I move validations to decorator it won't work cuz its different class than my model.
How can I achieve that?
Try to use a Form Object pattern instead.
Here is an example (from a real project) of how it could be done with reform.
class PromocodesController < ApplicationController
def new
#form = PromocodeForm.new(Promocode.new)
end
def create
#form = PromocodeForm.new(Promocode.new)
if #form.validate(promo_params)
Promocode.create!(promo_params)
redirect_to promocodes_path
else
render :edit
end
end
private
def promo_params
params.require(:promocode).
permit(:token, :promo_type, :expires_at, :usage_limit, :reusable)
end
end
class PromocodeForm < Reform::Form
model :promocode
property :token
property :promo_type
property :expires_at
property :usage_limit
property :reusable
validates_presence_of :token, :promo_type, :expires_at, :usage_limit, :reusable
validates_uniqueness_of :token
validates :usage_limit, numericality: { greater_or_equal_to: -1 }
validates :promo_type, inclusion: { in: Promocode::TYPES }
end
Bonus: The model does not trigger validations and much easy to use in tests.

Sequel validations in concerns

I have a Sequel model like this:
class User < Sequel::Model
include Notificatable
def validate
super
validates_presence [:email]
end
end
# concerns/notificatable.rb
module Notificatable
extend ActiveSupport::Concern
included do
def validate
super
validates_presence [:phone]
end
end
end
And here I got a problem: Notificatable validate method overrides the same method in the User model. So there is no :name validations.
How can I fix it? Thanks!
Why use a concern? Simple ruby module inclusion works for what you want:
class User < Sequel::Model
include Notificatable
def validate
super
validates_presence [:email]
end
end
# concerns/notificatable.rb
module Notificatable
def validate
super
validates_presence [:phone]
end
end

Rails - Write comment as a guest with devise. Design proposition?

I want to be able to write a comment as a guest or as a registered user with devise.
My comment model contains :title, :content, :user_id, :guest_email, :guest_website and :write_as_guest as a boolean.
I wanted to validate the presence of :guest_email only when no user is signed_in. But I think I'm not going in the good direction.
I'm managing the form with AJAX/jQuery and I wanted to have a guest form where :content and :guest_email are necessary fields. In another hand, I want to have the user form where only the :content is necessary.
Here is how I tried to go for it.
class Comment < ActiveRecord::Base
before_validation :set_write_as_guest
belongs_to :user
validates_presence_of :content
validates_presence_of :guest_email, :if => :write_as_guest?
private
def write_as_guest?
self.write_as_guest
end
def set_write_as_guest
if user_signed_in?
self.write_as_guest = false
else
self.write_as_guest = true
end
end
end
It seems that user_signed_in? method needs before_filter :authenticate_user! then I have the following in my comments_controller
before_filter :authenticate_user!, :only => :create
But however I don't want to authenticate to create because that's a guest...
So if somebody would be able to propose me a way to write as a guest or as a user, that would be really appreciated.
Thx
You can do a custom validation like this
class Comment < ActiveRecord::Base
validate :guest_commentator
def guest_commentator
user = User.find(user_id)
self.errors.add(:user_id => "some error message here ") unless user.nil?
end
end

Restrict access to some model items in Rails 3

I have Post model with published? field and some authorization system which defines admin? method inside ApplicationController.
I want to restrict access to unpublished posts and show them only to administrator.
I tried to define a scope accessible to return only published posts to users, but all posts for administrator.
scope :published, where(:published => true)
def self.accessible
admin? ? all : published
end
The problem is that admin? method can't be accessed inside the model. What is the best way to implement what I want?
# option 1
class Post < ActiveRecord::Base
def self.accessible_to user
user.admin? ? all : published
end
end
class PostsController < ApplicationController
def index
#posts = post.accessible_to current_user
end
end
# option 2
class Post < ActiveRecord::Base
def self.accessible is_admin
is_admin ? all : published
end
end
class PostsController < ApplicationController
def index
#posts = post.accessible admin?
end
end
One way, but not so abstract.
def self.published_unless(condition)
condition ? all : published
end
Post.published_unless(admin?)

Resources