What is the best way to add a check for ac开发者_如何学运维cepting terms of use in a rails app?
I can't seem to get validates_acceptance_of
working quite right. I added a bool to my user model (was that necessary?). And then have a checkbox that returns either true/false.
I feel like I'm just making a silly little mistake. Any ideas?
In your model,
validates_acceptance_of :terms
If you're using attr_accessible
in your model then make sure you also add,
attr_accessible :terms
In your view,
<%= form_for @user do |f| %>
...
<%= f.check_box :terms %>
...
<% end %>
There is no need for an extra column in the users table unless you plan on denying access to users who have not accepted the terms of service, which won't exist since they can't complete registration in the first place.
This is a working Rails 4 solution:
Terms of service doesn't need to be a column in the database
Form
= f.check_box :terms_of_service
models/user.rb
validates :terms_of_service, acceptance: true
And most important, devise will sanitize your parameters and terms of service will be removed from the submitted params. So:
registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
before_filter :configure_permitted_parameters
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit(:full_name,
:email, :password, :password_confirmation, :terms_of_service)
end
end
end
This is a working solution for Rails-6.1 (I18n) + Devise-4.8.0 + SimpleForm. No need to add a column in the "users" table in DB.
View
<% label_str = t('read_html', mylink: link_to(t('terms'), '/a/b/c')) %>
<%= f.input :terms_of_service, label: label_str, as: :boolean, checked: false %>
Or, if you use Indo-European languages only, you can make it a little more simple, like:
label_str = (t('agree_html')+link_to(t('terms'), '/a/b/c')+'.').html_safe
/app/models/user.rb
attr_accessor :terms_of_service
validates_acceptance_of :terms_of_service, on: :create
validates_presence_of :terms_of_service, on: :create
/app/controllers/application_controller.rb
Devise::ParameterSanitizer::DEFAULT_PERMITTED_ATTRIBUTES[:sign_up] << :terms_of_service
# see /vendor/bundle/ruby/*/gems/devise-*/lib/devise/parameter_sanitizer.rb
Explanation
In the User model, on: create
guarantees it is read only in creation. If you need to reevaluate the condition in updating, too, specify it accordingly, like on: %i(create update)
.
In the User model, I add validates_presence_of
to play safe. The reason is, validates_acceptance_of
will not be executed when the parameter terms_of_service
is nil, in which case validates_presence_of
will catch it and set an error. Admittedly, if the data are always submitted via the web-interface you have built AND your implementation is working perfectly, the value should be always either true or false and never be nil. So, validates_presence_of
should not be necessary in this sense. It does no harm, though (except you'd need to be a little careful in manual user creation, bypassing the web-interface, such as from the Console).
The last one is neccesary for use with Devise for the same reason as in the answer by @vladCovaliov; that is, to prevent Devise from sanitizing your custom parameter, which is not a column in the database table. The one-liner in the example above can be stated in any files as long as you are sure it is read at the run-time and after Devise Ruby code. application_controller.rb
is one of the sure places (though I guess there is a better-fitting place). Make sure the sentence is put out of the class ApplicationController
block.
精彩评论