I would like to have access to the user information in the invitation/accept route. When I go to the form and use
<%= resource.name %>
it won't display the User. It also appears that it isn't loading the user during the accept. Is there an easy way to show the user some information about the invite?
I can think of two options:
You could override the devise invitable controller, see:
Anyone have experience with devise_invitable?
In my case, I wanted to pass the name of the invitor.
I add an integer attribute 'invitor' to the User class. This is the id of the invitor Person. Don't forget to add 'invitor' as attr_accessible in the model.
I already had a 'name' string attribute in the User class.
In the app/views/{users|devise}/invitations/new.html.erb (path may vary depending on how you generated the views) add a hidden form field with the logged in user (invitor):
... <%= f.text_field :invitor, :value => current_user.id, :hidden => true %> ...
In the email text app/views/{users|devise}/mailer/invitation.html.erb I can refer to the invitor:
... <%= (User.find #resource.invitor).name %> has invited you to <%= root_url %>, you can accept it through the link below....
Not that elegant, but it works. Improvements that survive updates of the devise_invitable gem are welcome.
Related
As a total Ruby noob i need to do a simple thing but doing it the ruby way is not clear for me.
What is want to do is the following:
I have a devise User model with a one to one association "Account"
In the devise registration view i want to add extra form fields for this account, and that is where i am stuck.
It seems i cannot add the account fields to the view
for example this will not work:
# address is a field of Account
<%= f.text_field :address %>
How can i bring the Account model into the scope? Or is there a way to do something like this
<%= f.text_field :account['address'] %>
I have really no clue how to add account into scope or how i can access the User assoc Account properly.
Thx for the help
You need to use accepts_nested_attributes_for :account to able to add parameters from registration form.
Then whitelist these parameters by overriding devise method configure_permitted_parameters.
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [account_attributes: [:address]])
end
You might need to change which parameters needs to be whitelisted.
Then in view, you need to use fields_for like
f.fields_for(:addresss) do |address_fields|
<%= address_fields.text_field :address %>
end
Hopefully, this solves the problem. Try to search about nested attributes if something doesn't work.
you need to override devise RegistrationsController from there modify on create method to build account record when user successfully sign up
When I create a form using simple_form_for #model, upon submit the post params has all the attributes grouped under params[model]. How do I get simple_form to drop this grouping and instead send it directly (under params root)?
<%= simple_form_for #user, do |f| %>
<%= f.input :name %>
<%= f.input :password %>
<%= f.submit %>
Now the name and password attributes would normally be sent under params[:user][:name], params[:user][:password] etc. How do I get simple_form to post these as params[:name], params[:password] etc.?
Thanks!
Ramkumar
ps: In case you are wondering why I need this, the bulk of my app is to serve as an API and I have built a set of methods to validate a request which expect some attributes to be in root. In a rare instance (forgot password), I actually need to present a form and I am looking for a way to use these methods.
you can explicitly define the name for an input by passing input_html to it:
input_html: { name: :name }
(needed this myself for sending an resource to a thirdparty endpoint with redirect to my side which relied on the plain attribute names, but i actually wanted not to built up label and input via the tags ;) )
also see simple form builder impl
Two ways I can think of:
The first is, don't use simple_form to build your form, but do it by hand or with the form_tag and *_tag methods. These will allow you to more closely specify what parameters are used in your form.
If you want to keep simple_form, though, then have it call a different controller action. Refactor the controllers to strip out the logic into a separate method. Something like:
class UsersController
def create_from_api
controller_logic(params)
end
def create_from_form
controller_logic(params[:user])
end
def controller_logic(params)
[actual work happens here]
end
end
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.
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.
I have a model, and I have a view that displays a form for creating a new object based on that model. Let's call that form, Form1.
Once the user submits Form1, the object is created. I then want to display, on the following page, a second form Form2, which asks the user to check off various options before the object is saved to the database.
My problem is probably extremely basic. I don't know how to create Form2, given that it is not tied directly to the model. Because I am a Rails newbie, I have only created forms as following:
form_for(#object) { |f| ... }
#object is an object instantiated from the model
Problem: I do not believe that kind of code will work for my purposes here. How do I create Form2, given that it must not be based on #object or #object's model?
Some specifics from my app:
The site accepts values (Form1) before redirecting to an OAuth server.
When the user verifies her credentials on the OAuth server, she is redirected back to my site. An XML-RPC request then retrieves information about the user's account on the OAuth server.
The XML response may indicate that the user has only one account on the OAuth server. If so, some values are retrieved from the XML and added to the object--which is then (finally) saved in the database--and the user is redirected to a success page.
However, if the XML response indicates that the user has multiple accounts on the OAuth server, I want to display a form (Form2) that allows the user to select which accounts on the OAuth server to associate with my site. So Form2 really asks the user how many objects to create, rather than about specific attributes of an object.
Use form_tag instead of form_for, then use the appropriate form helpers: text_field_tag instead of f.text_field, text_area_tag instead of f.text_area, etc. Example:
<%= form_tag "/my_controller/update2" do %>
<%= text_field_tag "account", "default info" %>
<%= submit_tag "Save" %>
<% end %>
The Rails API site has a great reference to all of the _tag helpers: http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html
Starting in rails3, validations have been decoupled from ActiveRecord so you can create vanilla objects that can be used as validators with the form helpers:
class Person
include ActiveModel::Validations
attr_accessor :first_name, :last_name
validates_each :first_name, :last_name do |record, attr, value|
record.errors.add attr, 'starts with z.' if value.to_s[0] == ?z
end
end
and then in your template:
<%= form_for(Person.new) do |f| %>
...
It's a handy way to get the benefits of the form helpers for things like email forms without having to create a model object tied to your schema.
To create a table-less model,
class Person
include ActiveModel::Model
attr_accessor :first_name, :last_name
validates :first_name, :last_name, presence: true
end
Then in your view,
<%= form_for(Person.new) do |f| %>
.... your form ....
<% end %>
Another similar solution can be found at RailsCasts:
Active-Model
If you are looking to use SimpleForm then there is a specific answer for that here Does form_tag work with Simple_form?