Couldn't find [model] without an ID - Ruby on rails - ruby-on-rails

I have multiples forms in the Edit view like you can see below:
View
-#posts.each do |post|
.form
= simple_form_for post, url: update_posts_path do |f|
= f.input :title
= f.submit
Then when I'm updating any form I get this error 'Couldn't find Pots without an ID'. You can see the controller and the routes file here:
Controller
def update
#post = Posts.find(params[:id]) //If I change it for Posts.first then is working
if #post.update_attributes(params.require(:posts).permit(:title))
redirect_to ....
else
flash[:notice] = "Sorry."
render :edit
end
end
Routes File
resources :posts, :only => [:index, :edit, :update] do
get "edit", :on => :collection, :as => :edit
patch "update", :on => :collection, :as => :update
end
I think that the error is that for some reason this (#post = Posts.find(params[:id])) is returning a nil object then the controller can't update it. Can someone give me a hand?

The error is the :on => :collection part. This allows the action to be called without an id, so params[:id] is empty.
:on => :collection is normally used for index like actions that have a set of records as a result, so don't need the id part.
btw: the whole thing:
get "edit", :on => :collection, :as => :edit
patch "update", :on => :collection, :as => :update
is redundant, the first line:
resources :posts, :only => [:index, :edit, :update]
tells Rails everything it needs.

For update action you are using :on => :collection but your request is put/patch request so you will use patch "update", :on => :member, :as => :update also make changes in form_for as per your route.Use<%=simple_form_for post ,:url=> update_post_path(post) do |f| %> instead of url: update_posts_path
Regarding params.require(:posts).permit(:title)
First problem : you are using posts instead of post
second is Parameter :id is missing
you will use params.require(:post).permit(:title,:id) instead of params.require(:posts).permit(:title)

Related

Button_to patch method is unexpectedly working

I was struggling the whole day to make my button_to working. This is the code in my order index view:
<%= button_to("Remove", {:controller => "orders", :action => "update", :id => product.id}, :method => :patch) %>
my controller :
def update
#order.products.delete(Product.find(#product.id))
#product.ordinable = true
#product.save
#order.amount = 0
#order.save
#order_amountnew = #order.amount
#order.products.each do |x|
#order_amountnew = #order_amountnew + x.price
end
#order.amount = #order_amountnew
#order.save
if #order.products.empty?
#order.destroy
end
redirect_to orders_url
end
and my routes:
Rails.application.routes.draw do
root to: 'pages#home'
devise_for :users
resources :products
resources :orders, only: [:show, :create, :index, :destroy, :update]
post '/payment', action: :payorder, controller: 'orders'
patch '/orders', action: :update, controller: 'orders'
require "sidekiq/web"
authenticate :user, lambda { |u| u.admin } do
mount Sidekiq::Web => '/sidekiq'
end
end
I was trying to trigger the code inside the update method using the button_helper inside my order index. I come up with this solution and unexpectedly my button_to method now trigger the update method, but only after i spent hours googling and added to my routes this line of code:
patch '/orders', action: :update, controller: 'orders'
My question is now, whenever i want to trigger a method with a link_to or a button_to, i must create a route for each method like that right? Otherwise, i get routing error right? I have this doubt because here:
resources :orders, only: [:show, :create, :index, :destroy, :update]
i already defined an update route for my orders resource, so i don't understand why i need to specify again the route for the crud method i want to use. Thank you.
resources :orders, only: [:show, :create, :index, :destroy, :update] will yield update url as /orders/:id. You can verify that by poking in rake routes output.
patch '/orders', action: :update, controller: 'orders' yields update url as /orders.
The reason why latter works is because <%= button_to("Remove", {:controller => "orders", :action => "update", :id => product.id}, :method => :patch) %> send a request to /orders?id=.... You can verify that in the stacktrace
If you want to use 1, you should change button_to to format like <%= button_to("Remove", product_path(product), :method => :patch) %>. See https://api.rubyonrails.org/v5.2.1/classes/ActionView/Helpers/UrlHelper.html#method-i-button_to for references.
Hope that helps :).

Undefined method with "_path" while using rails form_for

I'm running into a (I think) routing error while using the Rails form_for helper. I have been searching around and looked at this question, but the plural for "static_event" with pluralize is "static_events" so I am at a loss. Any help would be apprecited. Here are the details....
ActionView::Template::Error (undefined method `static_events_path' for #<#<Class:0x007f9fcc48a918>:0x007f9fcc46fa78>):
My Model:
class StaticEvent < ActiveRecord::Base
attr_accessible :content, :title, :discount, :location, :day_of_week, :start_time
My Controller:
class StaticEventsController < ApplicationController
before_filter :authenticate, :only => [:create, :destroy]
before_filter :authorized_user, :only => [:destroy]
def new
#title = "Share An Event"
#static_event = StaticEvent.new
end
def create
#static_event = current_user.static_events.build(params[:event])
if #static_event.save
flash[:success] = "Event Shared"
redirect_to #static_event #this was the old version
else
render :new
end
end
The route:
match '/static-events/new', :to => 'static_events#new'
match '/static-events/', :to => 'static_events#index'
match '/static-events/:id', :to => 'static_events#show'
The view
<%= form_for (#static_event) do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<%= text_field "static_event", "title", "size" => 48 %>
<%= time_select "static_event", "start_time", {:ampm => true, :minute_step => 15} %>
<%= text_area "static_event", "content", "cols" => 42, "rows" => 5 %>
<%= text_field "static_event", "discount", "size" => 48 %>
<%= text_field "static_event", "location", "size" => 48 %>
<%= text_field "static_event", "day_of_week", "size" => 48 %>
<input name="" type="submit" class="button" value="share on chalkboard" />
<% end %>
Only routes created using the resources method are automatically named.
If you want to name your routes, use the :as option:
match '/static-events/new', :to => 'static_events#new', :as => :new_static_event
match '/static-events/', :to => 'static_events#index', :as => :static_events
match '/static-events/:id', :to => 'static_events#show', :as => :static_event
However, it's better to use the resources method. You must pass the "true" name of your model as the first parameter, then override the path if you want:
resources :static_events, :path => 'static-events'
First of all, you should define your routes this way:
resources 'static-events', :only => [:new, :create]
This will create a route for new and create methods.
Because when you use a new ActiveRecord object as an argument to form for, it will looks for *s_path like static_events_path in your routes file with the POST verb.
I think the way you have defined your routes doesn't create the static_events_path with POST verb (you can check that by using rake routes as megas said). So don't use match anymore, use resources or get/post/... instead of match in your Rails 3 projects.
EDIT
I did not notice yesterday, but there is no route for create method. Add the route below before static_events#index or remove all your routes and do like I said above.
post '/static-events/', :to => 'static_events#create'
Run rake routes and you'll see the list of your routes. Then you can fix the route file to have appropriate route path.
This happened to me when i was using a nested resource, but forgot to actually initialize the parent resource using load_and_authorize_resource in cancan. Therefore, the parent resource was null and it threw this error.
I fixed it by declaring load_and_authorize_resource on the parent in the controller.

Rails 3 : Can't get form_for to work as a 'delete' following the RESTful achitecture => always giving a ROUTING ERROR

I have a very simple render that goes as follow:
<%= form_for(:relationships, :url => relationships_path, :html => {:method => 'delete'}) do |f| %>
<div><%= f.hidden_field :user_id_to_unfollow, :value => #user.id %></div>
<div class="actions"><%= f.submit "Unfollow" %></div>
<% end %>
When I submit this form it will always give me a
Routing Error
No route matches "/relationships"
on my page.
In my relationships controller, I have created all the propers methods:
def create
...
end
def destroy
...
end
def update
...
end
def show
...
end
And in my routes config I have made sure to allow all routes for the relationships controller
resources :relationships
But I can't seem to get into the destroy method of the controller :(
However if I remove the
:html => {:method => 'delete'}
method parameter in the form_for then I get to the create method of the controller no pb.
I don't get it....
Alex
ps: this is the rake routes results for relationships:
relationships GET /relationships(.:format) {:action=>"index", :controller=>"relationships"}
POST /relationships(.:format) {:action=>"create", :controller=>"relationships"}
You should point the delete request to single resource url eg. relationships/4325. Run rake routes to view what url/verb combinations are valid.
--edit
Routes for relationship resources:
resources :relationships, :only => [:index, :create, :destroy]
Unfollow button (creates a form for itself):
= button_to "Unfollow", relationship_path(relationship), :method => 'delete'

RoR fragement caching based on id

Is there a way to cache a fragment based only on an id and a part?
For example, <% cache(:id => session[:user], :part => 'test') do %>
The code doesn't seem to work though. It still caches based on the action that called it.
Edit:
The problem that I am having is that I cannot expire a fragment in an ajax request(I am refreshing the page as well with page.reload). I think the problem is the action I'm trying to expire is a member of a resource.
Here's my routes code:
map.resources :profiles, :as => 'profile', :only => [:show, :edit, :update], :member => {
:home => :get
} do |profile|
Here's the expire fragment:
expire_fragment(:controller => 'profiles', :action => 'home', :part => 'test')
Thanks

observe_form url confusion

i cannot seem to get observe_form to call a particular action
i have a route defined
map.resources :charges, :collection => {:charge_total => :get}
my controller
class ChargesController < ApplicationController
def charge_total
return 'foo'
end
end
my view: i have tried both...
observe_form form_id, :update => :charge_total, :url => :charge_total_charges
and
observe_form form_id, :update => :charge_total, :url => {:controller => :charges, :action => :charge_total}
when the form updates, i get an unknown action error
No action responded to update. Actions: charge_total, create
it sees that there is an action charge_total, however it is trying to respond to update? im not sure what is going on. any thoughts?
bahh!
put, not get...
map.resources :charges, :collection => {:charge_total => :put}

Resources