can't direct manual login away from sessions#create - ruby-on-rails

Running Ruby 1.9.3p545 rails 4.1.4
I have an application where users canlogin through facebook, twitter, etc and can rehister manually. I would like a logon process for those who have registered manually.
Routes are
get 'auth/:provider/callback', to: 'sessions#create'
get 'auth/failure', to: redirect('/')
get 'signout', to: 'sessions#destroy', as: 'signout'
get "sign_up" => "profiles#new", :as => "sign_up"
get "log_in" => "logins#new"
post "log_in" => "logins#login"
Everything works fine except the manual logi. logins.new presents a form ok bu the subsequent submit always ends up in sessions controller at create.
I defined a login controller and tried to use the above post in the routes to get it away from the omniauth process in sessions#create.
The login form is
Log in
<%= form_tag sessions_path do %>
<p>
<%= label_tag :email %><br />
<%= text_field_tag :email, params[:email] %>
</p>
<p>
<%= label_tag :password %><br />
<%= password_field_tag :password %>
</p>
<p class="button">
<%= submit_tag "Sign in" %>
</p>
<% end %>
logins#login is
def login
authorized_user = Profile.authenticate(params[:name_or_email],params[:password])
if authorized_user
flash[:notice] = "Wow Welcome again, you logged in as #{authorized_user.username}"
redirect_to(:action => 'home')
else
flash[:notice] = "Invalid Username or Password"
flash[:color]= "invalid"
render "login"
end
Is tehre any way I can direct the submit of the login form away from the sessions controller?
Thanks in advance
end

The line
<%= form_tag sessions_path do %>
is what's throwing things off. It makes the form post to sessions_path. Try replacing it with <%= form_tag log_in_path do %>, or, better, yet, replace it with <%= form_tag "" do %> since the default is to post to the same URL as the current page.
Some more clarification:
<%= form_tag sessions_path do %>
generates the following HTML (roughly, skipping some details that aren't relevant to this issue):
<form action="/sessions" method="post">
since /sessions is the path to sessions#create. You want the action to be /log_in, i.e. the path to logins#login, so you want to change the argument you're passing to form_tag.
Since you're already on the page log_in, if you leave the action blank, i.e.:
<form method="post">
it will get you where you want, since the default behavior of the browser is to post to the same page.

Related

Failing test: Actionview template error (no route matches action: show, controller: users, id: nil) for updating user

I've got a failing integration test for updating users (Rails 5). The errors are listed and pointed out in the test and 'edit.html.erb':
require 'test_helper'
class UsersEditTest < ActionDispatch::IntegrationTest
def setup
#user = users(:user_one)
end
test "unsuccessful edit" do
get edit_user_path(#user) #---> This is where the error is happening, line 10
assert_template 'users/edit'
patch user_path(#user), params: { user: { name: "", email: "not#valid", password: "not", password_confirmation: "valid" } }
assert_template 'users/edit'
end
end
The error reads:
ActionView::Template::Error: No route matches {:action=>"show", :controller=>"users", :id=>nil} missing required keys: [:id]
app/views/users/edit.html.erb:7:in
test/integration/users_edit_test.rb:10:in
Fixtures as follows:
user_one:
name: Example One
email: one#example.com
password_digest: <%= User.digest('password') %>
user_two:
name: Example Two
email: two#exmaple.com
password_digest: <%= User.digest('password') %>
Edit.html.erb as follows:
<% provide(:title, "Edit Account") %>
<% provide(:button_text, "Save Changes") %>
<h1 class="center">Edit Account</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= render 'form', url: user_path(current_user) %> #---> The other error
</div>
</div>
_form.html.erb as follows:
<%= form_for(#user, url: url) do |f| %>
<%= render "shared/error_messages", object: #user %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :password_confirmation %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
<%= f.submit yield(:button_text), class: 'btn btn-primary' %>
<% end %>
I know that the url I'm passing to my form via 'edit' is correct because I'm getting the correct action when I check my web inspector. It reads "users/1" with a method of post, with an additional hidden field named "_method" with the value of "patch". The application functions this way but the test fails.
On line 10 in the test it's supposed to be getting the edit_user_path, but for some reason throws an error about the show action and says the id is nil. I've changed the url that I pass to be "edit_user_path(current_user)" but that gives me an error of "No route matches [PATCH] "/users/1/edit"" when I submit the form and also renders a similar test error except for listing the edit action instead of show. I've tried changing it to 'users_path(current_user)' which gets my test to PASS FINALLY, but gives me the incorrect action (action="/users.1") when viewing it in the web inspector - also won't allow me submit the form, saying: "No route matches [PATCH] "/users.1""
I'm following the latest Rails Tutorial by Michael Hartl and can't imagine what I could have missed to be stuck so bad on this (day two of trying to tackle this problem). My routes in case anyone is wondering:
root 'static_pages#home'
get '/about' => 'static_pages#about'
get '/help' => 'static_pages#help'
get '/signup' => 'users#new'
post '/signup' => 'users#create'
get '/login' => 'sessions#new'
post '/login' => 'sessions#create'
delete '/logout' => 'sessions#destroy'
resources :users
I can get passed all of this simply by giving edit.html.erb it's own form instead of rendering the form in it's view, passing test and all. So I'll probably continue on doing that, but I know there has to be a way, or at least some stupid mistake I need to fix, for me to be able to do this the way the tutorial is.

Ruby on Rails POST request fails

Here the thing goes, I wanna write a login in a page in Ruby on Rails, when the url is localhost:3000/admin, I'll get the page which need to fill in. After the form has filled in, I submit the button and the form should be admitted to the create action with post method, however it still works with get method and new action.
What happens to it?
Here is the routes.rb file:
Prefix Verb URI Pattern Controller#Action
new_admin_users GET /admin/users/new(.:format) admin/users#new
admin_users POST /admin/users(.:format) admin/users#create
admin GET /admin(.:format) admin/users#new
POST /admin(.:format) admin/users#create
posts_home GET /posts/home(.:format) redirect(301, /posts)
posts_about GET /posts/about(.:format) redirect(301, /about)
Then here is the new action
<form class="form-signin">
<h2 class="form-signin-heading">Please sign in</h2>
<%= form_for :user,url:admin_users_path do |f| %>
<p>
<%= f.label :name%><br>
<%= f.text_field :name ,class:"form-control" %>
</p>
<p>
<%= f.label :pass%><br>
<%= f.text_field :pass,class:"form-control" %>
</p>
<div class="checkbox">
<label>
<input type="checkbox" value="remember-me"> Remember me
</label>
</div>
<p>
<%= f.submit'Sign in', :class=>"btn btn-lg btn-primary btn-block" %>
</p>
<%= link_to 'Back', posts_path %>
<%end%>
</form>
Here is the routes.rb:
Rails.application.routes.draw do
namespace :admin do
resources :users
get "", to:"users#new"
post "", to:"users#create"
end
get "/posts/home", to: redirect("/posts")
get "/posts/about", to: redirect("/about")
resources :posts do
resources :comments
end
root "posts#index"
get "/home",to: "posts#index"
get "/about",to: "posts#about"
end
If you have some throught, please tell me, thanks in advance!
You must have the actual User object built inside your controller. Try using that inside your form instead of symbol :user.
<%= form_for #user, url: admin_users_path do |f| %>
...
You can try explicitly specifying the method post
Instead of
<%= form_for :user,url:admin_users_path do |f| %>
Use this:
<%= form_for :user,url:admin_users_path, method: :post do |f| %>
Also check the created action in form created such way
Hope this Helps

undefined method user_path' form_for

I have a UsersController and it has below code
def sign_up
#user = User.new
end
And my view page has
<div class="col-md-6 col-md-offset-3">
<%= form_for #user do |f| %>
<%= f.label :first_name%>
<%= f.text_field :first_name %>
<%= f.label :last_name %>
<%= f.text_field :last_name %>
<%= f.submit "Register", class: 'btn btn-primary'%>
<% end %>
</div>
My routes.rb file contains the following entry
get 'signup' => 'users#sign_up'
But When I submit the form, it says
ActionView::Template::Error (undefined method `users_path' for #<#<Class:0x00000004d91490>:0x00000004d90220>)
Why does this throw an error and do I need to explicity point to url in the form_for?? Why is it so??
Change your routes to:
resources :users, only: [:new, :create], path_names: {new: 'sign_up'}
and rename your sign_up action back to new. The reason you are getting the error is rails trying to guess the correct url for given resource. Since you have passed #user, which is an instance of User class, it will try to call "#{#user.class.model_name.route_key}_path key, which results in the error you got.
To solve the issue you need either make your routes to define users_path or you need to specify the url directly using url option. users_path can be defined by either index or create action, so the above solution will work (and will not create remaining CRUD routes, yey!)
Try changing this line:
<%= form_for #user do |f| %>
to this:
<%= form_for(#user, url: 'signup') do |f| %>

Setting routing for different forms on different tabs in the same view

I'm in need of some help regarding setting up the routing (I think that is the problem) for a view that is set up with bootstrap tabbed navigation. What I want to do is set up a form in each tab. Sounds easy enough.
However I can't figure out how the routing works when you want to submit two different actions (one to save to the db, and the other to get info from the db), each from their own tab. I can get it all to work perfectly if I give the "get_users" controller action a view, but when I try to bring it back together on the same page, just in different tabs, it goes a little awry and I'm not sure how to route correctly.
The two controller actions I have are:
class Users::RegistrationsController < Devise::RegistrationsController
def user_accounts
#user = User.new
end
def get_users
#users = User.search(params[:search]).paginate
(:per_page => 20, :page => params[:page] )
end
end
EDIT ------------------------------------
Include routes.rb - excluding the extra devise related routes. Can get the create_internal_user action working not the other. I understand that the routes are
incorrect as rails could never understand them. The first is correct, the second is simply what I would imagine it to look like if it were possible
# Authentication
as :user do
#add new internal users
get '/useraccounts' => 'users/registrations#user_accounts', as: 'new_internal_user'
post '/useraccounts' => 'users/registrations#create_internal_user', as: 'internal_user'
**# searching users - this is where I am uncertain**
get '/useraccounts' => 'users/registrations#get_users', as: 'get_internal_user'
post '/useraccounts' => 'users/registrations#get_users', as: 'getting_internal_user'
# other devise routes here
end
The view that renders them looks like this and renders two partials:
<div class="container">
<h1>User Accounts</h1>
<ul class="nav nav-tabs">
<li class="active">Add User</li>
<li>Edit User</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div class="tab-pane fade in active" id="adduser">
<%= render 'users/registrations/create_internal' %>
</div>
<div class="tab-pane fade in" id="getusers">
<%= render 'users/registrations/get_users' %>
</div>
</div>
</div>
The two partials
_create_internal.html.erb
<%= form_for(resource, as: resource_name,
url: new_internal_user_path(resource_name)) do |f| %>
<div><%= f.label :email %><br />
<% for role in User::ROLES %>
<%= check_box_tag "user[roles][#{role}]", role,
#user.roles.include?(role),
{:name => "user[roles][]"}%>
<%= label_tag "user_roles_#{role}", role.humanize %><br />
<% end %>
<%= hidden_field_tag "user[roles][]", "" %>
<div class="col-md-10 center"><%= f.submit "Create User",
class: "btn btn-primary"%></div>
<% end %>
_get_users.html.erb
<%= form_tag({:controller => "users/registrations", :action => "get_users"},
method: :get) do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
<div class="center" id="users">
<% if defined?(#users) %>
<%= render 'users/registrations/searchresults' %></div>
<%= will_paginate #users %>
<% end %>
I've spent many many hours trying to figure this out and just haven't been able to. Very new to Rails so this may be an easy question for someone. I've had a look at using AJAX, and resourceful routing, but as I'm still new I'm finding it a bit tough to wrap my head around it all at the one time. This is my first post on SO so apologies if I'm missing anything (please let me know).
Let's say your controller is UsersController and assuming your routes are not nested, this is how you create named routes:
get '/useraccounts', to: 'users#get_users' ## this route maps to the get_users action
post '/useraccounts' to: 'users#create_internal_user' # this route maps to the create_internal_user action
EDIT:
the format is controller_name#action_name. So make sure to replace users with your controllers name in plural
UPDATE:
if your controller's name is RegistrationsController
try:
get '/useraccounts', to: 'registrations#get_users'
post '/useraccounts' to: 'registrations#create_internal_user'
Looking at it, I think your error will likely be from your _get_users.html.erb partial.
Firstly, you're using form_for - why? Your use of form_for basically means you have to use the data inside #user to make it work, which I think will be causing the problem
I would use a form_tag as this does not persist your data:
<%= form_tag({:controller => "users/registrations", :action => "get_users"}, method: :get) do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
<% end %>
<% if defined?(#users) #-> this might need to be passed as a local var %>
<%= render 'users/registrations/searchresults' %></div>
<%= will_paginate #users %>
<% end %>
Routes
Your other problem is to do with your routes:
get '/useraccounts' => 'users/registrations#user_accounts', as: 'new_internal_user'
post '/useraccounts' => 'users/registrations#create_internal_user', as: 'internal_user'
**# searching users - this is where I am uncertain**
get '/useraccounts' => 'users/registrations#get_users', as: 'get_internal_user'
post '/useraccounts' => 'users/registrations#get_users', as: 'getting_internal_user'
Tell me how you expect Rails to know the difference between get '/useraccounts and get /useraccounts? The fact is it can't
You'll need to split up the routes so they don't all use the same path. I would do this:
get '/useraccounts' => 'users/registrations#user_accounts', as: 'new_internal_user'
post '/useraccounts' => 'users/registrations#create_internal_user', as: 'internal_user'
**# searching users - this is where I am uncertain**
get '/search' => 'users/registrations#get_users', as: 'get_internal_user'
After much frustration I have solved my own problem. With help from Rich Peck I realised that I was essentially creating a view with two forms on it, and that the tabbed navigation didn't really mean anything to the problem.
So I really only needed the two routes:
# #add new internal users
get '/useraccounts' => 'users/registrations#user_accounts', as: 'user_accounts'
post '/useraccounts' => 'users/registrations#create_internal_user', as:
'create_internal_user'
And then in the controller just changed the user_accounts action to look like this:
def user_accounts
#user = User.new
if params[:search_button]
#users = User.search(params[:search]).paginate(:per_page => 15, :page => params[:page] )
end
end
Came about this discovery thanks to this question/answer here:
form_for with multiple controller actions for submit
In the end the problem wasn't what I thought it was and ended up being simple. Was certainly an interesting learning journey. Thanks for your help again Rich Peck.

Passing parameter to link_to rails 2

I wrote the following form:
<% remote_form_for :login,
:url => {:controller => :usuarios, :action => :login },
:html => { :multipart => true } do |f| %>
<p class="login_field">
Login:<br />
<%= f.text_field 'login' %>
</p>
<p class="login_field">
Clave:<br />
<%= f.password_field 'clave' %>
</p>
<br />
<p align ="right">
<%= f.submit 'Ingresar' %>
</p>
<p class="forgot">
<%= link_to "Olvid&oacute su clave?", { :controller => 'usuarios', :action => 'olvido_contrasena', :login => }, :post => true %>
</p>
<br />
<p id="error_msg_login"></p>
<% end %>
Now, In my controller I have:
def olvido_contrasena
if request.post?
u= Usuario.find_by_login(params[:login][:login])
puts u.email
if u and u.enviar_nueva_clave
flash[:message] = "Una nueva clave ha sido enviada a su correo electronico."
redirect_to :action=>'login'
else
flash[:warning] = "No se pudo enviar la nueva clave."
puts "fail"
redirect_to "/admin_main"
end
end
end
However, I have two problems:
The action is called as a GET (and it should be a POST).
The param[:login][:login] is not being sent....
What can I do here?
Thank you!
I solved my problem by adding a new view with a new form after the user clicks the "forgot password" link.
EASIEST and CLEANEST solution.
Basically -
You are clicking on link, which doesn't submit the form you have created, but "Submit" button can submit it.
As you are click a link, this is sending the GET request. If you want to send post request with form data, you may use, javascript event listeners to submit form on click of link.
As form is not being submitted, you are getting login[login] as nil.
To submit form with javascript you will be doing something like this with jquery -
$(".linkClass").click(function(event){
event.preventDefault(); //This will stop get request.
$("#formId").submit();
})
In your example code, the login-value is actually empty:
<%= link_to "Olvid&oacute su clave?", { :controller => 'usuarios', :action => 'olvido_contrasena', :login => }, :post => true %>
Also - "post => true" is not how to make it into a POSTed form.
Usually you'd use button_to (instead of link_to) but as you are already inside a form (and forms don't nest), you can fake a post by passing as a query string parameter the attribute "_method" (yes, it starts with an underscroe). so your example would become:
<%= link_to "Olvid&oacute su clave?", { :controller => 'usuarios', :action => 'olvido_contrasena', :login => #usario.login, "_method" => 'post'} %>
Now the problem is that the person is not already logged in... so you can't get their "login" - and the login field above the link is not part of the link. So you'll probably need to add some funky javascript to update the link field-value when somebody types something into the field.
... but your controller action should also deal with the case when somebody has not yet typed anything in. For example, if params[:login] is blank. it should render a "forgot your password? well enter your login name here" kind of page.

Resources