【问题标题】:Ruby on Rails populate 1 field from belongs to table idRuby on Rails 从属于表 id 填充 1 个字段
【发布时间】:2016-07-12 06:54:39
【问题描述】:

您好,我是 ruby​​ on rails 的新手。我创建了两个模型品牌和产品。一个品牌可以与许多产品相关联。我使用了脚手架,因为这是我们的讲师希望我们在项目中做的事情。

我已尝试设置我的产品屏幕,以便在您输入产品时获得可供选择的品牌名称下拉列表。输入商品详情后,选择品牌名称,点击提交;所选乐队名称中的brand_id 保存到product.brand_id 表中。 (我相信当我在控制器中设置 has_many 时,brand_id 会自动在 products 表中创建)。

我曾尝试使用 collection_set 执行此操作,但我苦苦挣扎。我曾尝试使用一些关于堆栈溢出的技巧,但它们都没有奏效,作为最后的手段,我尝试自己发布一个帖子。

在模型中我添加了以下内容:

class Brand < ApplicationRecord
    has_many :product
    validates :brand_name, presence: true
end

class Product < ApplicationRecord
    belongs_to :brand
    validates :name, presence: true
end

据我了解,这意味着产品表将具有品牌 ID 和 ID。

在产品控制器中,我添加了以下内容:

class ProductsController < ApplicationController
  before_action :set_product, only: [:show, :edit, :update, :destroy]

  # GET /products
  # GET /products.json
  def index
    @products = Product.all
  end

  # GET /products/1
  # GET /products/1.json
  def show
  end

  # GET /products/new
  def new
    @brand   = Brand.all
    @product = Product.new
  end
... more code ...

在产品视图的表单中,我添加了以下内容

<%= form_for(product) do |f| %>
  <% if product.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(product.errors.count, "error") %> prohibited this product from being saved:</h2>

      <ul>
      <% product.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %>
    <%= f.text_field :name %>
  </div>

  <div class="field">
    <%= f.label :model %>
    <%= f.text_field :model %>
  </div>

  <div class="field">
    <%= f.label :price %>
    <%= f.text_field :price %>
  </div>

  <div class="field">
    <%= f.label :vat %>
    <%= f.text_field :vat %>
  </div>

  <div class="field">
    <%= f.label :image_uri %>
    <%= f.text_field :image_uri %>
  </div>
  <div class="field">
      <%= f.collection_select :brand_id, @brand, :id, :brand_name %>
  </div>



  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

routes.rb

Rails.application.routes.draw do
  resources :users
  resources :products
  resources :sales_orders
  resources :payments
  resources :filter_group_items
  resources :filter_groups
  resources :categories
  resources :sales_order_lines
  resources :brands
  resources :addresses
  get '/cart' => 'cart#index'
  get '/products' => 'products#index'
  get '/brands' => 'brands#index'
  get '/users' => 'users#index'
  get '/addresses' => 'addresses#index'
  get '/payments' => 'payments#index'

  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  #root 'application#hello'
    # You can have the root of your site routed with "root"
  #root 'welcome#index'
  root 'products#index'
end

我收到以下错误 显示 /home/ubuntu/workspace/ssd_project/app/views/products/_form.html.erb 其中第 40 行提出:

用于#的未定义方法`brand_id' 你的意思?品牌

39 <div class="field">
40   <%= f.collection_select :brand_id, @brand, :id, :brand_name %>
41 </div>

模板包含的痕迹:app/views/products/new.html.erb

如果有人对如何执行此操作有任何建议,我将不胜感激。

新路线.rb

Rails.application.routes.draw do
  resources :users
  resources :products
  resources :sales_orders
  resources :payments
  resources :filter_group_items
  resources :filter_groups
  resources :categories
  resources :sales_order_lines
  resources :brands
  resources :addresses

  resources :brands do
      resources :products
  end

  get '/cart' => 'cart#index'
  get '/products' => 'products#new'
  get '/brands' => 'brands#index'
  get '/users' => 'users#index'
  get '/addresses' => 'addresses#index'
  get '/payments' => 'payments#index'



  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  #root 'application#hello'
    # You can have the root of your site routed with "root"
  #root 'welcome#index'
  root 'products#index'
end

数据库架构 schema.rb

# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20160706122948) do

  create_table "addresses", force: :cascade do |t|
    t.string   "line1"
    t.string   "line2"
    t.string   "line3"
    t.string   "country"
    t.string   "post_code"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "brands", force: :cascade do |t|
    t.string   "brand_name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "categories", force: :cascade do |t|
    t.string   "name"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "filter_group_items", force: :cascade do |t|
    t.string   "description"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
  end

  create_table "filter_groups", force: :cascade do |t|
    t.string   "description"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
  end

  create_table "payments", force: :cascade do |t|
    t.datetime "date"
    t.decimal  "amount"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "products", force: :cascade do |t|
    t.string   "name"
    t.string   "model"
    t.decimal  "price"
    t.decimal  "vat"
    t.string   "image_uri"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "sales_order_lines", force: :cascade do |t|
    t.integer  "qty"
    t.decimal  "price"
    t.decimal  "total"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "sales_orders", force: :cascade do |t|
    t.datetime "date"
    t.decimal  "total"
    t.decimal  "vat"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "users", force: :cascade do |t|
    t.string   "name"
    t.string   "email"
    t.string   "password"
    t.string   "phone"
    t.datetime "created_at",                 null: false
    t.datetime "updated_at",                 null: false
    t.boolean  "admin_user", default: false
  end

end

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    你试过了吗:

    <div class="field">
       <%= f.collection_select :brand_id, Brand.all, :id, :brand_name %>
    </div>
    

    第二个参数是一个集合,你可以通过Brand.all获得所有可能的品牌

    然后你可以在新操作下的 Products 控制器中取出 @brand = Brand.all

    另外,在您的表单中,我认为您应该使用 form_for(@product) 而不是 product。你想要实例变量@product

    您的路线安排是否使 Product 嵌套在 Brand 下?查看路线也会很有帮助。这是另一个潜在的问题

    已编辑:

    这将是一个嵌套路由的示例(您的应用没有):

    resources :brands do
      resources :products
    end
    

    这会产生这样的路线:

    /brands/:brand_id/products/:id

    所以我重新创建了您的应用程序,发现 form_for(product) 对我造成了错误。如果它切换到@product,一个实例变量(您已经在控制器中设置),那么您的代码将按预期工作。 form_for(@product) 应该与您的产品控制器中的 @product = Product.new 匹配,新操作。回想起来,我关于如何进行 collection.select 的其他建议在本质上更具风格,但我相信它使您的代码更易于遵循。

    第二次编辑:

    您的 schema.rb 文件显示了问题。您的 Product 表不包含对 Brand 表的引用,即使您已在模型中将两者与 has_manybelongs_to 相关联(与您认为这不会自动发生的情况相反,而是通过数据库移民)。关键是,产品表缺少brand_id

    首先,我将取消嵌套您的路线,使其与以前一样:

      resources :products
      resources :brands
    

    然后您需要运行迁移以将品牌参考添加到产品表中。在您的命令行中,使用命令rails generate migration add_reference_to_products,然后在您的迁移文件夹(可以在/db/migrate 中找到)中,打开您刚刚创建的迁移文件。将以下内容添加到您的 def change 块中:

    def change
      add_reference :products, :brand, index: true, foreign_key: true
    end
    

    确保保存文件。然后在你的命令行中输入rake db:migrate 来运行迁移。这将在您的产品表中为brand_id 创建一个列,并且您的代码应该可以工作

    【讨论】:

    • 您好,非常感谢您的回复。我已将收到的错误和 routes.rb 文件放在上面的原始帖子中。我试着做你的建议,但不幸的是得到了同样的错误。我认为 form_for(@product) 不是问题,因为其他表单使用 form_for(user) 而不是 form_for(@user)。我不确定您所说的路线是什么意思,以便产品嵌套在品牌下。这可能是问题所在。如果您可以提供更多信息。我将不胜感激。
    • 我做了您建议的其他更改。我怀疑我的问题在于我设置表格的方式。我想我没有正确设置 routes.rb 链接。如果我将以下内容放入代码中,则屏幕将正确呈现。 我附上了一份更改过的 routes.rb。如果你看到任何明显的东西,请告诉我。我将与讲师交谈并获得更多帮助。不过感谢您的帮助。
    • 我并不是建议在您的情况下使用嵌套路由...实际上它会使事情变得更加复杂。你能发布你的 schema.rb 吗?
    • 您好,我添加了上面的架构。我不确定它是否有帮助
    • 其实帮助很大。请查看最新编辑。希望能解决问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-07
    • 2011-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-24
    相关资源
    最近更新 更多