Custom message in devise invitable email - ruby-on-rails-3

How do you pass a custom message to the devise invitable email? I want the inviter to include a message to the invitee, like "Hey check out this site".
I tried both including it in the attributes and setting an instance variable in the block, neither seem to be accessible from the email.
user = User.invite!(:email => share.to_user_email, :message => "hey check this out") do
#message = "hey it's me!"
end

you have to do rails generate devise_invitable:views users
then you will get new erb file app/views/users/mailer/invitation_instructions.html.erb which you will be able to customize in any way you want

Email template will allow you to send same message for all the emails.
Here is another way/case, when you are taking message as an input from user.
model/user.rb
attr_accessor :message
controller
User.invite!({email: email}, current_user) do |user|
user.message = params[:message]
end
/views/devise/mailer/invitation_instructions.html.erb
<p>Hello <%= #resource.email %>!</p>
<p><%= #resource.message%>.</p>

the content of the mail is in app/views/devise/mailer/invitation_instructions.html.erb. By default it is:
<p>Hello <%= #resource.email %>!</p>
<p>Someone has invited you to <%= root_url %>, you can accept it through the link below.</p>
<p><%= link_to 'Accept invitation', accept_invitation_url(#resource, :invitation_token => #resource.invitation_token) %></p>
<p>If you don't want to accept the invitation, please ignore this email.<br />
Your account won't be created until you access the link above and set your password.</p>
modify this file to customize.

Related

Send Email Again in device system in rails

I have a question about the area to send again the email to confirm the account.
The previous developer of the website added this
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
<%= link_to 'Send Email Again', new_confirmation_path(resource_name) %>
<% end -%>
Why?
I am new on rails, but I don't undestand why he added this if condition.
Also because I noted that I can see this link both logged both not logged.

Is there any way to avoid having the browser's address changed after using "render"?

I am currently following the Ruby on Rails Tutorial by Michael Hartl. And there is something that has been bugging me for quite some time. I looked it up but I still can't find a good answer.
Anyway, I've noticed is when you have a validation error in the signup page it renders the original signup page and changes the nav bar address. I've matched /signup to the action new, but if I use render it changes from /signup to /users (the default, because of the RESTful standard I guess).
I'll leave some lines of my code:
routes.rb
resources :users
match '/signup', :to => 'users#new'
users_controller.rb
def new
#user = User.new
#title = "Sign up"
end
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Welcome to the Sample App!"
redirect_to user_path(#user)
else
#title = "Sign up"
#user.password = ""
#user.password_confirmation = ""
render 'new'
end
end
So I've tried to work around this by not using the render method but redirect_to instead but I'm having trouble using it. As it is actually sending data to the path provided, #user.errors gets overwritten by creating a new instance of the model and the flash variable cannot show the errors.
_errors.html.erb
<% if #user.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#user.errors.count, "error") %>
prohibited the user from being saved:
</h2>
<p>There were problems with the following fields:</p>
<ul>
<% #user.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
My question is: is there any way that by using render I can change the url displayed on the navbar? It's really frustrating if someone makes a mistake in the signup form, presses enter in the navbar and ends up in a totally different place.
The reason why the address changes is because you have performed a POST request to /users/ therefore the browser is doing the correct thing by displaying the different address.
There are a few of ways around this:
Store the invalid User object and redirect back to the Users.new action.
Change the URL of the Users.create action.
Use history.replaceState to change the user's address bar.
The first option keeps the controller more RESTful, however it will need use of the :session or flash to persist the data across the redirect.
The second option keeps the code simpler, but involves fiddling with the routes.rb file.
The third option relies on javascript and support for HTML5 to mess with the user's browser history.
Personally I would leave the URL as is, but if I had a client who insisted on doing this, I would go for the second option.

How can I update only a single field of a user profile in Rails 3?

I'm adapting the authentication system from Rails 3 Tutorial by Michael Hartl to better learn about rails before (most likely) switching to a system like authlogic or devise. My authentication system works great, and I have a user model that now includes fields that build a user profile. For example, users can write a blurb about themselves such as "tennis player, rock climber".
What I'd like to do is to be able to have a simple form that updates only that specific field ("blurb"). I've set this up on a user profile page where the user clicks a link called "edit" and this causes a partial to render showing a form with a field to update a user blurb as such:
in _edit_blurb.html.erb:
<div class = "editforms">
<%= form_for current_user do |f| %>
<div class="field">
<%= f.text_field :blurb, :class => "inputform round", :placeholder => "blurb" %>
</div>
<div class="actions">
<%= f.submit "Update", :class => "submit_button round mini_button" %> <br>
</div>
<% end %>
</div>
This form submits to an update action in the users controller, and for the most part updates the user blurb and nothing else. However, one glitch is that this update action submits a nil password (as there is no password field in the form) - leading to a change in the user password. This is problematic for obvious reasons. Originally, I added a line :if => lamdba {new_record? || !password.nil? } to the password validation to allow the update from the edit_blurb partial to update without needing a password. But, as you can see this allows for a nil password to be saved.
validates :password, :presence => true,
:if => lambda{ new_record? || !password.nil? },
:confirmation => true,
:length => { :within => 6..40 }
How can I alter either the form or the validation (or both) so that a user can update a blurb without updating/inputting his password (and fixing the reset-to-nil password update problem)?
I think I've provided the relevant code, but will add more if it will help! Thanks everyone!
what you'll want to do is prevent the user model from saving the password when the password value is nil. I don't know how your user model is set up, but if you've been following MH's railstutorial, the password should be saved by a method called:
before_save :encrypt_password
in User.rb. To fix this, add:
before_save :encrypt_password, :if => lambda { !password.nil? }
This should work.

Ruby on Rails: Custom Actions (Follow up)

This question is a follow up to this previous question: Ruby on Rails: Custom actions
As a follow up, what would be the syntax to use a custom action in a form_for? For my app, I have a partial called _invite_form.html.erb, and set the form to have a :url specification that I thought would link the form to the invite action on the Users controller:
<div id = "invite_form">
<h1>Invite</h1>
<%= form_for(invited, :url => invite_user_path) do |f| %>
<div class="field">
<%= f.text_field :email, :class => "inputform round", :placeholder => "email" %>
</div>
<div class="actions">
<%= f.submit "Invite", :class => "submit_button round" %>
</div>
<% end %>
</div>
This partial is called on certain pages, and this error is given:
"No route matches {:action=>"invite", :controller=>"users"}"
In my routes.rb file I have included the appropriate lines:
resources :users do
member do
get :invite
post :invite
end
end
Why is it that the route doesn't work? How do I change these files to make the form use the action "Invite" on the Users controller?
** Forgot to mention earlier: I defined invited in the Users helper: users_helper.rb:
module UsersHelper
def invited
#invited = User.new(params[:user])
end
end
As you don't have a persistent User just yet, make this a collection operation by:
Changing invite_user_path to invite_users_path in your controller
Changing member do to collection do in your routes
invite_user_path expects a user as an argument. Try invite_user_path(invited). You will also need to save the user before you can compute a path to it.
To experiment, go into rails console and see the difference between the following:
app.invite_user_path
app.invite_user_path(User.first)
app.invite_user_path(User.new)

Forgotten Password in Rails

I am trying to implement a forgotten password solution in rails. I have a form for the user to enter the email address for their registered account, and I intend to have a mailer email them a unique URL that will link them to a password reset page.
My config/routes.rb file has the following routes:
resources :users do
collection do
get :lost_password #the account-email submisison form url
get :reset_password #a url for the function that sends the response email
end
end
When I run rake routes from the console, I get the paths I want:
lost_password_users GET /users/lost_password(.:format) {:action=>"lost_password", :controller=>"users"}
reset_password_users GET /users/reset_password(.:format) {:action=>"reset_password", :controller=>"users"}
users GET /users(.:format) {:action=>"index", :controller=>"users"}
POST /users(.:format) {:action=>"create", :controller=>"users"}
BUT! When the user hits the submit button on the form outlined in the code below:
<h3>Reset Password</h3>
<%= form_for(:user, :url => reset_password_users_path) do |f| %>
<p>Enter the email address you used to register for this site.</p></br>
<div class="field">
<%= f.label :email %> </br>
<%= f.text_field :email %>
</div>
<div class="actions">
<%= f.submit "Send Email" %>
</div>
<% end %>
I get a
No route matches
"/users/reset_password"
error through the ActionController.
I do, in fact, have views and controller functions defined for both the lost_password_users_path and the reset_password_users_path, so I'm puzzled as to why I would run into this routing error.
I have two questions:
Why would the ActionController raise this error, when I clearly have the path, methods, and views defined?
Has anyone else implemented a password reset in RoR, and can you lend any insight as to whether or not this approach is good practice?
Thanks in advance!
Try changing get :reset_password to post :reset_password in routes.rb
function of reset password: I hope,it will be work, use in controller update function
if params[:user][:password].present?
puts "present"
puts params[:current_password]
if (params[:user][:password] == "")
params[:user].delete(:password)
else
if #user.valid_password?(params[:current_password])
#updated = true
puts #updated.to_s
#user.update_attributes(user_params)
sign_in(#user,:bypass => true)
flash[:notice] = "Password Updated Successfully"
redirect_back fallback_location: user_url
else
#updated = false
puts #updated.to_s
flash[:danger] = "Current Password does not matched"
redirect_back fallback_location: user_url
end
end