Rails button_to No route matches {:action=>"complete", :controller=>"dashboard", :name=>"Order"} - ruby-on-rails

Please help i have tried my best. I really need your help.
So im trying to make a mark order as complete. Now it all works up to the button to mark order as complete. I ran a migration to add.
class AddCompleteToOrder < ActiveRecord::Migration
def change
add_column :orders, :complete, :boolean, default: false
end
end
Then i added a method the order.rb of
def complete!
update(complete: true)
end
Then routes.rb
resources :orders do
post "complete", to: "orders#complete", on: :member
end
Then this is the button
= button_to "Mark as complete", { action: "complete", id: #order.id }
But i dont have a #order.id
but a order does have a #order.name so i changed it to
= button_to "Mark as complete", { action: "complete", name: #order.name }
But then i get the error:
ActionController::UrlGenerationError in Dashboard#dadmin
Showing /Users/jacksharville/Desktop/dancer/app/views/dashboard/dadmin.html.haml where line #87 raised:
No route matches {:action=>"complete", :controller=>"dashboard", :name=>"Order"}
Extracted source (around line #87):
85
86
87
= link_to "Back to Dashboard", :back, :class => 'btn-danger btn'
= button_to "Mark as complete", { action: "complete", name: #order.name }
So clearly im doing the routes.rb wrong but i cant fix it. Please help. Any help greatly appreciated.
routes.rb (full file)
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
get 'home/index'
root 'home#index'
#pages
get '/why' => 'pages#why'
get '/trak' => 'pages#trak'
get '/contact' => 'pages#contact'
get '/mydms' => 'pages#mydms'
get '/air' => 'pages#air'
get '/ocean' => 'pages#ocean'
get '/road' => 'pages#road'
get '/courier' => 'pages#courier'
get 'fulfilment' => 'pages#fulfilment'
get 'express' => 'pages#express'
resources :dashboard
get 'dadmin' => 'dashboard#dadmin'
get 'myorders' => 'dashboard#myorders'
get 'label' => 'dashboard#label'
resources "contacts", only: [:new, :create]
devise_for :users
as :user do
get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'
put 'users' => 'devise/registrations#update', :as => 'user_registration'
end
resources "orders"
get "/confirm" => "confirmations#show"
get 'dconfirmation' => 'orders#confirmation'
resources :orders do
post "complete", to: "orders#complete", on: :member
end
end
orders_controller.rb
class OrdersController < ApplicationController
before_filter :authenticate_user!
def new
#order = Order.new
end
def create
#order = current_user.orders.new(order_params)
#order.email = current_user.email
#order.name = current_user.name
#order.address_line_1 = current_user.address_line_1
#order.address_line_2 = current_user.address_line_2
#order.postcode = current_user.postcode
#order.city = current_user.city
#order.country = current_user.country
if #order.save
redirect_to dconfirmation_path
end
end
def order_params
params.require(:order).
permit(
:email,
:delivery_name,
:company_name,
:delivery_address1,
:delivery_address2,
:delivery_address3,
:delivery_city,
:delivery_postcode,
:delivery_country,
:phone,
:package_contents,
:description_content,
:restricted_items,
:terms_conditions,
:insurance,
:contents_value,
:cf_reference,
:reference_number
)
end
def show
#user = User.find(params[:id])
end
def confirmation
end
def complete!
order = Order.find(params[:id])
order.complete!
# handle response
end
end
dashboard_controller.rb
class DashboardController < ApplicationController
before_filter :authenticate_user!
def index
end
def admindashboard
(current_user.nil?) ? redirect_to(root_path) : (redirect_to(root_path) unless current_user.admin?)
end
def adminuser
(current_user.nil?) ? redirect_to(root_path) : (redirect_to(root_path) unless current_user.admin?)
end
def dadmin
(current_user.nil?) ? redirect_to(root_path) : (redirect_to(root_path) unless current_user.admin?)
# #order = Order.all
#order = Order.order("name").page(params[:page]).per(1)
end
def myorders
#order = current_user.orders.order("name").page(params[:page]).per(1)
end
def show
#user = User.find(params[:id])
end
def label
#order = current_user.orders.order("name").page(params[:page]).per(1)
end
def complete!
order = Order.find(params[:id])
order.complete!
# handle response
end
end

You can specify this additional option in the button_to tag :controller => "order", but the proper way to use button_to tag is to not create a separate hash for options. Instead use it as a button_to("Mark as complete", controller: "order", action: "complete", name: #order.name)

try this
button_to "Mark as complete", { controller: "orders", action: "complete", name: #order.name }, {method: :post}

This link can help: Routing Error - No route matches when using button_to with custom action
rake routes give me:
complete_order POST /order/:id/complete(.:format) orders#complete

You need to move the complete action from DashboardsController to OrdersController, which is where it is defined in the routes file.
Also, you can probably use:
= button_to "Mark as complete", complete_order_path(#order)
The controller action is looking for params[:order_id] so it can find the right order. I am not sure how orders are defined in your view, but you will need to pass an order object to the path.
If by any chance you defined a to_param method in Order class, which defines order's name rather than id as params, you will need to update the complete action to look for an order by name.
But my guess is that it is the default id. So passing the order object to the path should work.

Related

Fix inconsistent route names (Rails)

Routes
resources :favorites, only: [ :index, :create, :destroy ] , param: :listing_id
Rake routes
favorites GET /favorites(.:format) favorites#index
favorites POST /favorites(.:format) favorites#create
favorite DELETE /favorites/:listing_id(.:format) favorites#destroy
Notice the (s) in favorites, why is it not all favorite or favorites?
I create one favorite and destroy one favorite, so I think it should be singular in both.
I need
favorite POST /favorites/:listing_id(.:format) favorites#create
I tried this in my routes:
resources :favorites, only: [ :index, :destroy
] , param: :listing_id
post 'favorites/:listing_id' => 'favorite#create', as: :favorite
but get this error:
ArgumentError: Invalid route name, already in use: 'favorite' You may
have defined two routes with the same name using the :as option, or
you may be overriding a route already defined by a resource with the
same naming. For the latter, you can restrict the routes created with
resources as explained here:
http://guides.rubyonrails.org/routing.html#restricting-the-routes-created
How do I modify this one?
How do I keep it consistent as I need create path and destroy path consistent in my view for a number of reasons.
My controller
class FavoritesController < ApplicationController
before_action :load_listing, only: [:create, :destroy]
def index
#favorites = current_user.favorites.map{|i| i.id} || []
#listings = ListingsQuery::Search.call(:favorited_ids=> current_user.favorites.map{|i| i.id} )
respond_to do |format|
format.html {}
format.js {}
end
end
def create
if current_user.favorite!(#listing)
format.js {}
end
end
def destroy
if current_user.unfavorite!(#listing)
format.js {}
end
end
private
def load_listing
#listing_id = favorite_params[:listing_id]
#listing = Listing.find(#listing_id)
end
def favorite_params
params.permit(:listing_id)
end
end
view
<% if listing.is_favorited == true %>
<%= link_to favorite_path(:listing_id => listing.listing_id), method: :delete, remote: true do%>
<i id='i-<%= listing.listing_id %>' class=" fa fa-heart"></i>
<% end %>
<% else %>
<%= link_to favorite_path(:listing_id => listing.listing_id), method: :post, remote: true do %>
<i id='i-<%= listing.listing_id %>' class="fa fa-heart-o"></i>
<% end %>
<% end %>
create.js
(function(){
$("#i-<%= #listing_id %>").removeClass('fa-heart-o');
$("#i-<%= #listing_id %>").addClass('fa-heart');
$("#i-<%= #listing_id %>").parent().attr("data-method",'delete');
})();
Why is this...
resources :favorite do
collection do
post "for_lisiting/:listing_id", action: :create_for_listing
delete "for_listing/:listing_id", action: :delete_for_listing
end
end
preferred over this..
match 'favorite' => 'favorites#create', via: :post
match 'favorite' => 'favorites#destroy', via: :delete
It seems to me, but maybe I am wrong. that
/favorite/for_lisiting/:listing_id(.:format)
is unnecessarily long compared to
/favorite/:listing_id(.:format)
however, I am a novice, so value your reasoning.
When using rails resource helper, it creates some REST endpoints. You have listings that can be favorited, you are mixing both resources. Your resource is the Listing and favorite/unfavorite/favorites are actions on the resource.
Try something like this:
resources :listings do
member do
post :favorite, action: :create_favorite
delete :favorite, action: :delete_favorite
get :favorites
end
end
That will give you two route: /listings/:id/favorite (both for create -POST- and delete -DELETE-) and /listings/:id/favorites (GET). Both create and delete will be the same favorite_listing_path(listing) (or similar, check rake routes).
Now, on your ListingsController, define those actions:
class ListingsController < ApplicationController
def create_favorite
Listing.find(:id).favorites.create(user: current_user)
redirect_to :something, notice: 'Favorited'
end
def delete_favorite
Listing.find(id).favorites.where(user: current_user).destroy_all
redirect_to :something, notice: 'Unfavorited'
end
def favorites
#favorites = Listing.find(id).favorites
end
# of course, you could add a before_action to DRY it, I just wanted to be explicit on which is the actual resource
end

ActionController::ParameterMissing in UsersController#update

I have a small game in which after the game is over the user is linked to a view that displays a leader board of all users and their scores. To do this I have treated the link as an update action so that the users score can be updated after the game is over, however, upon clicking the link I get an error saying "param is missing or the value is empty: user". I am also wondering if this is being caused because there is no form to be filled simply a variable being updated.
Controllers:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
session[:user_id] = #user.id
redirect_to '/play'
else
render '/'
end
end
def update
#user = User.find(current_user)
if #user.update(user_params)
redirect_to '/leaderboard'
else
render '/play'
end
end
private
def user_params
params.require(:user).permit(:nick_name, :score)
end
end
class ScoresController < ApplicationController
before_action :require_user, only: [:index]
def index
#user = User.find(current_user)
#score = #user.score
#score = 0
end
def leaderboard
#users = User.all
end
end
View-link:
<div class="game-over"><%= link_to 'Game Over', "/update", :style => 'text-decoration:none; color:white;' %></div>
Routes:
Rails.application.routes.draw do
root 'users#new', as: :users
post '/' => 'users#create'
get '/logout' => 'sessions#destroy'
get '/play' => 'scores#index', as: :user
get '/update' => 'users#update'
get '/leaderboard' => 'scores#leaderboard'
user has to be present in the request params because you required it in user_params. You can change link_to to use query parameters as follows:
link_to "Refresh", {controller: 'users', action: 'update', nick_name: "#{user.nick_name}", score: "#{get_score}"}, style: '...'
Or change update route to contain those parameters in the url.
# routes.rb
get '/update/:nick_name/:score' => 'users#update'
Tip: You probably should change it to PUT and use form instead, since update action alters state in the server.
Looks like whatever you are using to pass through your params to make the request is not properly nested under a user key.

Controller method #show getting called

I have a link on my #index view:
<%= link_to 'Export Calendar (ICS)', { controller: :tickets, action: :ics_export, format: :ics }, class: "class-needed right" %>
routes.rb that pertains to this:
resources :tickets
get 'tickets/calendar' => 'tickets#ics_export'
post 'tickets' => 'tickets#index'
patch 'tickets/:id/close' => 'tickets#close', as: 'close_ticket'
post 'tickets/:id' => 'ticket_comments#create'
My TicketsController that pertains:
before_action :set_ticket, only: [:show, :edit, :destroy, :update, :close]
def show
#ticket_comment = TicketComment.new
end
def ics_export
tickets = Ticket.all
respond_to do |format|
format.html
format.ics do
cal = Icalendar::Calendar.new
tickets.each do |ticket|
event = Icalendar::Event.new
event.dtstart = ticket.start
event.description = ticket.summary
cal.add_event(event)
end
cal.publish
render :text => cal.to_ical
end
end
end
private
def set_ticket
#ticket = Ticket.find(params[:id])
end
And when I click the link, it takes me to /tickets/calendar.ics which is correct but I get the following error:
ActiveRecord::RecordNotFound in TicketsController#show
Couldn't find Ticket with 'id'=calendar
Extracted source (around line #83):
private
def set_ticket
#ticket = Ticket.find(params[:id])
end
The #ticket = Ticket.find(params[:id]) is highlighted. Which make sense that it is failing to call a ticket with an id of calendar.
Request has parameters:
{"id"=>"calendar",
"format"=>"ics"}
How do I fix this error? Why is it calling the show action?
There is a footnote in the canonical Rails Routing from the Outside In to the effect:
Rails routes are matched in the order they are specified, so if you have a resources :photos above a get 'photos/poll' the show action's route for the resources line will be matched before the get line. To fix this, move the get line above the resources line so that it is matched first.
As commented, the fix is to specify get 'tickets/calendar' => ... ahead of resources :tickets. If the order of routes is in question, you can run rake routes, which, to the best of my knowledge, should render your routes in the order they are checked.

Adding a route for a controller action

I am implementing a like system in my rails app using David Celis gem called Recommendable. I've gotten everything to work in the console but I can't get the right routes and I'm getting the "No route matches [GET] "/categories/1/posts/1/like" error.
I have the following in my models:
class Category < ActiveRecord::Base
has_many :posts, :dependent => :destroy
extend FriendlyId
friendly_id :name, use: :slugged
end
class Post < ActiveRecord::Base
belongs_to :category
end
In my Post Controller I have:
class PostsController < ApplicationController
before_filter :authenticate_user!
before_filter :get_category
def like
#post = Post.find(params[:id])
respond_to do |format|
if current_user.like #post
else
flash[:error] = "Something went wrong! Please try again."
redirect_to show_post_path(#category, #post)
end
end
end
end
In my routes I have:
resources :categories do
resources :posts do
put :like, :on => :member
end
end
match 'categories/:category_id/posts/:id', :to => 'posts#show', :as => 'show_post'
Can someone please point at my errors? I can get the PUT to work but I dont know where the GET error is coming from as I am trying to redirect back to the post if an error occurs when the user like's a certain post. Thank you in advance.
EDIT:
In my view I have:
- title "#{#post.class}"
%p#notice= notice
%p
%b Title:
= #post.title
%p
%b Description:
= #post.description
%p
%b Likes:
= #post.liked_by.count
= link_to 'Edit', edit_category_post_path(#post)
\|
= link_to 'Back', category_posts_path
\|
= link_to 'Like', like_category_post_path(#post)
Replace:
= link_to 'Like', like_category_post_path(#post)
with:
= link_to 'Like', like_category_post_path(#category, #post), method: :put
Or, as I like it:
= link_to 'Like', [#category, #post], method: :put
I think your like has to be:
def like
#post = Post.find(params[:id])
respond_to do |format|
format.html do
if current_user.like #post
flash[:notice] = "It's ok, you liked it!"
redirect_to :back
else
flash[:error] = "Something went wrong! Please try again."
redirect_to show_post_path(#category, #post)
end
end
end
end
Your route expects a PUT request, while you're issuing a GET request.
You'll need to either access your route via a button_to with :method => :put so that your app is issuing PUT requests (the correct solution), or change your route to use GET requests (the wrong way to make requests which modify state):
get :like, :on => :member

simple_navigation gem and rails 3.0.9

routes.rb
PASFramework::Application.routes.draw do |map|
resources :users do
collection do
get :index
get :edit
post :update
get :show
end
end
root :to => 'users#index'
end
==================================================================
navigation.rb
# Configures your navigation
SimpleNavigation::Configuration.run do |navigation|
navigation.items do |primary|
primary.item :users, 'Welcome User', root_path do |users|
users.item :edit, 'Edit Profile', edit_users_path
end
end
end
==================================================================
User_controller
class UsersController < ApplicationController
def index
user = current_facebook_user.fetch
#u = User.find_by_facebook_id(user.id)
if #u.nil?
#u = User.find_or_create_by_facebook_id(user.id)
#u.update_attributes( :first_name => current_facebook_user.first_name,
:last_name => current_facebook_user.last_name )
gflash :notice => "Welcome, #{current_facebook_user.name} "
else
gflash :notice => "Welcome back, #{current_facebook_user.first_name} #{current_facebook_user.last_name}"
end
return
rescue Exception
logger.info "Problem"
logger.error($!)
top_redirect_to auth_url
end
def show
end
def edit
user = current_facebook_user.fetch
#user = User.find_all_by_facebook_id(user.id)
end
def update
user = current_facebook_user.fetch
#user = User.find_all_by_facebook_id(user.id)
if #user.update_attributes(:first_name => params[:first_name],
:last_name => params[:last_name])
redirect_to user_path, :notice => t('users.update_success')
else
render :action => 'edit'
end
end
end
==========================================================================
The menu is created really well and thanks for this awesome plugin. But when I click edit user I get an error:
ActionView::Template::Error (No route matches {:action=>"show", :controller=>"users"}):
Can someone help me with that please? Can someone explain me why in routes.rb resources user only is not working instead of the collection thing?
Thanks in advance.
It's because of how you are defining the show route.
resources :users do
collection do
get :index
get :edit
post :update
get :show #this is your problem
end
end
Trying renaming this to a different action. The default show route is getting overridden.
resources :users do
collection do
get :index
get :edit
post :update
get :second_show # of course rename this to a better name
end
end

Resources