Why is it that my <%= form_for charges_path %> returns an undefined local variable when visiting /product/:product with these routes :
get 'product/:product' => 'charges#new'
post 'product/:product' => 'charges#create'
but works when I add these?
resources :charges, :only => [:new, :create]
I'd like to clean this up
When you use the get and post methods you don't get the path helpers created, ie. there is no charges_path method unless you provide a string with the :as option.
So without charges_path method, ruby thinks it's the name of a variable and so you get the error you're getting.
Related
I have a _form for new and edit for a #Giveaway object. Within this form I have a field for a random winner.
I want to populate this field by calling the method giveaways#random_winner with <%= button_to "Randomly Pick Winner!", {:action => 'choose_winner'}, :method => :get %>, but I am getting this error No route matches {:action=>"choose_winner", :controller=>"giveaways"} when loading /giveaways/new.
Here is my controller:
def choose_winner
random_winner = SubscriberUser.where(user_id: current_user.id).pluck(:subscriber_id).sample(1)
session[:random_winner] = random_winner
redirect_to :back
end
Here are the routes that I have tried. I'm not very good at non-scaffold routes yet:
resources :giveaways do
member do
get 'choose_winner' => 'giveaways#choose_winner'
#tried get :choose_winner, as: :choose_winner
#tried get 'new/choose_winner'
#tried get 'choose_winner'
#tried get 'choose_winner', to: 'giveaways#choose_winner', as: 'choose_winner'
end
end
Question -- Why is the page not loading when I have defined the controller and action in the route? Will I have to reload the page when I do run that route... is there a better way to get at this data?
Your routes.rb is close
resources :giveaways do
member do
get :choose_winner
end
end
And then I would use a Rails route helper so you don't have to worry about setting the action/controller yourself.
<%= button_to "Randomly Pick Winner", choose_winner_giveaway_path(#giveaway), method: :get %>
In my application I have a link_to helper method:
<%= link_to "Downgrade", :controller => :subscriptions, :action => :downgrade, class: "btn btn-primary", remote: true %>
In my controller I have this code:
class SubscriptionsController < ApplicationController
respond_to :js
def downgrade
# some code
end
end
I am getting this error:
No route matches {:action=>"downgrade", :class=>"btn btn-primary", :controller=>"devise/subscriptions"}
Here is my routes.rb code:
Rails.application.routes.draw do
resources :wikis
devise_for :users
resources :users, only: [:update]
root to: 'welcome#index'
resources :charges, only: [:new, :create]
end
I know Rails is expecting a route for this but I don't know what route I would use since the method isn't a restful verb. Maybe there is another way without using the link_to which allows me to directly call a controller method from a view? Maybe I need to restructure where things are as well. Any help is appreciated.
Let me know if there is more code you would need to fully assess this situation.
Basic setup
first you need to setup your route in routes.rb
get 'downgrade' => 'subscriptions#downgrade', :as => :downgrade_subscription
This will redirect /downgrade to your subscriptions controller & downgrade action. The as option saves this route into a variable you can call from all your views.
<%= link_to "Downgrade", downgrade_subscriptions_path, class: "btn btn-primary", remote: true %>
Further configuration
You can also nest this route inside your subscription resources like so:
resources :subscriptions do
get 'downgrade' => 'subscriptions#downgrade', :as => :downgrade_subscription
end
This will create the path /subscriptions/downgrade instead of /downgrade.
The Rails Docs on routing does a great job explaining this in more detail. Definitely check it out!
or you can try this on your routes.rb
match '/downgrade_subscription', :to => 'subscriptioni#downgrade', :via => :get
In routes.rb:
resources :conversations, only: [:index, :show, :new, :create, :destroy] do
collection do
get :inbox
end
In my controller:
def inbox
<stuff>
end
In my view (using haml):
=link_to 'Inbox', inbox_conversations, :id => 'load-inbox', :class => 'message-control-highlight', :remote => true
I get the following error on page load:
undefined local variable or method `inbox_conversations' for #<#<Class:0x3d51470>:0x3d59198>
In my view, if I replace inbox_conversations with a "#", I don't get any errors on page load. I've tried appending inbox_conversation with likely classes, such as current_user and current_user.mailbox. I've also tried changing the routing from collection to member--and even taking it out of any collection/member block. What could be the problem here?
Try using inbox_conversations_path or inbox_conversations_url
=link_to 'Inbox', inbox_conversations_path, :id => 'load-inbox', :class => 'message-control-highlight', :remote => true
You need to append _path or _url to your routes, e.g.
= link_to 'Inbox', inbox_conversations_path
See the complete Rails Routing guide for all the details:
http://guides.rubyonrails.org/routing.html
I'm working through Ryan Bates' Railscast #124: Beta Invitations. I've got all the code in place, but I haven't been able to actually get things working. When I try to send an invite email, I get this message.
Routing Error
No route matches [POST] "/invitations"
If I pluralize the resource's name in Routes.rb, I get a different routing error.
Routing Error
uninitialized constant InvitationsController
What am I doing wrong?
Here's my Routes.rb file.
resources :users, :invitation
resources :sessions, :only => [:new, :create, :destroy]
match '/hunts', :to => 'hunts#index'
match '/signup/', :to => 'users#new'
match '/signin', :to => 'sessions#new'
match '/signout', :to => 'sessions#destroy'
match '/contact', :to => 'pages#contact'
match '/about', :to => 'pages#about'
match '/help', :to => 'pages#help'
root :to => "pages#home"
match ':controller(/:action(/:id(.:format)))'
end
And my Invitation Controller.
class InvitationController < ApplicationController
def new
#invitation = Invitation.new
end
def create
#invitation = Invitation.new(params[:invitation])
#invitation.sender = current_user
if #invitation.save
if logged_in?
Mailer.deliver_invitation(#invitation, signup_url(#invitation.token))
flash[:notice] = "Thank you, invitation sent."
redirect_to root_path
else
flash[:notice] = "Thank you, we will notify when we are ready."
redirect_to root_path
end
else
render :action => 'new'
end
end
end
Update: Here's the info requested.
Views/invitation/html.erb
<%= form_for #invitation do |f| %>
<p>
<%= f.label :recipient_email, "Friend's email address" %><br />
<%= f.text_field :recipient_email %>
</p>
<p><%= f.submit "Invite!" %></p>
<% end %>
rake routes is a very useful tool which you can use to see all the routes defined for your application.
You have added resources :invitation which defines the following routes
invitation_index GET /invitation(.:format) invitation#index
POST /invitation(.:format) invitation#create
new_invitation GET /invitation/new(.:format) invitation#new
edit_invitation GET /invitation/:id/edit(.:format) invitation#edit
invitation GET /invitation/:id(.:format) invitation#show
PUT /invitation/:id(.:format) invitation#update
DELETE /invitation/:id(.:format) invitation#destroy
Note that you are calling the InvitationController's actions.
So nothing is wrong with your route -> controller mapping.
You are just posting to a non-existent route. When you pluralize the route's name, you end up having a non-existent controller (InvitationsController).
Just change the URL you're posting to and you're good to go.
Try to use the plural when you call resources in your config/routes.rb:
resources :users, :invitations
This happens because you pass an instance of the Invitation model (#invitation) to this helper, it pluralize the class name to know where to submit.
Moreover, since #invitation is not yet saved in the DB (#invitation.new_record? returns true) then form_for set the form's method to "POST".
This information means the POST request to 'invitations' is processed by "invitations#create" (The create method of the InvitationsController class). It's convention over configuration, if you want to access invitations in a RESTful way and use resources in your config/routes.rb things must be named in a certain way to work out of the box (or you could simply override the "action" attribute of your form using some of the form helpers options).
BTW if you want to make things in a different manner you should read the Rails Guide to Routing and see if some option can help you to define your invitations routing rules, and have a look at the REST chapter of the Getting Started Rails Guide.
UPDATE: I missed the sentence "If I pluralize the resource's name in Routes.rb, I get a different routing error."
BTW, the problem is your controller class name is "InvitationController" while the form generated by the form_for helper submit to "/invitations".
I have a User model. If I do:
def my_action
#user = User.new
end
then
<% form_for(#user) do |f| %>
I get
undefined method `users_path' for #<ActionView::Base:0x1b4b878>
Which make sense because I haven't mapped it going map.resources :users... but I don't want to do it this way because I don't need all the resources.
How can I just define this user_path method in my routes?
Since I came here looking for a way to create helpers in routes.rb, here is the way to do it:
get '/users/:id/' =>'users#show', :as => :user
You can also customize restful routes. For example in my application only the index and show actions are appropriate for certain controllers. In my routes.rb file I have some routes like this:
map.resources :announcements, :only => [:index, :show]
You can also use :except if that's more appropriate.
You can map custom routes in your routes.rb file like this...
map.users '/users', :controller => 'user', :action => 'index'
This gives you the users_path helper you're looking for.