1

cIn my Rails 4 app, my update action is working, so I can edit, but my create action is not. I can't figure out why I can add products_id and user_id in the edit form, but when I try to use create a new catalogue I get errors.

My create action:

def create
 @catalogue = Catalogue.new(catalogue_params)
 if @catalogue.save
   redirect_to @catalogue, notice: "Catalogue was successfully created."
 else
   render action: "new"
 end
end

My update action:

def update
 if @catalogue.update(catalogue_params)
   redirect_to @catalogue, notice: "Catalogue was successfully updated."
 else
   render action: "edit"
 end
end

My strong parameters:

private

 def set_catalogue
   @catalogue = Catalogue.find(params[:id])
 end

 def catalogue_params
   params.require(:catalogue).permit(:title, :url, :google_name, product_ids: [], user_ids: [])
end

From the form:

Forgot my form code:

.field
  = f.collection_select(:user_ids, @catalogue.get_all_users, :id, :name, {}, multiple: true)
.field
  = f.label :product_ids
  = f.collection_select(:product_ids, @catalogue.get_all_products, :id, :title, {}, multiple: true)
.actions
= f.submit "Save"

The fields that are not working with create are the arrays: product_ids: [] and user_ids: []. If I click on one of the catalogues that I had created with a seed file, I can open it for edit and add a product or user from the drop down fields in the form. The catalogue is updated, no problem. The form has select and sends products and users as arrays.

But if I click on New Catalogue, I get this error:

2 errors prohibited this catalogue from being saved:

  Catalogue users is invalid
  Catalogue products is invalid
--- !ruby/hash:ActionController::Parameters
utf8: "✓"
authenticity_token: ddJsIAweWHoblmbOAjoNpZ0iPwi8ookrgH6HOzd/jh4=
catalogue: !ruby/hash:ActionController::Parameters
  title: Testing Create
  url: www.something.com
  google_name: ''
  user_ids:
  - ''
  - '1'
 product_ids:
  - ''
 - '1'
commit: Save
action: create
controller: catalogue

I can see that the selections are there for each item but not the names, so I don't understand why it's not creating, and why if I open a previously created catalogue, I can add products and users via the form. But not create.

And this from the console:

Processing by CatalogueController#create as HTML
Parameters: {"utf8"=>"✓",  "authenticity_token"=>"ddJsIAweWHoblmbOAjoNpZ0iPwi8ookrgH6HOzd/jh4=", "catalogue"=>{"title"=>"Testing Create", "url"=>"www.something.com", "google_name"=>"", "user_ids"=>["", "1"], "product_ids"=>["", "1"]}, "commit"=>"Save"}

I am using join tables between user and catalogue, and product and catalogue:

class CatalogueProduct < ActiveRecord::Base
  belongs_to :catalogue
  belongs_to :product

  validates :product_id, :catalogue_id, presence: true
end

class Catalogue < ActiveRecord::Base
  include ModelHelper
  has_many :catalogue_users, dependent: :destroy
  has_many :users, through: :catalogue_users

  has_many :catalogue_products, dependent: :destroy
  has_many :products, through: :catalogue_products

The user model follows the same patter as above.

I'm wondering if I need to convert those arrays to strings? Because in the above it's listing the actual id. But why then doesn't the update action need the conversion? I'm confused about what's going on and how to fix it. I kept getting errors when I tried converting to strings in the strong parameters.

Thank you!!!!!

2 Answers2

0

Here's the problem:

2 errors prohibited this catalogue from being saved:

  Catalogue users is invalid
  Catalogue products is invalid

Your code looks good

--

Associative Data

I think the problem is you're trying to pass multiple ids for user_ids and product_ids. Issue being this only works if you've got join models for either of those items (so Rails can populate their collection objects).

Without knowing your model associations, I can only speculate, but I would surmise changing your user_ids & product_ids to user_id & product_id should solve the issue (considering you have the columns user_id and product_id in your catalogues table)

.field
  = f.collection_select(:user_id, @catalogue.get_all_users, :id, :name, {}, multiple: true)
.field
  = f.label :product_ids
  = f.collection_select(:product_id, @catalogue.get_all_products, :id, :title, {}, multiple: true)
.actions
= f.submit "Save"

#app/controllers/home_controller.rb
def catalogue_params
   params.require(:catalogue).permit(:title, :url, :google_name, product_id, user_id)
end

--

Models

Thinking about your system, I would suggest you have a deeper issue with the structure of your models. More specifically, you want to associate a catalogue with multiple products & multiple users?

If this is the case, I would structure the models as thus:

#app/models/catalogue.rb
has_and_belongs_to_many :products
has_and_belongs_to_many :users

#Tables:
#catalogues_users
#cataglogues_products

This will allow you to submit user_ids and product_ids to the Catalogue model

Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • When I tried your suggestion, the database can't find the tables catalogues_uers and catalogues_products, even though those models have the belongs_to catalogue, belongs_to product. When I changed it back again, I get the list of catalogues on the index page, but I cannot create new ones. – Dana Nourie May 31 '14 at 19:34
0

In create action, before @catalogue=Catalogue.new(catalogue_params), just add this snippet:

params[:catalogue][:user_ids].delete('')
params[:catalogue][:product_ids].delete('')

That's because your form is submitting an empty id for each associated model (users, products), which is of course invalid when trying to associate.

Ruby Racer
  • 5,690
  • 1
  • 26
  • 43
  • I was hoping this would work. But, nope, same error. This is an interesting problem, but so frustrating too. – Dana Nourie May 31 '14 at 18:27
  • Well, that's funny... Could you also try adding these lines right under "def catalogue_params" instead of under "def create"? This is a common bag and you should either "hack" your model, or try to do a simpler thing. Check this out: http://stackoverflow.com/questions/8929230/why-is-the-first-element-always-blank-in-my-rails-multi-select-using-an-embedde – Ruby Racer May 31 '14 at 21:19
  • I added those two lines of code under def catalogue_params, and got this error: Completed 500 Internal Server Error in 26ms ArgumentError (When assigning attributes, you must pass a hash as an argument.): – Dana Nourie Jun 01 '14 at 01:47
  • The weird thing is, I did something similar on another project, and had no problem with the multiselect menu or the controller. It just worked without any special lines of code. – Dana Nourie Jun 01 '14 at 01:48
  • I tried the link you provided, and used this in the form: :include_hidden => false. But unfortunately I get the same error! – Dana Nourie Jun 01 '14 at 02:44