No route matches [POST] "/" only in testing - ruby-on-rails

Using Simple Form For, I have created a custom auth system.
routes.rb
get '/users/sign_in' => 'sessions#new', as: :sessions_new_user
post '/users/sign_in' => 'sessions#create', as: :sessions_create_user
match '/users/sign_out' => 'sessions#destroy', as: :sessions_destroy_user, via: :delete
get '/users/process_login' => 'sessions#process_login', as: :sessions_process_login
new.html.erb
<%= simple_form_for :user do |f| %>
<%= f.input :login, placeholder: "Login", label_html: { class: 'form-control' }%>
<%= f.input :password, label_html: { class: 'form-control' } %>
<%= f.submit "Log in", class: 'btn btn-lg btn-primary btn-block' %>
<% end %>
This issue is when i run the tests to simulate a sign in, I get this error.
user visits root of application
Failure/Error: click_on 'Log in'
ActionController::RoutingError:
No route matches [POST] "/"
user_spec.rb
scenario 'user visits root of application' do
visit root_path
expect(page).to have_content("Sign in to continue")
fill_in ' Login', with: ENV['NTUSERNAME']
fill_in ' Password', with: ENV['NTPASSWORD']
click_on 'Log in'
end
This works fine in development. I cant figure it out.

Firstly, if you are learning Rails I'd recommend you start out with the simple form helpers, as you can more clearly define what you're looking for. Since you are not using RESTful routes, you'll have to define everything by hand and are really missing out on Rails's approach of convention over configuration.
However, if you really want to make Simple Form work, here's how you would do it:
<%= simple_form_for :user, url: sessions_create_user, method: :post do |f| %>
<%= f.input :login, placeholder: "Login", label_html: { class: 'form-control' }%>
<%= f.input :password, label_html: { class: 'form-control' } %>
<%= f.submit "Log in", class: 'btn btn-lg btn-primary btn-block' %>
<% end %>
Also be aware that since you are not using an ActiveRecord-backed object (just a label), you'll have to be careful to match your expected params to what Simple Form is sending in. I'm also curious as to how you have SF render out the correct action path for a user session in development without specifying it out...

because simple_form_for don't have url, it will use the current url to submit data
Not tested but I think as below:
In development, when you visit root, it will redirect to /users/sign_in, posting to /users/sign_in is acceptable
In rspec, redirecting not change the current url, it still root_path, so posting to / is invalid

Nested forms are not allowed...
I had accidentally nested a form tag with an action of "#". It all worked in development as the browser spotted it was a nested form, and it was ignoring the tag. But when I ran a rack test it failed with No route matches [POST] “/” - it also did work when I used JS/selenium test as it was being run in a real browser.
<%= simple_form_for #user do |f| %>
<form action="#" method="POST">
<%= f.input :login %>
<%= f.input :password %>
<%= f.submit "Log in" %>
</form>
<% end %>

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.

How to add routes with the monologue gem

I am using the monologue gem and trying to create an email list signup form on one of the monologue pages. Here is the code:
<%= form_for EmailList.new, url: email_lists_path, remote: true, class: 'form-horizontal' do |f| %>
<%= f.text_field :email, id: 'userid', class: 'form-control input-medium email-field', placeholder: 'email', required: "" %>
<%= f.submit "Sign In", class: 'btn btn-success' %>
<% end %>
and here is how the route is defined when i run rake routes:
email_lists POST /email_lists(.:format) email_lists#create
So it should be working but instead I get this error:
undefined local variable or method `email_lists_path' for #<#<Class:0x007fdddf519a40>:0x007fdde482bd78>
It has something to do with how the monologue engine is mounted:
mount Monologue::Engine, at: '/blog'
Any way, how do I add routes that work within the blog?

Rails - Silmple Form calls a specified action of my user controller

My problem is that when i try to call a specified method from a simple_form_for form it doesn't work.
Here is my code :
<%= simple_form_for #user, :url => {:action => :register_iban}, :html => { :method => :post } do |f| %>
<div class="col-md-8">
<%= f.input :first_name, :label => t('user-show.payment.form.first_name'), placeholder: "Prénom" %>
<%= f.input :last_name, :label => t('user-show.payment.form.last_name'), placeholder: "Nom" %>
<%= f.input :iban, :label => t('user-show.payment.form.iban'), placeholder: "IBAN" %>
<%= f.input :bic, :label => t('user-show.payment.form.bic'), placeholder: "BIC" %>
</div>
<div class="col-md-8 text-center">
<%= f.submit t('user-show.payment.title'), class: 'btn btn-danger' %>
</div>
<% end %>
So, as you can see, i try to call register_iban method from my user controller.
But when i do that, i have an error : No route matches {:action=>"register_iban", :controller=>"users", :id=>"5", :locale=>nil}
Everytime i create a new method in a controller, i have to create a route in the routes.rb file ? Here, i'd like to make this url : /users/5/register_iban (where "5" is the user id) call my method.
Sorry but i start in ruby and i'm pretty stuck :/
in your config/routes.rb try to add in the users resources
resources users do
member do
post :register_iban
end
end
No route matches {:action=>"register_iban", :controller=>"users", :id=>"5", :locale=>nil}
This error means you're trying to access a route which doesn't exist.
The routes are defined at config/routes.rb:
#config/routes.rb
resources :users do
post :register_iban
end
This will allow you to call the register_iban method in the users controller through your form.
You'll also want to make sure you're calling routes with the appropriate helpers:
<%= simple_form_for #user, url: user_register_iban(#user) %>

Sending URL params via a form_tag and select_tag

I'm using nested resources, and in order to make a new Round, you need to have the id of its Case, so my routes.rb includes the following:
resources :cases do
resources :rounds
end
So, when a user hits the 'new round' button on the homepage, it first directs them to a page where they can pick a case that the round belongs to, before redirecting to the round form.
For the pick_case view, I have the following:
<%= form_tag new_case_round_path, method: :get do |f| %>
<%= f.select_tag :case_id,
options_for_select(Case.all.collect { |c| [c.title, c.id] }),
class: "chosen-select" %><br/>
<%= f.submit_tag "Create round", class: "btn btn-primary" %>
<% end %>
However, rails forces me to name a case_id in the new_case_round_path, so it gives me this error before it loads the pick_case view:
No route matches {:action=>"new", :controller=>"rounds"} missing required keys: [:case_id]
How can I reference the route that the form needs to submit to when the required information for the route is being entered in the form?
No route matches {:action=>"new", :controller=>"rounds"} missing
required keys: [:case_id]
The error clearly says that case_id is missing. Rails expects case_id to be present which can't be provided in your situation as you are creating a new case instance.
One way to resolve your situation is to use Shallow Nesting which provides the route for new case
resources :cases do
resources :rounds, shallow :true
end
Now, when you run rake routes, you will find a route for new case as below
new_case GET /cases/new(.:format) cases#new
So that in your pick_case view, you can change the form to
<%= form_tag new_case_path, method: :get do |f| %>
<%= f.select_tag :case_id,
options_for_select(Case.all.collect { |c| [c.title, c.id] }),
class: "chosen-select" %><br/>
<%= f.submit_tag "Create round", class: "btn btn-primary" %>
<% end %>
Which creates a case instance first before redirecting to the round form
A bit of a work-around for the answer, I feel like there's probably a more elegant way. I added post 'get_case' => rounds#get_case to routes.rb
I added this to my rounds controller:
def get_case
id = params[:case_id]
if id
redirect_to new_case_round_path(case_id: id)
else
flash[:danger] = "An error occured. Please try again"
redirect_to pick_case_path
end
end
And this is my new pick_case view:
<%= form_tag get_case_path do %>
<%= select_tag :case_id,
options_for_select(map_with_id(Case, :title)),
class: "chosen-select" %><br/>
<%= submit_tag "Create round", class: "btn btn-primary" %>
<% end %>

Rails simple form routing issue

I have a form in Rails
<div class="page-header">
<h3>Create Blah</h3>
</div>
<%= simple_form_for #blah do |f| %>
<%= f.input :id %>
<%= f.input :name %>
<%= f.input :pho %>
<%= f.input :fun %>
<%= f.submit :class => 'btn btn-primary' %>
<% end %>
<br>
When I click the submit button, where does the code attempt to go? Does it call the create method for blah_controller.rb? Because currently, I get a routing error
Routing Error
uninitialized constant BlahsController
Here is the BlahController#create method:
def create
authorize! :create, :blahs
#blah = Blah.new(params[:blah])
if #blah.save
redirect_to admin_blah_path(#blah), :notice => 'New blah created!'
else
render :new
end
end
In my rake routes, I have
admin_blahs GET /admin/blahs(.:format) admin/blahs#index
POST /admin/blahs(.:format) admin/blahs#create
new_admin_blah GET /admin/blahs/new(.:format) admin/blahs#new
edit_admin_blah GET /admin/blahs/:id/edit(.:format) admin/blahs#edit
admin_blah GET /admin/blahs/:id(.:format) admin/blahs#show
PUT /admin/blahs/:id(.:format) admin/blahs#update
DELETE /admin/blahs/:id(.:format) admin/blahs#destroy
It looks like your BlahsController is a namespaced controller, living under the Admin module (i.e., its fully-qualified name is Admin::BlahsController). If so, when constructing forms you must also provide the :admin namespace, using something like the following:
<%= simple_form_for [:admin, #blah] do |f| %>
See the Rails Guide to Form Helpers, under the "Dealing with Namespaces" section.

Resources