RubyOnRails 使用第二个表中的数据进行form.collection_select

RubyOnRails form.collection_select with data from second table

提问人:pebwindkraft 提问时间:12/19/2022 更新时间:12/20/2022 访问量:58

问:

我正在尝试在订单中使用form.collection_select,其中包含来自名为 products 的第二个模型的数据。我想在我的 HTML 页面中使用 products 表中的字段“product_reference”作为选择器。 在订单表单中,我想将所有product_references呈现在选择器中,让用户做出选择,product_reference,并将相应的product_id存储在订单表单(和数据库表字段)中。 我有两个表,通过id连接,如以下模式所示:

  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

使用以下描述的关系:

app/models/order.rb
  class Order < ApplicationRecord
    belongs_to :product
  end

app/models/ product.rb
  class Product < ApplicationRecord
    has_many :orders
  end

我使用了 rails 控制台,并以这种方式得到了我想要的东西:

Product.all.map(&:product_reference)
  Product Load (0.8ms)  SELECT "products".* FROM "products"
=>
["C-Beau33",
 "C-Beau50",
 ...
 "B-Volk33",
 "B-Volk66"]

在我的控制器中,我尝试将这个 dezired 结果分配给@prodrefs,然后我可以在collection_select中使用它: 订单控制员:

  # GET /orders/new
  def new
    @order = Order.new
    @prodrefs = Product.all.map(&:product_reference)
  end

我在我的html视图中使用了它: app/views/orders/_form.html.erb

<%= form.collection_select :order_id, Product.all, :id, @prodrefs, :prompt => 'Select Ref' %>

并点击此错误消息:

["C-Beau33", "C-Beau50", ... "B-Volk33", "B-Volk66"] is not a symbol nor a string

我认为此错误消息与我的问题没有完全相关,当尝试仅添加“.to_s”时,我只会收到另一个错误

undefined method `#<Product::ActiveRecord_Relation:0x00007fa1087ddda8>' for #<Product id: 1, brand: "Beaufort", product_reference: "C-Beau33",...>

到目前为止已经做了什么:

在直接在这个“product_reference”上使用外键的旧方法中,我能够在我的观点中使用此代码,就像一个魅力一样工作,用户可以从浏览器的下拉菜单中选择product_reference:

<%= form.collection_select :fk_prodref, Product.order(:product_reference), :product_reference, :product_reference, :prompt => 'Select Ref' %>

此fk_approach现在已被拒绝,因为需要进行一些扩展,并具有新的模型关联。

查看 RubyOnRails 指南,我可以找到关于城市的例子,以及 ActionView::Helpers::FormBuilder 页面中的解释,我看到的描述是:

collection_select(method, collection, value_method, text_method, options = {}, html_options = {})

所以我相信我text_method是这里的问题所在。当我从指南中翻译时,我得出了这个逻辑:

 collection_slct    html in city example
 method         ->  <option value=>
 collection     ->  Berlin
 value_method   ->  <select ... id="city_id">
 text_method    ->  <select name="city_id">

这让我相信,我希望将第二行(集合)作为我所有的产品参考。但是我错过了text_method上的要点,因为错误消息将我引导到那里。任何帮助都非常感谢

Ruby-on-Rails 表单 模型 集合-选择

评论


答:

2赞 trh 12/20/2022 #1

你很接近。有点像几种可行的方法的大杂烩,但你已经很接近了。

如果您愿意,您可以在控制器中执行此操作,尽管它只是

@products = Product.all.order(:id). # or whatever order you would like

然后在您的表格中

<%= form.collection_select( :product_id, @products, :id, :product_reference, prompt: 'Select Ref') %>
  • 第一个参数是您要保存的属性,在您的例子中, 在上面有order_id的地方,真的很product_id。
  • section 参数是集合的对象列表
  • 第三个参数是集合中需要保存到 product_id 属性的属性。在这种情况下,它是id
  • 第四个参数是要在下拉列表中显示的属性名称,:product_reference
  • 最后,第五个选项是提示

评论

0赞 pebwindkraft 12/20/2022
唉!太简单了,真的!我以为我必须使用order_id,因为我是部分的顺序形式,并在订单表中保存一个元素。看看 Rails 文档,它说第一个字段是“方法”,但你解释它的方式让我更清楚了——谢谢!