Rails form_for wrong method - ruby-on-rails

I've got a weird issue with one of my forms. The form only changes one variable of the object, called admin_comment. It ends up in the show method of the controller, in the terminal:
Processing by EnrolmentsController#show as
Here is the form_for
<%= form_for enrolment, :url => enrolments_admin_comment_path(enrolment), method: :get, remote: true do |f| %>
And here is the rake routes
enrolments_admin_comment GET /enrolments/admin_comment(.:format) enrolments#admin_comment
And the routes.rb part
get "enrolments/admin_comment"
resources :courses do
resources :enrolments
end
When I delete the method: :get part from the form_for, it ends up at the update method.
Everything else with the enrolments controller/model works fine. Does somebody know what's going on here? Thanks!
Update
After nearly getting insane I've got it working like this, but only with :get as method.
routes.rb
get "/enrolments/:id/admin_comment" => "enrolments#admin_comment", as: "enrolments_admin_comment"
form_for
<%= form_for enrolment, :url => enrolments_admin_comment_path(enrolment), method: :get, remote: true do |f| %>
If I change the method to :post, I get the following error:
ActionController::RoutingError (No route matches [POST] "/enrolments/28/admin_comment"):
Two questions came up:
1. What do I have to change to make it work with :post?
2. As far as I understand, if I just would just state the controller and the verb (:get / :post / ...), rails would know which method it has to use as the verbs are mapped to the methods. But when I state the whole path (controller and method), shouldn't rails know everything it needs without the verb? The form params are being sent anyway.
Update2
Ok, I've changed
get "/enrolments/:id/admin_comment" => "enrolments#admin_comment", as: "enrolments_admin_comment"
to
post "/enrolments/:id/admin_comment" => "enrolments#admin_comment", as: "enrolments_admin_comment"
Now everything works fine.

You'll be best looking at Rails' Resource Routing
HTTP Verbs
Each resources :controller you create in your routes.rb file creates a series of routes, which connect with relative HTTP Verbs:
The HTTP verbs part of the routing system is the most important, as it governs which controller action is loaded. You can use the same path helper with different HTTP Verbs to route to completely different controller actions
If you want to create a new path, you'd need to set the HTTP verb to method: :post, like this:
<%= form_for enrolment, :url => enrolments_admin_comment_path(enrolment), method: :post, remote: true do |f| %>
Routes
Perhaps you'd be better with this routing structure:
resources :courses do
resources :enrolments do
get :admin_comment, shallow: :true
end
end

Related

No route matches [POST] "/articles/new" - Why?

I made the following introduction:
http://guides.rubyonrails.org/getting_started.html
And after that, I wanted to create a new field (like title) and got the error notification:
Here is my code:
routes.rb
Rails.application.routes.draw do
get 'welcome/index'
resources :articles do
resources :comments
resources :description
root 'welcome#index'
# For details on the DSL available within this file, see guides.rubyonrails.org/routing.html
end
end
I know that this question has been asked a lot but their solutions didn't helped me.
What should I do?
Regards
The problem is in your new.html.erb form, you are missing url: articles_path, if you don't specify it, the form will be sent to the same action (i.e. new). So, since submitting the form uses POST (by default) method, you get:
No route matches [POST] “/articles/new”
You need to change your form_for and specify the url, like this:
<%= form_for :article, url: articles_path do |f| %>
From the same link your provided:
There's one problem with this form though. If you inspect the HTML
that is generated, by viewing the source of the page, you will see
that the action attribute for the form is pointing at /articles/new1.
This is a problem because this route goes to the very page that you're
on right at the moment, and that route should only be used to display
the form for a new article.
1 My emphasis.
By default rails new resource route has a GET HTTP verb, not POST. Unless you specified otherwise.
Seems like you are using new_article_path or articles/new in the form
<%= form_for :article, url: new_articles_path do |f| %>
Change it to
<%= form_for :article, url: articles_path do |f| %>

Rails run :get route within /new and /edit _form

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 %>

form_for routing error with scope :module nested routes

This may not make sense but I'm trying to learn harder stuff and progress, it seems like I'm missing the ID for address but can't seem to find a solution.
I included the url in form_for because when I remove it, the app breaks. But seems like I predefined the url than edit breaks.
<%= form_for([#address.user, #address], :url => user_addresses_path) do |f| %>
Error Readout:
No route matches [PATCH] "/users/1/addresses"
When I remove :url=>
undefined method `user_client_address_path'
routes.rb
Rails.application.routes.draw do
# Security Devise Setup
devise_for :admins
devise_for :users
# Main Pages
root 'website/page#index'
# Client Sections
resources :users do
scope module: "client" do
root :to => 'dashboard#index'
resources :addresses
end
end
namespace :admin do
root :to => 'panel#index'
end
end
rake routes partial output (let me know if more is needed)
user_addresses GET /users/:user_id/addresses(.:format) client/addresses#index
POST /users/:user_id/addresses(.:format) client/addresses#create
new_user_address GET /users/:user_id/addresses/new(.:format) client/addresses#new
edit_user_address GET /users/:user_id/addresses/:id/edit(.:format) client/addresses#edit
user_address GET /users/:user_id/addresses/:id(.:format) client/addresses#show
PATCH /users/:user_id/addresses/:id(.:format) client/addresses#update
PUT /users/:user_id/addresses/:id(.:format) client/addresses#update
DELETE /users/:user_id/addresses/:id(.:format) client/addresses#destroy
If you are using AJAX to submit the form, try adding method: 'POST' to it.
If you are submitting the form normally, try adding method: :post to the form_for hash.
It should end up something like:
<%= form_for([#address.user, #address], url: user_addresses_path, method: :post) do |f| %>

Hide search params in Rails4 url (param not found: ---)

I wanted to hide params in rails url while searching.
so previously my link is like this,
http://localhost:3000/photos?utf8=%E2%9C%93&room_ids[]=534b6cc56d696e0f000d0000&commit=Refine+Search
i wanted to achieve like below link,
http://localhost:3000/photos
So i have changed the form_tag method to Post from Get.
<%= form_tag photos_path, :method => 'post' do %>
...
<% end %>
In route file mentioned as,
match '/photos/index', via: :post
After doing it giving error as,
ActionController::ParameterMissing in PhotosController#create
param not found: photo
How to achieve it!!!
If you want custom action to be performed on the params, better write a method in controller
#photos controller
def customize
#custom action on params
end
add the method 'customize' in the routes and specify the route in the form.
Also, if your form doesn't have any fields from Photo model, you can use ActiveModel::Model for projecting an object. Checkout http://blog.remarkablelabs.com/2012/12/activemodel-model-rails-4-countdown-to-2013 and http://prasadsurase.github.io/blog/2014/02/19/using-activemodel-model-for-devise-based-invitations/ describing about how to use ActiveModel::Model.
<%= form_tag photos_index_path, :method => 'post' do %>
or
match '/photos/index', via: :post, as: :photos
In termial, type rake routes
match '/photos/index' => photos_index /photos/index photos#index
match '/photos/index', via: :post, as: :photos => photos /photos/index photos#index
According to Rails Guide
Never use the legacy wild controller route. This route will make all actions in every controller accessible via GET requests.
# very bad
match ':controller(/:action(/:id(.:format)))'
Don't use match to define any routes. It's removed from Rails 4.

Rails routing error with nested resources

In my application, I have a RecipesController and a CommentsController. All comments belong to a recipe, and can be voted up. Here's a snippet from my routes.rb:
resources :recipes do
member do
put 'vote_up'
post 'comment'
end
resources :comments do
member do
put 'vote_up'
end
end
end
If I run rake routes, I find the following route in the output:
vote_up_recipe_comment PUT /recipes/:recipe_id/comments/:id/vote_up(.:format) {:action=>"vote_up", :controller=>"comments"}
The CommentsController has a method called vote_up.
Also, linking to the route works (from my view)
<%= link_to 'Vote up', vote_up_recipe_comment_path(#recipe, comment), :method => 'put' %> <br />
However, clicking on that link gives me the following error:
Routing Error
No route matches "/recipes/7/comments/4/vote_up"
What am I missing? I'm not sure how to debug this, because as far as I can see the route should match.
I think that you get this error message because the request is made via HTTP GET method, not PUT.
In order to create links that use POST/PUT/DELETE method, your application should correctly load a Javascript Rails adapter.
Check that your app has jQuery (http://github.com/rails/jquery-ujs) or Prototype JS adapter and that your layout correctly loads it.
try the following tweak: send the put method as a symbol
<%= link_to 'Vote up', vote_up_recipe_comment_path(#recipe, comment), :method => :put %>

Resources