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.
Related
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.
I'm starting to learn Ruby on Rails and so far everything was going well, but eventually emerging a problem I can not solve in any way. When I edit the information on my form and I click to give the update it presents me the following error(Sorry for my English, I'm not fluent in the language):
Routing Error
No route matches [POST] "/grupos/14/edit"
Rails.root: C:/Ruby/Projetos/florarails
Application Trace | Framework Trace | Full Trace
Routes
outes match in priority from top to bottom
Helper HTTP Verb Path Controller#Action
grupos_path GET /grupos(.:format) grupos#index
POST /grupos(.:format) grupos#create new_grupo_path
GET /grupos/new(.:format) grupos#new
edit_grupo_path
GET /grupos/:id/edit(.:format) grupos#edit
grupo_path
GET /grupos/:id(.:format) grupos#show
PATCH /grupos/:id(.:format) grupos#update
PUT /grupos/:id(.:format) grupos#update
DELETE /grupos/:id(.:format) grupos#destroy
Here is my code controller:
class GruposController < ApplicationController
def index
#grupos = Grupo.all
end
def show
#grupo = Grupo.find(params[:id])
end
def new
#grupo = Grupo.new
end
def create
#grupo = Grupo.new(user_params)
if #grupo.save
flash[:aviso] = 'Grupo salvo com sucesso'
else
flash[:erro] = 'Erro ao salvar grupo'
end
redirect_to (#grupo)
end
private
def user_params
params.require(:grupo).permit(:descricao)
end
def edit
#grupo = Grupo.find(params[:id])
end
def update
#grupo = Grupo.find(params[:id])
if #grupo.update_attributes(params[:grupo])
flash[:aviso] = 'Grupo salvo com sucesso'
end
redirect_to grupos_path
end
def destroy
#grupo = Grupo.find(params[:id])
#grupo.destroy
flash[:info] = "Grupo excluido com sucesso"
redirect_to(grupos_path)
end
end
Here is the code of my View:
<%= form_for :grupo do |f| %>
<p>Edição de Grupos</p>
<%= f.label :descricao, "Descrição:" %>:
<%= f.text_field :descricao, :size => 40 %>
<%= f.submit "Alterar Dados" %>
<% end %>
Here is the file content routes.rb:
Rails.application.routes.draw do
resources :grupos
match 'grupos/:id', controller: 'grupos', action: 'show', via: 'get'
match 'grupos/:id/edit', controller: 'grupos', action: 'edit', via: 'get'
match 'grupos/:id/edit', controller: 'grupos', action: 'update', via: 'post' #(When this line is added another error is displayed on the screen >> "Unknown action The action 'update' could not be found for GruposController")
end
thank you for your attention.
Try this one:
<%= form_for :grupo, url: :grupo_path do |f| %>
<p>Edição de Grupos</p>
<%= f.label :descricao, "Descrição:" %>:
<%= f.text_field :descricao, :size => 40 %>
<%= f.submit "Alterar Dados" %>
<% end %>
Also, You do need in routes that match lines. resources :grupos will cover for you.
Remove:
match 'grupos/:id', controller: 'grupos', action: 'show', via: 'get'
match 'grupos/:id/edit', controller: 'grupos', action: 'edit', via: 'get'
match 'grupos/:id/edit', controller: 'grupos', action: 'update', via: 'post'
First, POST actions should be reserved for object creation, not update. Use PUT or PATCH for updates.
Also, key actions in your controller (edit, update, and destroy) are private which should be public in order to be routable. Which is the source of your error in the last section.
In a nutshell, most of your problems would be resolved simply using resources :groupos. Which will generate consistent routes:
grupos GET /grupos(.:format) grupos#index
POST /grupos(.:format) grupos#create
new_grupo GET /grupos/new(.:format) grupos#new
edit_grupo GET /grupos/:id/edit(.:format) grupos#edit
grupo GET /grupos/:id(.:format) grupos#show
PATCH /grupos/:id(.:format) grupos#update
PUT /grupos/:id(.:format) grupos#update
DELETE /grupos/:id(.:format) grupos#destro
As a final note, you should user form_for #grupo instead of form_for :gropo. This will allow your form fields to be dynamically populated from their matching attributes in #grupo
I have a UsersController and it has below code
def sign_up
#user = User.new
end
And my view page has
<div class="col-md-6 col-md-offset-3">
<%= form_for #user do |f| %>
<%= f.label :first_name%>
<%= f.text_field :first_name %>
<%= f.label :last_name %>
<%= f.text_field :last_name %>
<%= f.submit "Register", class: 'btn btn-primary'%>
<% end %>
</div>
My routes.rb file contains the following entry
get 'signup' => 'users#sign_up'
But When I submit the form, it says
ActionView::Template::Error (undefined method `users_path' for #<#<Class:0x00000004d91490>:0x00000004d90220>)
Why does this throw an error and do I need to explicity point to url in the form_for?? Why is it so??
Change your routes to:
resources :users, only: [:new, :create], path_names: {new: 'sign_up'}
and rename your sign_up action back to new. The reason you are getting the error is rails trying to guess the correct url for given resource. Since you have passed #user, which is an instance of User class, it will try to call "#{#user.class.model_name.route_key}_path key, which results in the error you got.
To solve the issue you need either make your routes to define users_path or you need to specify the url directly using url option. users_path can be defined by either index or create action, so the above solution will work (and will not create remaining CRUD routes, yey!)
Try changing this line:
<%= form_for #user do |f| %>
to this:
<%= form_for(#user, url: 'signup') do |f| %>
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
I keep getting an error saying: undefined method `androids_path' for #<#:0x007ff5edcd5330>. It's saying the error is at line 1 in new.html.
The name of the model is Android and is at android.rb. Any advice on how to fix this?
In androidapps_controller.rb:
def new
#android = Android.new
end
In new.html I have:
<%= form_for(#android, validate:true) do |f| %>
<% #android.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<%= f.submit %>
<% end %>
routes.rb
Grabapp::Application.routes.draw do
root :to => 'iosapps#index'
get "static_pages/home"
get "static_pages/add"
get "static_pages/about"
devise_for :users
resources :iosapps
resources :androidapps
Add to your routes.rb:
resources :android
You're error is because you've asked form_for to do resource based routing!
<%= form_for(#android, validate:true) do |f| %>
But you didn't define the resource based routing required to make it work!
Your model and controller are not matched (Android vs AndroidApp), so need to specify the correct url in your form:
<%= form_for(#android, validate: true, url: androidapps_path) do |f| %>
<%= form_for(#android, validate:true) do |f| %> automatically sets up the correct HTTP method (normally POST or PUT) with the HTML markup for a form. It also assumes you have a url set up called /androids in the case of POST and /androids/:id in the case of PUT. So for this to work you need to tell rails to create the necessary routings. This is done by adding the following line in config/routes.rb namely resources :androids.
This is why is is better to match up your model and controller names, Rails can then automatically infer the correct controller actions based on the model name.
You need to read up a bit more on routing and how it works. Do it here: http://guides.rubyonrails.org/routing.html