providence
providence

Reputation: 29463

Rails form trouble

So, I have something of an odd controller/view setup, editing a Product model object occurs in the listings controller/view. There is a long-winded explanation for why this is, but I digress. However, when I submit the form, I get the error Couldn't find Product without an ID . What gives? Strangely, when I look at the params sent with the request, the ID attribute is assigned to the 'format' key. ?!.

The controller code is very simple. Edit Action:

def edit
  @edit = Product.find(params[:id])
end 

Update Action:

def update
  @edit = Product.find(params[:id])

  if @edit.save
    redirect_to :url => listings_display_path
  end
end

Here is my form_for code:

<% form_for @edit, :url => (listings_update_path(@edit)) do |f| %>

Edit, the trace:

{"utf8"=>"✓",
"_method"=>"put",
"authenticity_token"=>"st17LW0S9uENaV8UBcxKUfRH67oo+r3TuFAxiPKMCEc=",
"product"=>{"brand"=>"test_brand",
"productname"=>"test_product",
"category"=>"test_category",
"regprice"=>"4",
"saleprice"=>"2",
"description"=>"description"},
"commit"=>"Submit",
"format"=>"21"}

Edit: routes.rb

resources :product do
  resources :promotions
  collection do
    get "replace"
  end
end

#listings
match 'listings/index' => 'listings#index'
match 'listings/display' => 'listings#display'
match 'listings/edit' => 'listings#edit'
match 'listings/update' => 'listings#update'

Edit: create action

def create

  @product = Product.new(params[:product])
  @product.user = current_user

  if @product.save
    redirect_to :action => 'index'
  end
end

Upvotes: 0

Views: 148

Answers (3)

Aaron Hinni
Aaron Hinni

Reputation: 14716

You need to fix the routes that are for a single product instance to have the id:

match 'listings/index' => 'listings#index'
match 'listings/:id/display' => 'listings#display'
match 'listings/:id/edit' => 'listings#edit'
match 'listings/:id/update' => 'listings#update'

Upvotes: 0

Andrew
Andrew

Reputation: 43113

First, for an alternate approach to editing multiple records on a single view, try this railscast: http://railscasts.com/episodes/198-edit-multiple-individually

Second, this is unconventional but your whole approach is unconventional...

You can stick a hidden field in the form with the ID in it. Something like:

<%= f.hidden_field, :product, :id %>

Then check your params hash and the id will be in there. You should be able to access it in the controller using something similar to:

# untested
@edit = Product.find(params[:product][:id])

Off the top of my head I'm not sure how it will be stored in your params hash but it will be there and you'll be able to access it like any other hash attribute.

Good luck!

--EDIT--

Also, regarding your comment about lack of flexibility in Rails -- one thing I've learned is that Rails isn't inflexible, but it is highly optimized for particular conventions. The developers refer to this as being "highly opinionated" software, which means:

  1. It can do just about anything you care to do it any way you want to do it, but...
  2. There's almost always a "preferred" way which is better, faster (harder stronger lol).

You would save yourself tons of time and energy -- and probably have a lot of fun -- grabbing the Beginning Rails 3 book. You could work through it in a weekend, and when you were done you would have a great primer on the "Rails Way" which would hopefully help you go from "I don't get why Rails doesn't do this or that" to "I get how Rails works and how easy it is to do what I want to do by following X pattern". That's what happened for me anyhow.

Again good luck!

Upvotes: 1

fl00r
fl00r

Reputation: 83680

Try this

<%= form_for @edit, :url => listings_path(@edit), :html => {:method => :put} do |f| %>

Upvotes: 0

Related Questions