form_for issue GET request instead of patch - ruby-on-rails

I have edit form for company as bellow in edit.html.erb
<%= form_for([:dashboard , #company] ) do |f| %>
<%= f.text_field :name , :class => "form-control" %>
<%= f.submit "Save" , :class => "btn btn-primary"%>
<% end %>
and my companies_controller.rb
def edit
#company = Company.find(params[:id])
end
def update
# Update code
end
and my routes.rb
namespace :dashboard do
resources :companies , only: [ :edit , :update ]
end
The problem is when submit the form get the bellow error
No route matches [GET] "/dashboard/companies/3"

form_for accepts a post method by default.Here the edit action is get method,so your form_for should look like this
<%= form_for([:dashboard , #company],:html => {:method => :get }) do |f| %>
<%= f.text_field :name , :class => "form-control" %>
<%= f.submit "Save" , :class => "btn btn-primary"%>
<% end %>
OR
You can do like this too
<%= form_for([:dashboard , #company] :url =>edit_dashboard_company_path(#company)) do |f| %>
<%= f.text_field :name , :class => "form-control" %>
<%= f.submit "Save" , :class => "btn btn-primary"%>
<% end %>

Related

Routing error - No route matches [POST]

Have read many questions / answers on this issue, yet do not seem to find my fix.
Here is the issue: I am following the getting started for Rails to create a simple register of annotations. My forms work - can add new & update annotations. Yet when I add links to the index, I get a routing error:
This: <%= button_to "Details", annotation_path(annotation), :class => "btn btn-primary btn-xs"%> results in: No route matches [POST] "/annotations/5"
This: <%= button_to "Add Annotation", new_annotation_path, :class => "btn btn-primary btn-xs"%> to No route matches [POST] "/annotations/new"
Thanks for help
Routes.db:
Rails.application.routes.draw do
root 'dashboard#index'
devise_for :users
resources :users, :annotations
Controller:
class AnnotationsController < ApplicationController
def index
#annotations = Annotation.all
end
def show
#annotation = Annotation.find(params[:id])
end
def new
#annotation = Annotation.new
end
def edit
#annotation = Annotation.find(params[:id])
end
def create
#annotation = Annotation.new(annotation_params)
#annotation.save
redirect_to #annotation
end
def update
#annotation = Annotation.find(params[:id])
if #annotation.update(annotation_params)
redirect_to #annotation
else
render 'edit'
end
end
def destroy
#annotation = Annotation.find(params[:id])
#annotation.destroy
redirect_to annotations_path
end
private
def annotation_params
params.require(:annotation).permit(:name, :description)
end
end
And the form (= partial)
<%= simple_form_for #annotation, url: annotations_path, html: { class: 'form-horizontal' },
wrapper: :horizontal_form,
wrapper_mappings: {
check_boxes: :horizontal_radio_and_checkboxes,
radio_buttons: :horizontal_radio_and_checkboxes,
file: :horizontal_file_input,
boolean: :horizontal_boolean
} do |f| %>
<%= f.error_notification %>
<%= f.input :name, placeholder: 'Enter name' %>
<%= f.input :description, placeholder: 'Description' %>
<%= f.input :file, as: :file %>
<%= f.input :active, as: :boolean %>
<%= f.input :choice, as: :check_boxes,
collection: [
'Option one ...',
'Option two ...'] %>
<%= f.input :documenttype, as: :radio_buttons,
collection: ['Type1', 'Type2'] %>
<%= f.button :submit %>
<% end %>
Note on the form: to no avail, I tried using <%= simple_form_for :annotation, url: annotations_path,
The issue is because the button_to helper actually generates a form at code level and thus is POSTing said form, however the route for a new resource must be a GET.
The button_to tag really should not be used for GET requests so I would use a link_to with CSS classes instead (you already have the necessary classes), but you can do it using the below if you wanted:
<%= button_to "Details", annotation_path(annotation), class: "btn btn-primary btn-xs", method: :get%>
The better approach however is:
<%= link_to "Details", annotation_path(annotation), class: "btn btn-primary btn-xs" %>
Read doc here button_to
The method is by default :post change it using :method param
<%= button_to "Details", annotation_path(annotation), :class => "btn btn-primary btn-xs", method: :get%>
<%= button_to "Add Annotation", new_annotation_path, :class => "btn btn-primary btn-xs", method: :get%>

explain what's wrong with delete and destroy?

Not able to delete the data stored in the database pls help?
this is my sages_controller.rb
def delete
#sage = Sage.find(params[:id])
end
def destroy
Sage.find(params[:id]).destroy
redirect_to '/thanksss'
end
this is my delete.html.erb
<%= form_for #sage do |f| %>
<%= f.label :Name %>
<%= f.text_field :Name %>
<br/>
<%= f.label :Email %>
<%= f.text_field :Email %>
<br/>
<%= f.label :Address %>
<%= f.text_field :Address %>
<br/>
<%= f.label :Number %>
<%= f.text_field :Number %>
<br/>
<%= f.submit 'Delete' %>
<% end %>
this is my routes.rb
get 'sages/delete/:id'=> 'sages#delete'
delete 'sages/delete/:id'=> 'sages#destroy'
You don't have to create form for this. button_to should work
<%= button_to "delete", #sage, :method => :delete, :class => :destroy %>
this will internally generate a form with DELETE method, opposed to default GET method like below,
<%= form_for #sage, :method => :delete do %>
You can do something like this,
Change your button to link,
<%= link_to "delete", #sage, :method=>:delete %>
And change your routes file to,
resources :sages,only: [:new,:create,:edit, :update, :delete]
get 'sages/delete/:id'=> 'sages#delete'
Change your delete method like,
def delete
#sage = Sage.find(params[:id])
destroy
end

Couldn't find User without an ID when calling method

I got a modal, with a form inside it. However I get the classic error when I try to submit:
Couldn't find User without an ID
My form looks like this:
<%= form_for add_email_users_path, url: { action: 'add_email', controller: 'users' } do |f| %>
<%= f.email_field :email, placeholder: 'Your email address', class: 'input-lg form-control' %>
<%= f.button 'Continue', class: 'btn btn-success', 'data-disable-with' => "Saving <i class='fa fa-spinner fa-spin'></i>".html_safe %>
<% end %>
routes:
resources :users, except: [:destroy] do
post 'add_email', on: :collection
end
User_controller:
def add_email
#user = User.find(params[:id])
if #user.update_attributes(setup_params)
redirect_to campaigns_path, notice: 'Thank you for adding your email!'
else
redirect_to :back, alert: 'Unable to save your email'
end
end
Try this:
<%= form_for add_email_users_path(#user) do |f| %>
<%= f.email_field :email, placeholder: 'Your email address', class: 'input-lg form-control' %>
<%= f.button 'Continue', class: 'btn btn-success', 'data-disable-with' => "Saving <i class='fa fa-spinner fa-spin'></i>".html_safe %>
<% end %>
and your route:
resources :users, except: [:destroy] do
post 'add_email', on: :member
end
You have the wrong path method in your form_for, it should be:
add_email_user_path(#user)
And your route should be for member not collection:
post 'add_email', on: :member
Here is what your stuff should look like:
form.html.erb
<%= form_for add_email_user_path(#user) do |f| %>
<%= f.email_field :email, placeholder: 'Your email address', class: 'input-lg form-control' %>
<%= f.button 'Continue', class: 'btn btn-success', 'data-disable-with' => "Saving <i class='fa fa-spinner fa-spin'></i>".html_safe %>
<% end %>
routes.rb
resources :users, except: [:destroy] do
post :add_email, on: :member
end
Take special note of the change to the form_for call.
It can't be a collection method as it is looking for specific id define it as a member method
resources :users, except: [:destroy] do
member do
post :add_email
end
end
In form
<%= form_for add_email_user_path(#user), method: :post do |f| %>
You can refer to this docs to understand member and collection methods

Passing model id through rails route in form

I'm calling a custom action with simple_form. I'm having trouble passing the :id parameter to the action.
routes
post '/posts/:id/admin_vote' => 'posts#admin_vote', as: 'admin_vote'
form
<%= simple_form_for :post, url: admin_vote_path(:post_id), :html => {:class => 'form-inline admin-vote-form'} do |f| %>
<%= f.select :vote, 1..20 %>
<%= f.submit 'Vote', :class => 'btn btn-primary btn-xs' %>
<% end %>
partial render
<%= render 'layouts/admin_vote', :locals => { :post => post, :post_id => post.id } %>
For some reason the action receives params[:id] = 'post_id' instead of the actual id.
You're providing :post_id symbol to the admin_vote_path, so it uses that. Change it to:
admin_vote_path(params[:post_id])
or a different parameter depending on the context of your form.
it seems to me your form should be
<%= simple_form_for post, url: admin_vote_path, :html => {:class => 'form-inline admin-vote-form'} do |f| %>
<%= f.select :vote, 1..20 %>
<%= f.submit 'Vote', :class => 'btn btn-primary btn-xs' %>
<% end %>
you should build form based on variable post

Ruby on rails form_tag - sending model parameters to controller

Controller: #micropost = Micropost.new(params[:micropost])
But this form_tag is sending me params[:content] instead of params[:micropost][:content]
<%= form_tag( {:controller => :microposts, :action => :create}, :remote => true) do %>
<%= text_area_tag :content, "", :size=> "20x2" %>
...
...
...
<%= submit_tag "submit" %>
<% end %>
server:
Processing by MicropostsController#create as JS
Parameters: {"utf8"=>"✓", "content"=>"sdfsdf", "commit"=>"submit"}
You have to do either of the following
<%= text_area_tag "micropost[content]", "", :size=> "20x2" %>
OR
<%= form_for :micropost, :url=>{ :controller => :microposts, :action => :create}, :remote => true do |f| %>
<%= f.text_area :content, "", :size=> "20x2" %>
<% end %>
You have to avoid mixing form_for and input_tag.
When you declare a form_for #an_object do |form|, the best practice is to use form.text_area :content when :content is an attribute of your #an_object.
In this case, you can also write: text_area_tag "an_object[content]", but it's a little more dirty.

Resources