Adding TOS agreement checkbox with Devise - ruby-on-rails

We're using devise for our members. We've added a tos_agreement field (boolean) to our member schema, and we added it to views/devise/registrations/new.html.haml.
In the Member model, we have a validation rule as follows:
validates_acceptance_of :tos_agreement, :allow_nil => false,
:accept => true
It works fine - if you don't accept the TOS, you can't register.
However, the problem comes with editing your settings. If you go to /members/edit you get the form where you can change your email address or password. There's no field for the TOS agreement since this shouldn't be changeable at this point. However, when you make a change (eg. change your password) and submit the form, it returns an error message that the TOS agreement can't be false.
How can we tell it never to attempt to modify the TOS agreement after the first registration?
Edit: so I think the fundamental problem is that we had :tos_agreement in our attr_accessible, which was a very bad idea now I think of it. But if we remove it, how do we modify Devise to accept the parameter and do something with it even though it's not mass-assignable?

You can pass an :on => :create option to the validator so that it's only checked on signup:
validates_acceptance_of :tos_agreement, :allow_nil => false, :accept => true, :on => :create

Related

Validating password with validates_format_of

EDIT: I realized the comments about there not being a difference with :save already covered were correct, and was able to work through some errors. However, it still appears the regex validation is failing for :password.
I'm a little confused, and think the problem might be related to there being only :password_digest in the table itself, while we use password and password_confirmation as attributes in the model. But I'm also guessing Rails has this all worked out and takes care of everything with the has_secure_password function.
validates_format_of :password, :with => /\A[a-zA-Z]\z/, :on => :create, :update fails with the string password.
Obviously, this doesn't make sense and matches fine in the console (using =~ or .match(). Also notice if I set allow_nil: true for :password other tests involving the user start failing (which doesn't make sense, as the password should never be nil anyways).
I don't see any use case where you need on create and update together if on: :save is already there.
For more model callbacks please refer this.
According to rails docs
The default behavior for all the built-in validation helpers is to be run on save (both when you're creating a new record and when you're updating it). If you want to change it, you can use on: :create to run the validation only when a new record is created or on: :update to run the validation only when a record is updated.
So, you should not use :on option in your validation

Boolean checkbox needs to be accepted all the time even when checked

I've put a validation in a checkbox for tos_agreements, but now, even if it's checked, it still gives me the error "Tos Agreements need to be accepted".
What I have is:
1.) I've added :tos_agreements to Devise permitted params in Application Controller
2.) I've validated like this:
validates_acceptance_of :tos_agreement, :allow_nil => false, :accept => true
Any idea? Thanks!
i usually do this with an attr_accessor(of course in the model of the user):
attr_accessor :tos_agreement
validates :tos_agreement, acceptance: true
this will validate that the checkbox tos_agreement will be checked, regards

How to customise devise views in rails 3.2 to include only some elements in the sign up form

I am a rails newbie and I have started hacking together a web app.
I used devise to set up user registrations and also generated the devise views templates.
I added custom models in there - username, first name, surname etc. I then added them in the attr_accessor in user.rb etc. and validates for the presence of these details
I thought of adding these elements in the edit registration form which worked successfully.
On the signup page - the code asks only for email, password, confirm password (as is set as default by devise).
If i now try and register as a new user (after all these steps), i get an error saying that First name cannot be empty, surname cannot be empty etc.
How can i exclude these from the sign up yet keep them active in the user profile edit?
I hope I'm making sense.thanks for your help in advance
If I understand correctly, during signup/registration you want to only ask for email and password, excluding the other User model attributes (first name, surname) from that form. However you also want to later have these other attributes validated when the user edits their profile.
So since you are validating for the presence of these extra attributes which are not provided when the signup form is submitted, the attempt to create a new user record simply fails to create at validation.
Try the :on => :update validation option to specify that certain fields should only be validated when later updated, rather than the default which is to validate any time a record is saved. Like this:
class User < ActiveRecord::Base
validates :email, :presence => true
validates :firstname, :presence => true, :on => :update
validates :surname, :presence => true, :on => :update
...
end
See http://guides.rubyonrails.org/active_record_validations_callbacks.html#on
you can go into your views > devise folder and create a registrations folder if its not there and make a new.html.erb
have a look at the file that you find under the link:
https://github.com/plataformatec/devise/blob/master/app/views/devise/registrations/new.html.erb
copy it to your new file and customize it as you want... it should overwrite the devise default view.

rails 3.1 partial_updates doesn't seem to work with password

i have a user model with a password attribute, which gets saved as password_digest.
What i want to do is have the edit user page and the edit password page separated, so that
the admin doesn't need to input the password everytime he needs to change something else. For this i have made an extra action / view.
My problem is that when i update the user info, i get password validation errors even though
i have no password field in the form. Which leads me to the conclusion that partial_updates isn't working with the password attribute (as i have already tested in the console that it is enabled, and it is)
Is this me doing something wrong, or should i approach this differently?
Similar to the railscasts approach mentioned by #normalocity, but without the need to set a pseudo-attribute in the controller, we do this (which is essentially taken from restful_authentication):
attr_accessor :password
validates :password,
:length => { :minimum => 8 },
:confirmation => true,
:presence => true,
:if => :password_required?
def password_required?
password_digest.blank? || !password.blank?
end
Basically, we assume that if the password_digest hasn't been set yet (for a new record), or if the password pseudo-attribute has been set, then that means the password is being changed and the validations have to be run. So we don't need to set a updating_password pseudo-attribute like they do in the railscasts episode.
You need to validate the password only if it's being changed. If it's not being changed, then the validation for the password field should be skipped.
Railscasts.com episode #41 shows you how to do this.

Rails validation problem

I've got a User model with three fields, :email, :display_name and :handle. Handle is created behind the scenes from the :display_name.
I'm using the following validations:
validates :display_name, :presence => :true, :uniqueness => { :message => "Sorry, another user has already chosen that name."}, :on => :update
validates :email, :presence => :true, :uniqueness => { :message => "An account with that email already exists." }
I use the handle as the to_param in the model. If the user fails the validation by submitting a :display_name that already exists, then tries to change it and resubmit the form, Rails seems to use the new handle as the validation for the email -- in other words, it assumes that the email doesn't belong to the current user and validation on the email then fails. At this point, Rails assumes that the changed display name/handle is the one to use for the look up and the update action can't complete at all, because it can't find the user based on the new handle.
Here's the update method:
def update
#user = User.find_by_handle(params[:id])
#handle = params[:user][:display_name]
#user.handle = #handle.parameterize
...
end
This problem doesn't happen when the validation first fails on a duplicate email, so I'm assuming it's something about the way I've written the update method -- maybe I should try setting the handle in the model?
maybe I should try setting the handle in the model?
^ This.
The controller isn't the place to do something like this. If it's model logic that's happening behind the scenes, beyond the user's control, why put it in controller code?
Do it instead in a before_save filter, which is guaranteed to run only after the chosen display name is determined to be available and the record is deemed valid. In this way the handle won't be changed on the cached record until it is actually committed to the db, eliminating the problem of the incorrectly generated URL.
before_save :generate_handle
...
def generate_handle
self.handle = display_name.parameterize
end

Resources