Routing error - No route matches [POST] - ruby-on-rails

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

Related

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

form_for issue GET request instead of patch

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

No route matches [POST] "/organizations/new"

In my rails app I got quite a few resources and have created a few forms already - but for some reason I don't seem to get one specific form for a new object to work. I am not sure if it is because I am using a three-way has_many :through relationship or because I am just overlooking something else
Here's how my routes looks like
resources :users, shallow: true do
resources :organizations, :notifications
end
resources :organizations, shallow: true do
resources :plans, :users, :notifications
end
My organizations_controller looks like this:
def index
#user = current_user
#organizations = #user.organizations.to_a
end
def show
#user = current_user
#organization = Organization.find(params[:id])
end
def new
#organization = Organization.new
end
def create
#user = current_user
#organization = Organization.new(organization_params)
#organization.save
redirect_to #organization
end
On my organizations index page I link to this:
<%= button_to 'New Organization', new_organization_path, :class => 'btn btn-primary' %>
which should lead to my new.html.erb:
<%= form_for (#organization) do |f| %>
<%= render 'layouts/messages' %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
</div>
<div class="form-group">
<%= f.label :website %>
<%= f.text_area :website, class: 'form-control' %>
</div>
<%= f.button :class => 'btn btn-primary' %>
<% end %>
Every time I click on "new Organization" I get following error:
No route matches [POST] "/organizations/new"
Which is correct - I do not have a new_organizations_path that accepts POST requests. I know I can manually change the method of the form to GET but shouldn't it work the way I did it? I have another form that follows the same principle just for a different resource and it works perfectly.
Thanks for your help in advance!
button_to would always send a POST request unless something else is specified.
On the other form, you must be using link_to and not button_to which is why its working there.
You can change the button_to in two ways, pick the one that suits you:
Option 1: Use link_to
<%= link_to 'New Organization', new_organization_path, :class => 'btn btn-primary' %>
Option 2: Use button_to with method: :get
<%= button_to 'New Organization', new_organization_path, method: :get, :class => 'btn btn-primary' %>

Searching in Rails

I have two models: Inbox and Equipments. They have has_many relation :through => :inbox_equipments
In Inbox view I have the next code
<%= form_for #inbox, :html => { :multipart => true } do |f| %>
<%= f.text_area :number, placeholder: "Enter inbox number" %>
<% Equipment.all.each do |equipment| %>
<%= check_box_tag :equipment_ids, equipment.id, #inbox.equipments.include?(equipment), :name => 'inbox[equipment_ids][]' %>
<%= equipment.name %>
<% end %>
<%= f.submit "Submit", class: "btn btn-large btn-primary" %>
<% end %>
I need text area for find (or filter) desired value of equipment in check_box_tag
Like this:
<%= form_tag equipment_index_path, :method => 'get', :id => "equipments_search" do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Find", :name => nil, class: "btn btn-small btn-primary" %>
Help, please.
Although your description was not the best, I think you're looking for ajax
I would do this:
Call From Ajax
Ajax will allow you to pull the other form from your Rails app as a partial, appending it as required. This will give you the ability to treat the form as an asynchronous request, removing any issue from the form itself
Here's what I'd do:
#app/assets/javascripts/application.js
$("input[type=checkbox]").on("change", function() {
$.ajax({
url: "controller/search",
data: $("input[name=inbox[equipment_ids]").serialize(),
error: function(data) {
alert(data)
}
});
});
#config/routes.rb
match 'search(/:search)', :to => 'controller#search', :as => :search, via: [:get, :post]
#app/controllers/your_controller.rb
def search
#results = Model.where(:id => params[:equipment_ids])
respond_to do |format|
format.js
end
end
#app/views/your_controller/search.js.erb
$("form").append(data)
This won't work out of the box, but it will give you some ideas as to what you can do

Rails mailboxer gem cannot send message

I am using Mailboxer gem for the messaging function, but as I am very new I am not very sure how to use it. Basically I created the following message controller:
class MessagesController < ApplicationController
before_action :set_message, only: [:new, :create]
def new
#message = Message.new
end
def create
current_user.send_message(#recipient, message_params(:body, :subject))
redirect_to conversations_path
end
private
def set_message
#recipient = User.find(params[:recipient_id])
end
def message_params
params.require(:message).permit(:body, :subject)
end
end
Then my view:
<h1>New Message</h1>
<%= simple_form_for(#message, html: {class: "form-horizontal"}) do |f| %>
<%= f.error_notification %>
<%= f.input :subject %>
<%= f.input :body, as: :text, input_html: { rows: "3"} %>
<div class="form-actions">
<%= f.button :submit, class: "btn btn-primary" %>
</div>
<% end %>
But I can't send message...
(BTW I can send message is the console, and also replace part of the message controller with "current_user.send_message(#recipient, "test", "test")", but definitely not what I want)
Use form_tag instead of form_for
Instead of using form_for, try using form_tag, as this has worked for me:
<%= form_tag("/messages/send_message", method: "post", url: send_message_path) do %>
<%= hidden_field_tag :user_id, "#{#user.id}" %>
<%= text_field_tag :subject, nil, :class => 'form-control', :placeholder => "Subject" %>
<%= text_area_tag :message, nil, :class => 'form-control', :placeholder => "Message" %>
<%= submit_tag "Submit", :class => "btn btn-primary" %>
<% end %>
This would have an action you messages controller like this:
def send_message
#user = User.find(params[:user_id])
#message = params[:message]
#subject = params[:subject]
current_user.send_message(#user, "#{#message}", "#{#subject}")
redirect_to root_path
end
And something like this in you routes file:
post '/messages/send_message', :to => "messages#send_message", :as => "send_message"
Really hope this helps!

Resources