I am trying to use form.collection_select in an order form with data from a second model named products. I would like to use the field "product_reference" from the products table as selector in my HTML page. When in the order form, I want to present all product_references to the user in a selctor, let the user make his choice, take this product_reference, and store the corresponding product_id in the order form (and database table field). I have two tables, connected by id as in this schema:
create_table "orders", force: :cascade do |t|
t.datetime "order_date"
t.bigint "product_id", null: false
...
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["product_id"], name: "index_orders_on_product_id"
end
create_table "products", force: :cascade do |t|
t.string "brand"
t.string "product_reference"
t.string "description"
...
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["product_reference"], name: "index_products_on_product_reference", unique: true
end
with the relationships described this way:
app/models/order.rb
class Order < ApplicationRecord
belongs_to :product
end
app/models/ product.rb
class Product < ApplicationRecord
has_many :orders
end
I used the rails console, and got exactly what I want this way:
Product.all.map(&:product_reference)
Product Load (0.8ms) SELECT "products".* FROM "products"
=>
["C-Beau33",
"C-Beau50",
...
"B-Volk33",
"B-Volk66"]
In my controller I have tried to assign @prodrefs with this dezired result, which I could then use in the collection_select: Order Controller:
# GET /orders/new
def new
@order = Order.new
@prodrefs = Product.all.map(&:product_reference)
end
I used this in my html view: app/views/orders/_form.html.erb
<%= form.collection_select :order_id, Product.all, :id, @prodrefs, :prompt => 'Select Ref' %>
and step on this error message:
["C-Beau33", "C-Beau50", ... "B-Volk33", "B-Volk66"] is not a symbol nor a string
I think this error msg is not precisely linked to my problem, when trying just to add ".to_s" I only get another error on
undefined method `#<Product::ActiveRecord_Relation:0x00007fa1087ddda8>' for #<Product id: 1, brand: "Beaufort", product_reference: "C-Beau33",...>
What has been done so far:
in an older approach with a foreign key directly on this "product_reference", I was able to use this code in my view, worked like a charm, user could select the product_reference from the pull down menu in his browser:
<%= form.collection_select :fk_prodref, Product.order(:product_reference), :product_reference, :product_reference, :prompt => 'Select Ref' %>
This fk_approach has now been rejected, cause some extensions were necessary, with new model associations.
Looking at the RubyOnRails Guide, I can find the example on cities, and the explanation in ActionView::Helpers::FormBuilder page, I see the description as:
collection_select(method, collection, value_method, text_method, options = {}, html_options = {})
So I believe my text_method is the problem here. When I translate from the guide, I come to this logic:
collection_slct html in city example
method -> <option value=>
collection -> Berlin
value_method -> <select ... id="city_id">
text_method -> <select name="city_id">
which let's me believe, that I want to have the 2nd row (collection) as all my product references. But I ammissing the point on the text_method then, cause the error message directs me there. Any help highly appreciated
CodePudding user response:
You're close. Kind of a mish-mash of several ways that can work, but you're close.
You can do this in a controller if you choose, though it would just be
@products = Product.all.order(:id). # or whatever order you would like
Then in your form
<%= form.collection_select( :product_id, @products, :id, :product_reference, prompt: 'Select Ref') %>
- The first argument is the attribute you are saving, in your case, where you have order_id above, it's really product_id.
- The section argument is the list of objects for the collection
- The third argument is the attribute from the collection you need to save to the product_id attribute. In this case, it is
id
- The fourth argument is the attribute name you would like displayed in the dropdown,
:product_reference
- Lastly the fifth option is for the prompt