RoR: how do I create a "valid signup code" lookup? - ruby-on-rails

I want to be able to give codes to potential users in the form of email links (e.g. mysite.com/signup?beta=rapunzel)
When someone clicks on the link, it populates a hidden_field with the value (will just using :params[:beta] work?)
Then before it creates the user it validates by checking against another table where I have different beta code.
Then goes ahead and stores which code or maybe just the beta.id.
Suggestions? A plugin already exists?
Thanks.

When your user hits mysite.com/signup, the action associated with that route will have the value "rapunzel" stored in params[:beta]. You can pass that onto your view by assigning it into an instance variable (#beta), pass it back to your user controller through your hidden field as planned, and compare it there to your table before saving the user object.
Or you could only allow your user to get to the signup page at all if they're passing in a valid beta code, in which case you won't need any special form fields:
def signup
unless BetaCode.find_by_code(params[:beta])
flash[:notice] = "You can't sign up without a beta code!"
redirect_to root_path
end
end

What parameters you get out of your URL will depend on how your routes are set up. With your current route you would get:
params[:beta] = "rapunzel"
If you specify your route as:
map.connect '/signup/:beta', :controller => 'signup', :action => 'beta'
you could send them a link like: mysite.com/signup/rapunzel instead and you would get the beta parameter the same as before.
To get the beta field onto the form just include it as a hidden field on the form page template.
In the controller put something like:
#beta_id = params[:beta]
Then in the view template put:
hidden_field_tag 'beta', #beta_id
Then when they signup and create a proper id you'll probably want to hook in an association from their row in the user's table to the row containing the beta id in the "beta" table. This could be a has_one association on the beta table if you only wanted to allow a single user to register with each beta id, or a has_many if multiple people could sign up with it.

I would have done this with a validation.
class User < ActiveRecord::Base
validate_on_create {|r|
beta_code = BetaCode.find_by_code(r.beta_code)
beta_code && beta_code.destroy ||
r.errors.add(beta_code, "is invalid")
}
attr_accessor :beta_code
end
In your form:
<% form_for(#user) do |f| %>
# fields...
<%= f.text_field :beta_code %>
<% end %>
This assumes that you have a BetaCode model whose table contains a list of beta codes.

Related

Invite User to Organization with Devise Invitable

I am sending an invitation to a new user using Devise Invitable. I have a related table to Users called Organizations, with a belongs_to/has_many relationship. When the new user goes to accept the invitation, it states that there must be an organization specified. How would I go about making sure the user is assigned to the inviting user's organization automatically, so that the database is updated and the invitation can be accepted?
Thank you!
Modeling after the invitation token as a hidden field, I added
<%= f.hidden_field :plan_id, :value => 1 %>
<%= f.hidden_field :organization_id, :value => 1 %>
to the edit.html.erb invitations view. This works to submit the information I'm looking for, but I'm worried that it is not secure, as those parameters could be adjusted. I also tried adding the following to the edit control in the invitations controller, but it did nothing.
resource.plan_id = 1
resource.organization_id = 1
I have a similar setup, have you tried something like this in the create section of your invitations controller?
This approach works for me, but you'll need to override the default invitations controller do it this way.
def create
#invited_user = User.invite!({:email => "bob#someone.com"}, current_user)
#invited_user.update(organization: current_organization)
...
end
I have current_organization defined in my application_controller.rb file as:
def current_organization
#current_organization ||= current_user.organization
end
if you use devise invitable, Overwrite your invitations controller's new and update actions.
In the new action associate the new user to the group, in the update action permit the foreign key and you should be good to go.

Rails - Users should have only one row of data in a table

I want for every users to have only one row of data in a table named business. He can edit it for the second time.
Also i want to submit each column value separately using form_for but when i do like this when submitting the form for the second time for a different column entry, it goes to the second row making the previous row empty.
How can i achieve this?
Here is my code...
<%= form_for #new_business do |f| %>
<%= f.text_area :first_problem %>
<%= f.submit %>
<% end %>
A screenshot of the data table
Table data screenshot
Any help is appreciated as i am new to rails. Thanks.
One user can only have one business, you need to set relationship between them
In user.rb model
has_one :business
In business.rb model
belongs_to :user
For your second problem, i think you are not passing row id for which you want to update columns, so everytime it is creating a new entry for that column
It looks like your code snippet is from your new template (i.e. "app/views/businesses/new.html.erb"). This should only be used when you want a new object created. Your controller probably says something like
def new
#new_business = Business.new
end
When the form is submitted, the :create action in your controller gets called, which should create a new record in the database.
When you want to edit that object, you use an edit action in your controller that corresponds to an edit.html.erb view. Something like this in the controller:
def edit
#business = Business.find(params[:id])
end
with a similar form to the one you listed above in the view. When that form is submitted, it should route to an :update action in your controller, that updates the existing record in the database.
The tricky part about what you are trying to accomplish is limiting each user to only being able to create one record in the database. There are many ways to go about doing this, but the general idea would be to restrict the user's access to the new and create actions in the controller once they have already created a record. You can do that by using before_action (if using Rails 4.0 or greater) or before_filter (if using Rails < 4.0) to call a method that checks if a user has already created a record.

Automatically populating simple_form fields - RAILS

Let's say I have a Customer and a Brand class (where a customer has many brands and a brand belongs to a customer). When the user is on the show page for a specific customer, he/she has the option to click a button to add a new brand (that button redirects to the form to create a new brand, which contains a field where the user should indicate which customer that brand belongs to). But when the user gets to that form, he/she should not have to manually indicate which customer that brand belongs to, but rather that information should be entered automatically based on the customer_id of the customer whose show page the user was just looking at. If no show page was being looked at, the field for the parent customer_id should be empty (as it is by default) and the user should enter it manually.
Is there a way to implement this in Rails? If so, how?
Your question is a bit hard to understand, but let's go.
First, you have to create a link to a new brand, something like:
<%= link_to 'New brand for #{#customer.name}", new_brand_path(customer_id: #customer.id) %>
In this way you are passing the customer_id as a param.
In the brand controller on the new action you will do
def new
#customer = Customer.find_by_id(params[:customer_id])
#brand = #customer ? Brand.new(customer_id: #customer.id) : Brand.new
end
You see that I made an example to make it clear what to do. There are better ways of doing that, but I guess this will guide you through what you want.
On the link from the show page, you could have something like this
<%= link_to 'New Brand', new_brand_path(customer_id: params[:id]) %>
Then in the controller, you could have some code that checks to see if the customer_id is present in the params hash in the new action:
#brand.customer = Customer.find(params[:customer_id]) if params[:customer_id]
Now, when the form is rendered, assuming using form_for #brand, the customer field will be set.
If they are linking from another page (other than show), then just don't pass in the customer_id: params[:id] in the link_to method call. It will bypass the if statement in the controller and the customer will be blank.
#new_brand = #customer.brands.new
It populates cusomer_id in #new_brand with correct value

How can I use rails- devise to sign up multiple users at once? [duplicate]

I'm trying to user Devise invitable to add multiple users at once. Basically when someone creates an account, the first thing they'll want to do is add a bunch of users using the invitable form...
just not sure how to duplicate fields in the form and have them send a create request for each entry.
Thanks in advance!
This is how I would do it.
Provide a text area that accepts a comma-separated email list. Define
a new action that sends an invitation to each email in this list.
Lets assume a User model and a users controller for this example.
Define a route for the batch_invite action.
resources :users do
collection do
post 'batch_invite'
end
end
Define the batch_invite action in the users_controller
def batch_invite
#Validate the user_emails field isn't blank and emails are valid
params[:user_emails].split(",").each do |email|
User.invite!(:email => email)
end
#redirect_to appropriate path
end
A form that accepts a comma-separated list of emails in a textarea.
<%= form_tag batch_invite_users_path, :method => :post do %>
<%= label_tag "Email ids of people you'd like to invite." %>
<%= text_area_tag :user_emails %>
<%= submit_tag "Invite!" %>
<% end %>
A couple of notes :
If you like your controller skinny, you could move the logic to the model, for instance, by creating a send_batch_invitations method in your User model and pass the params[:user_emails] as an argument to that method from the users controller.
Since the method that sends the invitations could take sufficient time to complete, I would suggest you assign this task to a background job processor, such as delayed_job or resque.
There are railscasts that demonstrate the usage of these two background job processors.

Devise invitable batch invite - Ruby on rails

I'm trying to user Devise invitable to add multiple users at once. Basically when someone creates an account, the first thing they'll want to do is add a bunch of users using the invitable form...
just not sure how to duplicate fields in the form and have them send a create request for each entry.
Thanks in advance!
This is how I would do it.
Provide a text area that accepts a comma-separated email list. Define
a new action that sends an invitation to each email in this list.
Lets assume a User model and a users controller for this example.
Define a route for the batch_invite action.
resources :users do
collection do
post 'batch_invite'
end
end
Define the batch_invite action in the users_controller
def batch_invite
#Validate the user_emails field isn't blank and emails are valid
params[:user_emails].split(",").each do |email|
User.invite!(:email => email)
end
#redirect_to appropriate path
end
A form that accepts a comma-separated list of emails in a textarea.
<%= form_tag batch_invite_users_path, :method => :post do %>
<%= label_tag "Email ids of people you'd like to invite." %>
<%= text_area_tag :user_emails %>
<%= submit_tag "Invite!" %>
<% end %>
A couple of notes :
If you like your controller skinny, you could move the logic to the model, for instance, by creating a send_batch_invitations method in your User model and pass the params[:user_emails] as an argument to that method from the users controller.
Since the method that sends the invitations could take sufficient time to complete, I would suggest you assign this task to a background job processor, such as delayed_job or resque.
There are railscasts that demonstrate the usage of these two background job processors.

Resources