# Terminal
rails g model consent name mandatory:boolean description:text
rails g model user_consent user:references consent:references agreed:boolean
rails db:migrate
rails g devise:views
# models/consent.rb
class Consent < ApplicationRecord
has_many :user_consents
# has_many :users, through: :user_consents
end
# models/user_consent.rb
class UserConsent < ApplicationRecord
belongs_to :user
belongs_to :consent
end
# models/user.rb
class User < ApplicationRecord
devise :database_authenticatable, :registerable, :recoverable,
:rememberable, :trackable, :validatable
include UserConsentValidation
end
# models/concerns/user_consent_validation.rb
module UserConsentValidation
extend ActiveSupport::Concern
included do
has_many :user_consents, dependent: :destroy
has_many :consents, through: :user_consents
accepts_nested_attributes_for :user_consents
validate :consent_given
def build_consents
return unless new_record?
Consent.all.map { |consent| user_consents.build(consent_id: consent.id) }
end
private
def consent_given
errors.add(:consent, 'must be accepted to continue') unless mandatory_consents.map(&:agreed).all?
end
def mandatory_consents
user_consents.select { |uc| uc.consent.mandatory? }
end
end
end
# views/devise/registrations/new.html.erb
<div class="field">
<%= f.fields_for :user_consents, resource.build_consents do |c| %>
<%= c.hidden_field :consent_id %>
<%= c.check_box :agreed %>
<%= c.object.consent&.description %>
<br>
<% end %>
</div>
# db/seeds.rb
Consent.create do |consent|
consent.name = 'cookies'
consent.mandatory = true
consent.description = 'I agree for use of cookies on this site to distinguish me from other users.'
end
Consent.create do |consent|
consent.name = 'terms_and_conditions'
consent.mandatory = true
consent.description = 'I agree to the terms and conditions.'
end
Consent.create do |consent|
consent.name = 'privacy_policy'
consent.mandatory = true
consent.description = 'I agree to the privacy policy.'
end
Consent.create do |consent|
consent.name = 'sell_your_information'
consent.mandatory = false
consent.description = 'I agree to allow my information to be sold to third parties.'
end
# controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
private
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up) do |user_params|
user_params.permit(:email, :password, :password_confirmation, user_consents_attributes: {})
end
end
end
# config/initializers/filter_parameter_logging.rb
Rails.application.config.filter_parameters += [:first_name, :last_name, :email, :password]