Rails Authentication - Query on Customizing Devise Views - ruby-on-rails

I am a Devise fan and have used Devise for many of my Ruby on Rails applications .
I usually follow the below RailCasts for installing and customizing Devise .
http://railscasts.com/episodes/209-introducing-devise
http://railscasts.com/episodes/210-customizing-devise
The video tells us that if we want to customize the views , we need to run the below command -
rails generate devise:views
This creates the views related to authentication in the apps/views/devise folder . We can customize the look and feel .
My questions is - How do we allow multiple views for signing in ? For eg - I want to allow the user to be able to Login from the Root page itself by clicking a Login button on a navbar which leads to a modal box ( overlay / popup ) which allows the user to enter his login credentials , instead of having to visit the predefined pages generated by Devise.
You can have a look at the below link to see the project I am working on now .
http://squilio.heroku.com/ .
Try clicking on the Login button. I would like to have my signin form here .

the railscast episode you saw is too old ( Apr 12, 2010), latest Devise version is 2.0. so I think some of the features is deprecated.
For your question: If you want to have 2 different pages (e.g. 1 is a dialog/pop up by ajax, another is regular erb page), you have to implement 2 different actions, or at least you have to implement 2 different strategies for them. e.g.
# will render app/views/.../regular_login.html.erb
def regular_login
end
# render a dialog box only.
def dialog_login
render :layout => false
end

I found an elegant solution from this article ..
https://github.com/plataformatec/devise/wiki/How-To:-Display-a-custom-sign_in-form-anywhere-in-your-app
It shows how we can achieve this by using form_for and posting to user_session_path
<%= form_for("user", :url => user_session_path) do |f| %>
<%= f.text_field :email %>
<%= f.password_field :password %>
<%= f.check_box :remember_me %>
<%= f.label :remember_me %>
<%= f.submit 'Sign in' %>
<%= link_to "Forgot your password?", new_password_path('user') %>
<% end %>

Related

Two different login pages for one model with devise on rails

I am working on an rails app in which there is one table Users, which has two roles Admin and member. Until now I am using single login page.
But now, I need to make two different login pages with completely different styling for admin and member.
Moreover Admin don't have sign_up option but member has.
I am totally confused that is it possible or not?
If possible, how to achieve this.
Devise sign in form is just a form with action matching to devise controller.
You can write this form code anywhere you like,
<%= form_for(:user, :url => session_path(:user)) do |f| %>
<%= f.text_field :email %>
<%= f.password_field :password %>
<%= f.check_box :remember_me %>
<%= f.label :remember_me %>
<%= f.submit 'Sign in' %>
<%= link_to "Forgot your password?", new_password_path(:user) %>
<% end %>
Adding to #maximus answer, you could use the Pundit gem to define your logged in :user action through a UserPolicy controller. Within this controller, you should be able to define which direction a passed in User navigates to defined by their logged in role.
https://github.com/elabs/pundit

re-use views on rails

I can't find a way to use views from other views.
I think I can explain it better with this example: I have two controllers, IndexController and UserController. The user controller has an action called login with its view which renders the login form and validates the user when a post from its form happens.
In IndexController, there is an action called home which renders the home page view. In this view I want to render the loginform, but I want to re-use the user/login view.
In almost all the frameworks I worked with there is a way to call another controller action in order to re-use and isolate the logic.
I find that, in Rails, there is a helper render that I can call in the following way:
render 'user/login'
or
render :template => 'user/login'
In both cases I only get errors like "the route index/login does not exist" or "the controller index has to login action". Besides, I set the login view file name as login or _login. (I read that is used for partial views.)
You can do this by creating a shared folder within your views folder and create the login form as a partial.
So your login partial might be something like this.
/app/views/shared/_loginform.html.erb:
<div id="loginform">
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
<%= f.text_field :email %>
<%= f.password_field :password %>
<%= f.submit "Login" %>
<% end %>
<div id="loginlinks">
<%= link_to "Become a member", new_member_registration_path %> <br />
<%= link_to "Forgot Password?", new_member_password_path %>
</div>
</div>
Then in your views just call:
<%= render "shared/loginform" %>
You should take a look at Railscast: "#269 Template Inheritance".
Since Rails 3.1, controller inheritance now applies to views as well. This is preferred over the older "shared folder" strategy.
In short, you put your shared partials in app/views/application then you can override them in your resource specific view directories (e.g app/views/users).

Rails Advanced Sign Up Implementation How To?

I am a three week old Rails newbie and I have something that I want to implement but have no idea how to go about it. I'm making an app:
I want a user to enter some sign-up info on the new users view page, then, when they click submit, instead of the user being created and saved in the database right away, instead I want them to be taken to a second webpage where they will be asked for some final verification before they can create their account. Then when they click 'verify' and the verification passes, the account is finally created and saved to the database.
This is hard for me because I only know how to make basic forms, where you enter info, hit submit, and you have a new entry in the database. I don't know how to defer the "user creation" for another webpage, but a friend has mentioned something about http requests, but I still don't know anything. I'll post some of my code so far:
My users_controller new definition:
def new
#user = User.new
#user.websites.build
end
My users_controller create method:
def create
#user = User.new(params[:user])
if #user.save
sign_in #user
flash[:success] = "Welcome!"
redirect_to #user
else
render 'new'
end
end
My users/new.html.erb sign up form:
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<%= render 'shared/error_messages' %>
<%= form_for(#user) do |f| %>
<%= f.label :email %>
<%= f.text_field :email %><br/>
<%= f.label :password %>
<%= f.password_field :password %><br/>
<%= f.label :password_confirmation, 'Confirm Password' %>
<%= f.password_field :password_confirmation %><br/>
<%= f.fields_for :websites do |builder| %>
<%= builder.label :url, 'Website URL' %>
<%= builder.text_field :url %>
<% end %>
<%= f.submit "Sign up", :id => 'submit' %>
<% end %>
I've never asked a question that's just asking for advice like this before, so I'm hoping this is the right place to ask. Any and all help is appreciated.
I think you are trying to create a "multistep" form...
There is a very good railscast about it: http://railscasts.com/episodes/217-multistep-forms?view=asciicast
However, you might face some validation problems, as you need to validate each step individually. So, take a look also here: http://guides.rubyonrails.org/active_record_validations_callbacks.html#conditional-validation
I hope it helps...
You'd better use Devise for user management.
https://github.com/plataformatec/devise
Here's a railscast tutorial.
railscasts.com/episodes/209-introducing-devise
If you're doing multistep, you can always pass information from one page to another. You can store it in a session array, repost it to the other page, or even make a cookie.
Remember to also do every step of this under https, because account creation requires sensitive info.
If Rails is your first I would actually recommend something lower level like PHP so you can understand how everything works before you start doing stuff with a high level framework like rails. MVC is usually not the best first step in web development, even though it is powerful and easier than doing everything from scratch.

passing options when using methods in a rails gem

I'm using this gem for Facebook authentication in my Rails app.
I'm having some issues in IE and I think it's because of an issue in the Javascript in this file -
If you look at line 52, it seems I can pass options into channelUrl.
I'm implementing a login button like this -
<%= fb_login(:text=>"Log in") %>
Can I do this from my app, or do I need to edit the gem?
If I look at the README, you should have a partial like this one:
<%= fb_connect_async_js %>
<% if current_facebook_user %>
<%= "Welcome #{current_facebook_user.first_name} #{current_facebook_user.last_name}!" %>
or
<%= "Hello #{fb_name(current_facebook_user, :useyou => false)}!" # link to facebook profile %>
<%= fb_logout_link("Logout of fb", request.url) %><br />
<% else
# you must explicitly request permissions for facebook user fields.
# here we instruct facebook to ask the user for permission for our website
# to access the user's facebook email and birthday
%>
<%= fb_login(:text => 'Log in', :perms => 'email,user_birthday') %>
<% end %>
In that case, you just have to pass the options to fb_connect_async_js:
<%= fb_connect_async_js :channel_url => 'http://blahblah' %>
... rest of the partial ...
If your partial doesn't look like the one above, you should edit your question to post yours (the full one).

Adding "linked accounts" (e.g., Twitter, Facebook) to a Rails 3 website

This isn't a question about how to use Twitter or Facebook API, but a simpler one about how to keep the databases in sync. What I want to do is to create a NEW linked account, and then attach that to the current user. I KNOW that my code currently is nonfunctional:
On the Edit Profile page
<%= f.label :account %> <i>(link another account to this profile)</i><br />
<% form_for #user.linked_accounts do |f| %>
<%= f.text_field :username %>
<%= f.collection_select :service, User::POSSIBLE_SERVICES, :to_s, :to_s,
:include_blank => true
%>
<%= f.submit %>
<% end %>
How do I get it to submit into a devise database? It's definitely the " form_for #user.linked_accounts " I need to fix. I changed it to #user and I get a no-method error because :service is only defined in a linked account. I think that what I need to do is to create a new linked account, and then do the form_for #user.new_account.
The error I receive is:
SQLite3::SQLException: no such column: linked_accounts.user_id: SELECT "linked_accounts".* FROM "linked_accounts" WHERE ("linked_accounts".user_id = 1)
There is a railscast that deals with this. It uses an authorisations table which belongs_to the user table so you can add twitter, facebook etc... to the user
The cast is over 2 episodes and uses omniauth which is a really neat solution. You can find them here
http://railscasts.com/episodes/235-omniauth-part-1
http://railscasts.com/episodes/236-omniauth-part-2
if i correctly understand your problem it's may be a solution for you to :
create a new model to contain social network information
use nested model to allow adding social via the edit user form
And that's it

Resources