Ruby on Rails从属于表id

时间:2016-07-08 17:55:07

标签: ruby-on-rails ruby

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

我尝试设置我的产品屏幕,这样当您输入产品时,您会看到一个品牌名称下拉列表供您选择。输入产品详细信息时,选择品牌名称,然后单击“提交”;所选波段名称中的brand_id保存在product.brand_id表中。 (我相信当我在控制器中设置has_many时,会在products表中自动创建brand_id)。

我尝试过使用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

根据我的理解,这意味着产品表将具有brand_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

如果有人对如何做到这一点有任何建议,我将非常感激。

New 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

  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

Database Schema 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

1 个答案:

答案 0 :(得分: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

您的路线是否已安排,以便产品嵌套在品牌下?看看路线也会很有帮助。这是另一个潜在的问题

<强>编辑:

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

resources :brands do
  resources :products
end

这会产生这样的路线:

/品牌/:brand_id /产品/:ID

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

第二次编辑:

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

首先,我会删除你的路线,以便它像以前一样:

  resources :products
  resources :brands

然后,您需要运行迁移以将品牌引用添加到products表。在命令行中,使用命令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以运行迁移。这将在您的product表中为brand_id创建一列,您的代码应该可以使用