Reputation: 1
In my Rails 4 application I create pages through a PagesController to form a menu. The menu has links to redirect_to index action of the appropriate controller. Columns for that Page model are :id, :title, :access_level, :html (actually refers to the controller), :icon
Example data is: 5, Employees, 3, employees, users
NOTE: Irrelevant parts of code such as "resources :employees" are not visible!
Routes file:
resources :pages
resources :access
PagesController:
def show
@pages = Page.find(params[:id])
redirect_to controller: "#{@page.html}", action: "index"
end
Block to generate links
<% @pages = Page.all %>
<% @pages.each do |page| %>
<li>
<%= link_to({ controller: "pages", action: "show", id: "#{page.id}" }) do %><i class="fa fa-<%= page.icon %> fa-fw"></i> <%= page.title %>
<% end %>
</li>
<% end %>
HTML Generated link_to based on the example:
<a href="/pages/5"><i class="fa fa-users fa-fw"></i> Employees</a>
Everything works fine except when I try to implement a basic login system but get the following error:
ActionController::UrlGenerationError in Access#index
Showing C:/Users/Samsung/Documents/rails/AjansTakip/app/views/access/index.html.erb where line #9 raised:
No route matches {:action=>"attempt_login", :controller=>"access"}
Index.html.erb Line 9 of Access View
<%= form_for :access, url: {action: "attempt_login"} do |f| %>
AccessController (:id_number is short for identification_number and has no relation to :id)
def attempt_login
if params[:id_number].present? && params[:password].present?
found_user = Employee.where(id_number: params[:id_number]).first
if found_user
authorized_user = found_user.authenticate(params[:password])
end
end
if authorized_user
redirect_to controller: 'pages', action: 'index'
else
redirect_to action: 'login'
end
end
I am following Lynda Rails 4 Essential Training and I am unable to pass the first part of the implementation of the basic login system therefore please do not comment on any part of coding other than routing since I am trying to learn it on my own.
As far as solutions I tried this one which works to pass the error to bump into another one
get 'access/attempt_login', to: 'access#attempt_login'
but I am pretty sure there is a better way of handling these kind of situations. I get another error when I submit the form via post on index.html.erb:
No route matches [POST] "/access/attempt_login"
I think the problem arises because of the default routing which is :controller(/:id(/:action)) and that the controller expects an :id before the :action. I see no point in routing "get" for all kind of actions that do not require an :id.
Another solution that I used was to change the default routing to ":controller(/:action(/:id))" but this causes even more problems than it solves (we might even say it does not solve anything at all). Even the links in the menu break because link_to :action "show" does not get parsed as href="pages/show/5". I also tried generating links as link_to({ controller: "pages", action: "show", id: "show/#{page.id}" }) but this is nowhere as practical and dynamic as I would want to be.
Please point me in the right direction. I am also willing to change how Paging works with the PagesController, I could not think of a better way of storing pages in a database and redirecting them all in one place.
Thanks
Upvotes: 0
Views: 728
Reputation: 13621
Yeah don't use the default controller stuff, that's old school. Instead, give this a try:
Delete the get line:
get 'access#attempt_login', to: 'access#attempt_login'
Now, since you want it on a collection of the resource, try this:
resources :access do
collection do
get :attempt_login
end
end
Then in your form:
<%= form_tag attempt_login_access_path, method: :get do |f| %>
I use form_tag when it comes to urls that aren't for create or update actions. Form_for is good when you have a model present. The method get is also important, as forms default to post. You may need to double check that route path:
bundle exec rake routes | grep attempt
And ensure the method is right.
Upvotes: 3