Anthony D Gardner Anthony D Gardner - 7 months ago 27
Ruby Question

Rails - Session Variable Not Persisting Through Apartment Switch

I have a situation.

>rails -v
Rails 4.2.4

>ruby -v
ruby 2.1.8p440 (2015-12-16 revision 53160) [i386-mingw32]


I am building a multi-tenant Time Entry solution using the Apartment gem. Here's the flow. I'm stuck.

1) User arrives at the signup page, which creates the tenant. Here's the controller:

def new
@tenant = Tenant.new
end

def create
@tenant = Tenant.new(tenant_params)
session[:tenant_attributes] = @tenant.attributes

if @tenant.save

flash[:success] = "Org ID #{session[:tenant_attributes]["org_identifier"]} created for #{session[:tenant_attributes]["org_name"]} successfully!"
# Start a job for creating the tenant: this is handled in the model?
# Apartment::Tenant.switch!("#{session[:tenant_attributes]["org_identifier"]}")
redirect_to new_user_url(:subdomain => "#{session[:tenant_attributes]["org_identifier"]}") #new_user_path
else
render :new
end
end


And the view:

<% provide(:title, 'Sign up') %>
<h1>Welcome!</h1>
<p class="center">
Make time entry easy, for once.
</p>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for (@tenant) do |f| %>
<%= render 'shared/tenant_error_messages' %>

<%= f.label :creator_email, "What is your email address?" %>
<%= f.email_field :creator_email, class: 'form-control' %>

<%= f.label :org_name, "What is the name of your organization?" %>
<%= f.text_field :org_name, class: 'form-control' %>

<%= f.label :org_identifier, "Please choose an abbreviated Org ID" %>
<%= f.text_field :org_identifier, class: 'form-control' %>

<%= f.submit "Create your own Org", class: "btn btn-primary" %>

<% end %>
</div>
</div>


As you can see, this is set to redirect to the
new_user_url
helper passing a subdomain equal to the new org_identifier (the tenant that was just created.)

2) Upon correct info submission, the redirect happens after the tenant is created. I've confirmed creation is happening. I've confirmed the redirect is correct. Then the session variable empties itself.

The users controller:

def new
# Instantiate a new user object at the open of the 'new' view
@user = User.new

end

def create
# This is the method conducted at the submission of the form and instantiates/saves its own user object
@user = User.new(user_params)
if @user.save
log_in @user
flash[:success] = "Welcome to the Time Entry Solution!"
if @user.site_id == "nil"
redirect_to new_client_path #(:subdomain => session[:tenant_attributes]["org_identifier"])
else
redirect_to current_user
end

else
render 'new'
end
end


The users/new view:

<% provide(:title, 'Sign up') %>
<center><p>
Tell us more about you.
</p>
</center>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<% if session[:tenant_attributes] %>

<h2><%= session[:tenant_attributes] %></h2>
<h2><%= session[:tenant_attributes] %></h2>
<% else %>
<h2> The session variable is empty.</h2>
<% end %>

<%= form_for (@user) do |f| %>
<%= render 'shared/error_messages' %>

<%= f.hidden_field :email, :value => session[:tenant_attributes]["creator_email"] %>

<%= f.label :first_name %>
<%= f.text_field :first_name, class: 'form-control' %>

<%= f.label :last_name %>
<%= f.text_field :last_name, class: 'form-control' %>

<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>

<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>

<%= f.submit "Create an org ID", class: "btn btn-primary" %>

<% end %>

</div>
</div>


When I submit the subsequent form - which includes a hidden field with the email parameter as the session value I want - I get "Email is invalid."

--- !ruby/hash:ActionController::Parameters
utf8: "✓"
authenticity_token: IAEe2EyvrGFa9gMp2X0WnlBzMHF9WdDXhVIs5s3vPkK54xqgICp3T8S/tXQiQnKYqr2CVTH7+0H9G4SaZNGoDQ==
user: !ruby/hash:ActionController::Parameters
email: ''
first_name: Anthony
last_name: Gardner
password: Password12345!
password_confirmation: Password12345!
commit: Create an org ID
controller: users
action: create


I've looked through the Apartment gem doc and scoured the web. I can't see any reason why this should be failing. But of course, I'm sure it's right in front of my face. Any help would be appreciated.

UPDATE:

I found this solution that I will be trying, setting domain of the cookie store to all then checking inside the app controller afterward. I'm not using devise, but we'll see if it works.

Answer

Found the answer here: Share session (cookies) between subdomains in Rails?

The problem was in our session_store.rb. We weren't taking into account that by setting domain: :all, we were disregarding the default TLD length of 1. We were using lvh.me instead of localhost.

Hope this helps others!

Comments