Rails devise registration two ways after sign_up - ruby-on-rails

I want devise to redirect to specific controller index action( or specific page) after user is sign_up.
In detail, i have an app with 2 ways to sign-up : for the client and for the Professor . Actually, the 2 type use the same registration page, it works very nice but when they sign_up they are automatically redirect to the same page ...
So, i want to change the way like this :
- when user click on I want to become Professor i want to register (full name, mail, password) and redirect after sign_up to the Professor dashboard
- and when user click on Client i want to register with the "same way" BUT in the end, i want to redirect to the client's dashboard.
So, i started to change devise.rb to change this
config.allow_unconfirmed_access_for = 2.days (automatically login after sign_up)
And in my RegistrationsController, i override the after_sign_up_path_for to have something like
def after_sign_up_path_for(resource)
if 'user is Prof'
redirect_path_professor
else
redirect_path_client
end
end
but how can i check (in condition) if user click on Prof. or Client ?. Its the same resource (registration) ^^
Thanks

Why not using only one link, then let the user selects his role in the registration view?
If you really want two links for the same view, you should pass the role in a param (something link link_to 'Becoming a Professor', new_registration_path(role: 'professor'), then add an hidden_field in your registration form with the value of the param.
= f.input :role, as: :hidden, input_html: { value: params[:role] }
But don't forget to validate the content of the params to avoid the bad values sent by teasing users
Also, after_sign_in_path_for(resource) should be in application_controller. You'll need a column in users to specify the role, and your method will looks like something like this:
def after_sign_in_path_for(resource)
stored_location_for(resource) || (resource.role.professor? ? professor_dashboard_url : user_dashboard_url(resource))
end

Related

Accessing Params in Rails 3.2

I am working through the RailsApps Stripe tutorial.
When a new subscriber is created through a devise registration controller they are then directed to their content page through a content controller. I want to use their name and email address created upon registration on their content page. But I can't seem to bring the params into the content controller.
I put#user = User.find(params[:id]) into the content_controller but I get the error "Couldn't find User without an ID".
On the error page it lists under Request Info > rack session: "warden.user.user.key"=>["User", [2],
So does that mean that ID of User #2 is being passed to the content_controller but that I can't access it?
I put#user = User.find(params[:id]) into the content_controller but I
get the error "Couldn't find User without an ID".
This error means that params[:id] = nil, i.e., you are not passing id in the params hash when redirecting the user to content page.
Possible Solutions:
With Devise you get a helper method called current_user which returns an instance of currently logged in user. So, you could directly use current_user to access the attributes of currently logged in user. For example:
To access name and email fields of currently logged in user, all you need to do is
current_user.name
current_user.email
In routes.rb, pass the id of the currently logged in user via the route of content page as below:
## Add :id dynamic segment to your content page route
get "content/:id", :to => "contents#action_name", :as => "content_page"
Since, I don't have the route details, you would need to modify the above route as per your requirement.
Next, when redirecting the user to content page after sign up just pass the currently logged in user as below in ApplicationController method named after_sign_up_path_for (You need to override this Devise method if you want to redirect the user to a different route than the default root path):
def after_sign_up_path_for(resource)
content_page_path(resource) ## Provide the path and pass resource to it
end
With Devise, you can access the currently logged in user via the current_user helper in your controller.
See documentation: https://github.com/plataformatec/devise#controller-filters-and-helpers

Registration with Devise with only email field on page with other form

I want to give users posibility to add content not being registered but show 'registration form' above submit button on my 'content form'. How to do that using Devise gem? Or maybe I should use some other gems for this functionality?
Thanks.
Generated in standard view user login is default by email. If you wont show registeration form directly in place you want put render file with registeration form:
<%= render :file => 'users/registrations/new' %>
I propose to review the wiki: How To: Add sign_in, sign_out, and sign_up links to your layout template
and RailsCasts: Episode 210
You can register the user in the back-end (for default configuration):
user = User.new(params[:user])
if user.save!
#some logic, where user adds content
else
#some logic
If you want to register only with the email, you will need to generate a password, and for example, send it to the user email. See more there: https://github.com/plataformatec/devise/wiki/How-To:-Automatically-generate-password-for-users-(simpler-registration)/

Helper method for url?

I have multiple fields for social networking websites where users can enter their username and it would link to their twitter, facebook, myspace account etc. My problem is how can I have it so when a user enters their username I can link to their account.
Here's what I have and I know this is probably not correct. In my profile index.html
<%= link_to twitter_url %>
profile helper method
def twitter_url
return(self.url= "http://twitter.com/#{profile.twitter}/account")
end
In my profile controller
include ProfilesHelper
The actual field in database is called
twitter_link
How can I get the just the user username then on my part which will do the rest link to their twitter, facebook etc account page?
How is that method supposed to know what the profile object is without you passing it in?
I'm imagining there being a #profile variable defined in your controller. In the view, you would have this:
<%= link_to twitter_url %>
And in the helper, this:
def twitter_url
"http://twitter.com/#{#profile.twitter_link}/account"
end
Note here that you don't need to set self.url or have an explicit return. This is because the method will automatically return a String which is what link_to takes.
If you want this method to be in a helper that's available in just your ProfileController, then why not put it inside ProfileHelper so that it's automatically included just by being related by name?

Devise. Registration and Login at the same page

I'm trying to integrate Devise into my application. I need implement login form at top of the page (I've implemented this form into layout page) and I've implemented registration which contains registration form.
But it shows validation errors for both form when I tried submit incorrect registration data.
Without more information, it's hard to guess what the problem is. I've found the Wiki pages to be really helpful (and increasingly so), though you may have already looked them over:
Devise Wiki Pages
Two pages that might be relevant to your needs:
Display a custom sign_in form anywhere in your app
Create custom layouts
Hope this helps!
-- ff
The problem of seeing the validation errors for both forms stems from the 2 things. First, devise forms use a generic 'resource' helper. This creates a User object, and that same user objet gets used for both the sign up and the sign in form. Second, devise errors are typically displayed using the 'devise_error_messages!' helper which uses that same shared resource.
To have sign in and sign up on the same page you need to create different user objects for each form, and a new way of displaying the error messages.
First off, you'll need to create your own registration controller (in app/controllers/users/)
class Users::RegistrationsController < Devise::RegistrationsController
include DevisePermittedParameters
protected
def build_resource(hash=nil)
super
# Create an instance var to use just for the sign up form
#sign_up_user = self.resource
end
end
And update your routes file accordingly
devise_for :users, controllers: {
registrations: 'users/registrations'
}
Next you'll need your own error messages and resource helpers. Create a new helper like devise_single_page_helper.rb and add the following:
module DeviseSinglePageHelper
def devise_error_messages_for_same_page(given_resource)
return "" if given_resource.errors.empty?
messages = given_resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
sentence = I18n.t("errors.messages.not_saved",
count: given_resource.errors.count,
resource: given_resource.class.model_name.human.downcase)
html = <<-HTML
<div id="error_explanation">
<h2>#{sentence}</h2>
<ul>#{messages}</ul>
</div>
HTML
html.html_safe
end
def sign_up_user
#sign_up_user ||= User.new(username: 'su')
end
def sign_in_user
#sign_in_user ||= User.new(username: 'si')
end
end
Finally, in your views, update your forms like so:
-# The sign up form
= simple_form_for(sign_up_user, url: registration_path(resource_name)) do |f|
-#...
= devise_error_messages_for_same_page(sign_up_user)
-# The sign in form
= simple_form_for(sign_in_user, url: sessions_path(resource_name)) do |f|
#...
= devise_error_messages_for_same_page(sign_in_user)
All of this together gives you 2 different objects - 1 for sign up and 1 for sign in. This will prevent the error messages from one showing in the other. Please note that recommend putting both forms on your sign in page (and perhaps having the default sign up page redirect to the sign in page) because by default a failed sign in attempt will redirect to the sign in page.
You should have two forms on the page — one for signing up and one for registering. If you want a single form and multiple potential actions you are going to need a couple buttons that get handled client side and change the form's action & method to the appropriate route depending you want to create a user or a session.
If you think you did this already, the problem almost certainly lies in your code. If you were to share it with us we could perhaps point out something you may have missed.

Best way to allow admin to build objects for Admin

My objective is to allow Admins the right to sign Users up for a Project.
Currently, Users can sign themselves up for Projects.
So I was thinking in order to allow Admin to do this.. do something like this :
haml
= link_to "Project Signup", card_signups_path + "?user=#{user.id}", :class => "button"
And pass the params[:user] so I can replace this controller with this :
if params[:user]
#card_signup = User.find(params[:user]).build_card_signup
else
#card_signup = current_user.build_card_signup
end
The trouble is though.. this is a 3 part signup process, and its loaded VIA AJAX, so I can't pass the ?user=#{user.id} in any of the steps after the first.. ( at least not by the same convention that I already did, or know how to )
What kind of strategy would you employ in this?
One possible way of accomplishing this, would be to add a hidden field to your form, that mirrors the parameter your passing in, if its found.
So if the parameter your passing in is user, in your view you want to add a hidden field something like:
<input type="hidden" name="user" and value="<%= params[:user] %>" />
or with a rails form helper:
hidden_field_tag 'user', params[:user]
This way the code in your controller can check for this parameter at each step on the receiving end and know who to save the object for. Something like this:
def create
#card_signup = CardSignup.new(params[:card_signup])
if params[:user] && params[:user].to_i > 0
##
##some logic here to make sure current_user is admin, as no one else is allowed to do this
##
#card_signup.user_id = params[:user]
else
#card_signup.user_id = current_user.id
end
##onto validating model and saving / redirecting / etc
end
But the ultimate goal here is to keep the user param around, whether its an initial GET parameter to the page, or a Put/Post from ajax/etc to submit the form, this parameter will be around.
One other security angle to check would also be in the 'new' action of this controller, and check that if the user param is present then the current_user is an administrator, otherwise redirect or display an error message. This combined with re-validating this on the create should provide a decent way of making sure no one else can make these requests. You could also put this in a before_filter and call it for only new and create to keep things clean.

Resources