1

I'm new to rails to bear with me.

This concerns two of my models: Product and Manufacturer.

When creating a new product the user can select which manufacturer the product belongs to from a drop down list. The problem is that I can't get this manufacturer to save. I know I have to add some code to the controller and I've tried various things but to no avail.

Here's the view:

<h1>New Product</h1>

<%= form_for(@product) do |f| %>
<div>
    <%= f.label :name, 'Name' %>
    <%= f.text_field :name %>
</div>

<div>
    <%= f.label :market_price, 'Market Price' %>
    <%= f.text_field :market_price %>
</div>
<div>
    <%= f.label :sell_price, 'Sell Price' %>
    <%= f.text_field :market_price %>
</div>
<div>
    <%= f.label :stock_level, 'Stock Level' %>
    <%= f.text_field :stock_level %>
</div>
<div>
    <%= f.label :manufacturer, 'Manufacturer' %>
    <%= f.collection_select(:manufacturer, Manufacturer.all, :id, :name, prompt: true) %>
</div>
<div>
    <%= f.label :location, 'Location' %>
    <%= f.collection_select(:location, Product.all, :id, :location, prompt: true) %>
    </div>
<br> </br>
<div>
        <%= f.submit "Create Product" %>
</div>

And here's part of the controller:

def create
  @product = Product.new(params[:product].permit(:name, :market_price, :sell_price, :stock_level, :location))
  @product.save
  flash[:notice] = 'Product Created'
  redirect_to @product
end
end

After hours of trying several nesting methods, I still can't get this to work. Surely it's very common to save fields from various models on one page???

Arkane55
  • 17
  • 6
  • 2
    In addition abbot567's answer which is very useful, I think you also need to permit the manufacturer id in the controller, which is a nested object. More info: http://stackoverflow.com/questions/18436741/rails-4-strong-parameters-nested-objects – jyrkim May 09 '15 at 10:05

2 Answers2

1

You would usually nest your routes, so that products were within manufacturer:

resources :manufacturer do
    resources :products
end

Then your form would be a form for an array:

form_for([@manufacturer, @product]) do |f|
    f.hidden_field :manufacturer_id, value: @manufacturer.id

This allows you to pass in the ID of both the manufacturer and the product.

Now in your controller you can use something like the following, provided the associations are set up, such as product belongs_to :manufacturer and manufacturer has_many :products

@manufacturer = find(params[:manufacturer_id])
@product = @manufacturer.products.create()
abbott567
  • 862
  • 6
  • 18
  • while this is interesting, it's not at all relevant to the question at hand. – sevenseacat May 09 '15 at 10:13
  • @sevenseacat it isn't? I apologise if this is the case. Perhaps I misunderstood the question? – abbott567 May 09 '15 at 10:23
  • @abbott567 where do the last two lines of code go in the controller? Thanks!! – Arkane55 May 10 '15 at 03:06
  • @Arkane55 they would go in the create action. In the question you posed, you had Product.new then Product.save, the two lines would replace this. This will look up the manufacturer, and then create and save a product linked to that manufacturer – abbott567 May 10 '15 at 07:13
  • also, as @jyrkim mentions in the comments above, you would possibly need to add :manufacturer_id to your permitted parameters – abbott567 May 10 '15 at 07:15
  • @abbott567 it's not relevant because you're asking the OP to restructure his routes, form and controller when all he's missing is permitting a parameter. – sevenseacat May 10 '15 at 07:30
  • I see, then by all means submit the correct answer and I will of course upvote it... – abbott567 May 10 '15 at 07:34
0

In your form, you need to have a field for manufacturer_id, not manufacturer. You would change f.collection_select(:manufacturer to be f.collection_select(:manufacturer_id.

Then, in your controller, you need to add manufacturer_id to the list of parameters you are permitting in your permit method call. So it would be Product.new(params[:product].permit(:name, :market_price, :sell_price, :stock_level, :location, :manufacturer_id)).

sevenseacat
  • 24,699
  • 6
  • 63
  • 88
  • I tried this method and it didn't work. Besides I don't see the difference between having `manufacturer_id` and `name` in the form, can you explain? – Arkane55 May 10 '15 at 02:42
  • What "didn't work"? You use `manufacturer_id` because that's the name of the field in your database, as it is an association with the Manufacturer model. – sevenseacat May 10 '15 at 07:28
  • @Arkane55 - If this doesn't work, it's probably an issue with the way you've set up your models (`has_one`/`has_many` and `belongs_to` relationships) – rohitpaulk May 10 '15 at 07:59
  • @sevenseacat So my Manufacturer model has 3 fields: `id` (auto generated), `name` and `manufacturer_id` (which I added after reading your post). How are `name` and `manufacturer_id` any different? They are similar fields. The error which I got was undefined method 'manufacturer_id'. @rohitpaulk the associations are set up fine: manufacturer `has_many` products and product `belongs_to` manufacturer – Arkane55 May 10 '15 at 09:32
  • Ah no, I presumed you have a manufacturer_id field on your Product model, given you said a product belongs to a manufacturer. – sevenseacat May 10 '15 at 11:14