Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add invite code to Devise

I'm creating an RSVP app for a wedding. In order to eliminate random people from RSVP'ing to the event I wanted to include a code (ie "groombride2015") on the invitations. I want to add this field to the signup and not allow the signup to process unless this code is valid. I've spent all day trying to figure this out.

The closest I've come to getting it to work was using this method... http://wp.headynation.com/simple-invitation-access-code-using-rails-4-devise/

Can anyone help me out?

like image 291
devoidofgenius Avatar asked Feb 28 '15 22:02

devoidofgenius


1 Answers

I just implemented this the other day, and it's actually very straightforward. First, you need to add another permitted parameter to the Devise sign up form in

app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  before_action :configure_permitted_parameters, if: :devise_controller?
  after_action :verify_authorized, unless: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(
        :username, 
        :email, 
        :password, 
        :password_confirmation, 
        :remember_me, 
        :sign_up_code
    ) }
  end
end

These params don't have to match exactly, but you need to make sure that whatever form field you're using to enter the signup code matches the name you pass here.

Now update the devise view with a field for the code attribute:

app/views/devise/registrations/new.html.erb

<%= form_for( resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <!-- Your Other Form Stuff -->
  <%= f.text_field :sign_up_code %>
<% end %>

Next, we need to add a virtual attribute and some validation:

app/models/user.rb

class User < ActiveRecord::Base
  attr_accessor :sign_up_code
  validates :sign_up_code,
    on: :create,
    presence: true,
    inclusion: { in: ["your_code"] }
  # The rest of your model
end

Now you're all set!

Note that you could also do something like the following if you wanted dynamic invite codes from a table invite_codes:

inclusion: { in: proc { InviteCode.where( used: false ).map( &:code ) } }

In the above model, I have a string code and a boolean used to make sure that invite codes can only be used once.

For example, I use the following seed.rb code to populate invite codes on database creation:

  invite_codes = (0...50).map { { code: SecureRandom.hex(7), used: false } }
  invite_codes = invite_codes.uniq

  invite_codes.each do |invite_code|
    InviteCode.find_or_create_by!( invite_code )
  end
like image 148
s_dolan Avatar answered Nov 04 '22 15:11

s_dolan