Update attributes rails - No route matches [POST] - ruby-on-rails

I'm trying to basically update my integration object attribute "filters". I have a integrations controller and what seems the proper actions to do so. But when I try to save after filling out the text-field I get this error No route matches [POST], I understand what it's saying but isn't update a post? Here is my code for clarity.
Controller
def update
#integrations = current_account.integrations.find(params[:id])
attrs = params.require(:integration).permit(:filters)
if #integrations.update_attributes(attrs)
redirect_to account_integration_path
else
render :filters
end
end
def filters
#integrations = current_account.integrations.find(params[:id])
end
View
<%= form_for #integrations, url: filters_account_integration_path do |f| %>
<%= f.text_field :filters, class: "tag-autocomplete" %>
<%= link_to "Save", account_integration_path, method: :post, class: [ "button", "button--modal" ] %>
<% end %>
Routes
resources :integrations, only: [ :index, :destroy, :update ] do
get "filters", on: :member
end
Hopefully that is enough info let me know if you need more? My basic question is why is this not updating the integration object? Isn't update a post?

resources generates seven routes by default. You're using it to generate only three of those. Those three routes will look like this:
GET /integrations
DELETE /integrations/:id
PATCH /integrations/:id/edit
Your form, on the other hand, is trying to use this route:
POST /integrations/:id
which doesn't match any of the generated routes.
Instead, try using the default form helpers:
<%= form_for #integrations, url: url_for(:controller => :integrations, :action => :update, :id => #integrations.id) do |f| %>
<%= f.text_field :filters, class: "tag-autocomplete" %>
<%= f.submit "Save" %>
<% end %>
That's assuming that #integrations is a single Integration resource. If it isn't, you have bigger problems than just this.

Related

creating a form to route a method inside controller

I am trying to create a form that redirects to a method called accept_item on the form controller. My issue is that it's not going through the accept_item method when I submit the form.
form_controller.rb
def accept
#form = Form.find(params['id'])
end
def accept_item
redirect_to inventories_path
end
accept.html.erb
<%= form_tag accept_item_forms_url do %>
<% #form.items.each do |i| %>
<%= label_tag 'Item Name' %>
<p><%= i.name %></p>
<%= label_tag 'Quantity' %>
<p><%= text_field_tag 'quantity', i.quantity %></p>
<% end %>
<%= submit_tag 'Accept', class: 'btn btn-default btn-about pull-left', data: {confirm: 'Are you sure you want to accept?'} %>
<% end %>
routes.rb
resources :forms do
collection do
get :accept_item, :as => :accept_item
end
end
Error Message
No route matches [POST] "/forms/accept_item"
The form_tag helper uses the HTTP POST method by default. You defined your routes with get:
get :accept_item, :as => :accept_item
You should use post instead:
post :accept_item, :as => :accept_item
Also I don't think you need the as: :accept_item part, unless you're going to use accept_item_url instead of accept_item_forms_url.
just remove :as => :accept_item, and change method to post
post :accept_item
You will get /foo when using :as => 'foo'.

Sending URL params via a form_tag and select_tag

I'm using nested resources, and in order to make a new Round, you need to have the id of its Case, so my routes.rb includes the following:
resources :cases do
resources :rounds
end
So, when a user hits the 'new round' button on the homepage, it first directs them to a page where they can pick a case that the round belongs to, before redirecting to the round form.
For the pick_case view, I have the following:
<%= form_tag new_case_round_path, method: :get do |f| %>
<%= f.select_tag :case_id,
options_for_select(Case.all.collect { |c| [c.title, c.id] }),
class: "chosen-select" %><br/>
<%= f.submit_tag "Create round", class: "btn btn-primary" %>
<% end %>
However, rails forces me to name a case_id in the new_case_round_path, so it gives me this error before it loads the pick_case view:
No route matches {:action=>"new", :controller=>"rounds"} missing required keys: [:case_id]
How can I reference the route that the form needs to submit to when the required information for the route is being entered in the form?
No route matches {:action=>"new", :controller=>"rounds"} missing
required keys: [:case_id]
The error clearly says that case_id is missing. Rails expects case_id to be present which can't be provided in your situation as you are creating a new case instance.
One way to resolve your situation is to use Shallow Nesting which provides the route for new case
resources :cases do
resources :rounds, shallow :true
end
Now, when you run rake routes, you will find a route for new case as below
new_case GET /cases/new(.:format) cases#new
So that in your pick_case view, you can change the form to
<%= form_tag new_case_path, method: :get do |f| %>
<%= f.select_tag :case_id,
options_for_select(Case.all.collect { |c| [c.title, c.id] }),
class: "chosen-select" %><br/>
<%= f.submit_tag "Create round", class: "btn btn-primary" %>
<% end %>
Which creates a case instance first before redirecting to the round form
A bit of a work-around for the answer, I feel like there's probably a more elegant way. I added post 'get_case' => rounds#get_case to routes.rb
I added this to my rounds controller:
def get_case
id = params[:case_id]
if id
redirect_to new_case_round_path(case_id: id)
else
flash[:danger] = "An error occured. Please try again"
redirect_to pick_case_path
end
end
And this is my new pick_case view:
<%= form_tag get_case_path do %>
<%= select_tag :case_id,
options_for_select(map_with_id(Case, :title)),
class: "chosen-select" %><br/>
<%= submit_tag "Create round", class: "btn btn-primary" %>
<% end %>

Ruby on Rails path understanding

I want to update an existing title and a description . My items are called todo, and the database is todos(since I generate with the generate commant) .
The code that i have is
edit.html.erb :
<%= form_for :session, url: todos_path(#todo), method: :patch do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :description %>
<%= f.text_field :description %>
<br />
<%= f.submit "Create" %>
<% end %>
routes.rb:
get "/todos", to: "todos#index"
get "/todos/new", to: "todos#new"
post "/todos", to: "todos#create"
delete "/todos/delete" , to: "todos#delete"
get "/todos/three", to: "todos#three"
post "/todos/edit", to: "todos#edit"
patch "/todos/edit", to: "todos#update"
# You can have the root of your site routed with "root"
root 'todos#index'
and finally the controller:
def edit
#todo = Todo.find_by_id(params[:id])
end
def update
todo = Todo.find_by_id(params[:session][:id])
todo.update(:description,params[:session][:description])
end
My problem is : I come from the index page with an ID and the edit function display me the item that I want, then I want to update the title and description field and to hit the f.submit button to update it. My issue is that the parameters don't come, I get todos.2 (which I guess it's the size of that :session hash ?).
I do not with to use <%= button_to %> since I saw it is not needed in all tutorials .
My question is where is my mistake, why don't the parameters come ?
Change in routes:
patch "/todos/:id", to: "todos#update", as: "update_todo"
In form:
<%= form_for #todo, url: update_todo_path(#todo), method: :patch, do |f| %>
In controller:
def update
#todo.update(params.require(:todo).permit(:title, :description))
#todo.save
end
If you want to know all existing routes, you may use:
$ rake routes
It will show table like
Prefix Verb URI Pattern Controller#Action
root GET / posts#index
sign_up GET /sign_up(.:format) users#new
where prefix will be you path url like 'sign_up' it is "sign_up_path" in controller/views.
Change routes to this:
patch "/todos/edit/:id", to: "todos#update", as: :update_todo
then form:
<%= form_for :session, url: update_todo_path(id: #todo.id), method: :patch do |f| %>
and then controller:
def update
todo = Todo.find(params[:id])
todo.update_attributes(params[:session].slice(:description))
end
However, I'd recommend you to stick with the convention instead of writing and defining your own named routes for such purposes.

Routing a resource to controller

How do you route a resource to its controller? I am using the resource in an edit page for a different model, so my actions are being routed to its model controller first.
This edit page requests from
class Grandstreamers::ResellersController < ApplicationController
def new
end etc...
I am trying to route the requests to here instead:
Grandstreamers::CertificatesController < ApplicationController
def new
end
def update
end etc...
This is my form under views/grandstreamers/resellers/edit.html.erb
<%= form_for #untrained, :url => certificates_update_path(#untrained) do |f| %>
<p> Trained Users </p>
<%= select_tag "certificate[user_id]", options_for_select(#current_trained.collect{|x| [x.name, x.id]}), {:multiple => :multiple} %>
<%= f.submit "Un-Train", class: "btn btn-large btn-primary" %>
<% end %>
<%= form_for #trained, :url => certificates_create_path(#trained) do |f| %>
<p> Non-Trained Users </p>
<%= select_tag "certificate[user_id]", options_for_select(#non_trained.collect{|x| [x.name, x.id]}), {:multiple => :multiple} %>
<%= f.submit "Train", class: "btn btn-large btn-primary" %>
<% end %>
My route is:
resources :certificates
Note that the
:url => certificates_create_path
is not correct and not working. Is there a way to specify this route in my routes.rb file or in my form? Thank you
EDIT
This is my resellers_controller edit() which is routes to first.
#trained = Certificate.new(params[:certificate])
#Trying to get to certificates_controller update. Then update the :attend to "No"
##untrained = Certificate.new(params[:certificate])
##untrained = Certificate.find(params[:id])
##untrained = Certificate.find_by_user_id(params[:id])
#untrained is not defined, I am not sure how to get it to just go to my certificate controller. For #trained I can define it since its not made yet and does not give me errors when it cant find a correct value.
My certificates controller which uses create() but cannot get to update()
def create
#trained = Certificate.new(params[:certificate])
if #trained.save
#trained.update_attributes(attend: "Yes")
end
redirect_to grandstreamers_resellers_path
end
def update
#untrained = Certificate.find(params[:id])
#untrained.update_attributes(attend: "No")
redirect_to grandstreamers_resellers_path
end
Major Issue
The instance variable #trained and #untrained need to be defined somehow in reseller_controller. What can I define them as to load the edit page?
Part Solution
I defined this is in my resellers_controller and it loads the edit page now.
#untrained = User.find(params[:id])
Now I get this error:
No route matches [PUT] "/certificates.1"
I believe the problem is you need to let routing know the full name to the controller.
From the Rails routing guide:
scope module: 'Grandstreamers' do
resources :certificates
end
Use these paths when creating the form:
<%= form_for #untrained, :url => certificate_path(#untrained), :method => :put do |f| %>
<%= form_for #trained, :url => certificates_path, :method => :post do |f| %>
use this his routes.rb file
namespace :grandstreamers do
resources :certificates
end

Nested routes form is performing a get request for the index action instead of the create action

I have an app and I have nested routes like so
resources :teams, shallow: true do
resources :texts
resources :translations
end
here is my app/texts.show.html.erb.My app has texts and each text has a translation and each translation belongs to a text.When I click on a text I am taken to the texts show page where I have a form for a translator.The translator can translate the text.Each translation and text belongs to a team so that I can show specific texts and translations for specific teams.However the form below seems to be doing a get request for the index action.That is the error I am getting and I can't figure out why.Maybe something very obvious I am missing.
<% if current_user.translator %>
<%= form_for [#team, #translation] do |f| %>
<%= f.text_area :translation_text, :placeholder => 'Çeviri' %>
<%= f.hidden_field :text_id, :value => params[:id] %>
<%= f.submit 'Çevir', class: 'btn btn-primary' %>
<%end%>
<%end%>
Here is my translations_controller.rb file
def create
team = Team.find(params[:team_id])
#translation = team.translations.new(translation_params)
#translation.user_id = current_user.id
if #translation.save
redirect_to request.original_url, success: 'Çeviri tamalandı'
else
redirect_to request.original_url, danger: 'Çeviri sırasında sorun oluştu lütfen tekrar dene'
end
end
private
def translation_params
params.require(:translation).permit(:team_id, :text_id, :translation_text)
end
Could the problem be that I am in texts#show and am doing something wrong with the form?

Resources