2

I'm implementing an invitation system and I want the new user form to pre-populate the user's email address in the email address field on the form (eventually, I will refactor this so it's not a form_field), so that the user doesn't have to type in all their information, just enter a password.

I have created the getter/setter methods in the users.rb model like this:

  def invitation_token
    invitation.invitation_token if invitation
  end
  def invitation_token=(invitation_token)
    self.invitation = Invitation.find_by_invitation_token(invitation_token)
  end

INVITATION MODEL

class Invitation < ActiveRecord::Base

  #--== ASSOCIATIONS
  belongs_to :sender, :class_name => 'User'
  has_one :recipient, :class_name => 'User'
  #--== CALLBACKS
  before_create :generate_token
  before_create :recipient_is_not_registered
  before_create :decrement_sender_count, :if => :sender
  #--== VALIDATIONS
  validates_presence_of :recipient_email
  #validate :recipient_is_not_registered
  validate :sender_has_invitations, :if => :sender
  #--== METHODS
  private
    def recipient_is_not_registered
      if User.find_by_email(recipient_email)
        false
      else
        true
      end
    end

    def sender_has_invitations
      unless sender.invitation_limit > 0
        redirect_to root_url
      end
    end

    def generate_token  #TODO: MOVE to lib/generate_token.rb
      self.invitation_token = Digest::SHA1.hexdigest([Time.now, rand].join)
    end

    def decrement_sender_count
      sender.decrement! :invitation_limit
    end

end

USER CONTROLLER

class UsersController < ApplicationController
  def new
    @user = User.new(:invitation_token => params[:invitation_token])
    @user.email = @user.invitation.recipient_email if @user.invitation
  end

  def create
    @user = User.new(user_params)
    if @user.save
      session[:user_id] = @user.id
      redirect_to root_url, notice: "Thank you for signing up!"
    else
      render "new"
    end
  end

 ...

  def user_params
    params.require(:user).permit(:email, :password, :password_confirmation, :admin)
  end
end

views/users/_form.html.erb

<%= form_for @user do |f| %>  

  <%= f.hidden_field :invitation_token %>

  <div class="field">
    <%= f.label :email %><br />
    <%= f.text_field :email %>
  </div>
  <div class="field">
    <%= f.label :password %><br />
    <%= f.password_field :password %>
  </div>
  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation %>
  </div>
  <div class="field">
    <%= f.check_box :admin %>
    <%= f.label :admin %>
  </div>
  <div class="actions"><%= f.submit %></div>
<% end %>

I was following Ryan Bates' RC#124 - Beta Invitations, and got stuck here. His code doesn't produce the error, so I should mention that this is a Rails 3.2.18 app.

When I reload the form, the user's email isn't populated in the form. The relevant log shows:

Started GET "/signup.914823d28d07b747213ec3de47f89ad537169e34" for 127.0.0.1 
at 2016-04-30 20:24:47 -0600
Processing by UsersController#new as 
  User Load (1.0ms)  SELECT "users".* FROM "users" WHERE "users"."auth_token" = 'rOHiKmDcceytxi_t151YIQ' LIMIT 1
  Invitation Load (0.0ms)  SELECT "invitations".* FROM "invitations" WHERE "invitations"."invitation_token" IS NULL LIMIT 1
  Rendered users/_form.html.erb (5.0ms)
  Rendered users/new.html.erb within layouts/application (6.0ms)
Completed 200 OK in 102.0ms (Views: 25.0ms | ActiveRecord: 3.0ms)

So it appears that the invitation_token isn't being passed in, since the log shows it is NULL.

I have gone over the RC code from top to bottom and can't find out why it's not being passed.

Any help would be appreciated. Thanks.

UPDATE: The output from the view source is:

<input id="user_invitation_token" name="user[invitation_token]" type="hidden" />, so it's not being passed along.

1 Answer 1

3

Set the value on the hidden field by passing the value: key:

<%= f.hidden_field :invitation_token, value: some_value %>
Sign up to request clarification or add additional context in comments.

7 Comments

The point of the exercise is to have the invitation_token populated from the url, example: http://localhost:3000/signup/914823d28d07b747213ec3de47f89ad537169e34 This isn't being set from the URL, which is sent to the user via email.
You're assigning invitation_token to user in you're new action. So why not <%= f.hidden_field :invitation_token, value: @user.invitation_token %>? Otherwise, how about <%= f.hidden_field :invitation_token, value: params[:invitation_token] %>?
That works, but there is another problem. Somewhere in my code, it is generating the URL as http://localhost:3000/signup.1b344bd1ed23ea367728239496339074fc859721. This doesn't work. In order to have the fill-in work as intended, the URL needs to drop the "." after "signup" and replace it with a "/". I can't see where it's putting the period in place of the slash char.
This is because whatever route is generating http://localhost:3000/signup.1b344bd1ed23ea367728239496339074fc859721 is missing an identifier in your routes (e.g. /signup/:token/)
This is the route I have set up... get 'signup/:invitation_token', to: 'users#new', as: 'signup'
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.