2016-07-08 58 views
0

您好我是Ruby on Rails的新手。我創造了兩個模型品牌和產品。一個品牌可能與許多產品有關。我使用腳手架,因爲這是我們的講師期望我們在我們的項目中做的。Ruby on Rails從屬於表id的1個字段填充

我試圖設置我的產品屏幕,這樣當你輸入產品時,你會得到一個可供選擇的品牌名稱的下拉列表。當您輸入產品詳情時,請選擇品牌名稱,然後點擊提交;所選波段名稱中的brand_id保存到product.brand_id表中。 (當我在控制器中設置has_many時,我相信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。

在產品控制器I加入下列:

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/prod ucts/_form.html.erb在哪裏行#40上升:

未定義的方法`brand_id'爲# 您的意思是?品牌

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

模板包含的跟蹤:應用程序/視圖/產品/ new.html.erb

如果任何人有如何做到這一點,我會很感激的任何建議。

新的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 

數據庫架構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

你試試這個:

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

第二個參數是一個集合,你可以得到所有可能的品牌與Brand.all

然後你就可以取出保存在產品控制線@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

首先,我想UNNEST你的路由,這樣,就如前:

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的列,並且您的代碼應該可以工作

+0

嗨非常感謝您的回覆。我在上面的原始文章中放置了我得到的錯誤和routes.rb文件。我試着做你的建議,但不幸的是得到了同樣的錯誤。我不認爲form_for(@product)是問題,因爲其他表單使用form_for(user)而不是form_for(@user)。我不確定你的意思是什麼路線安排,以便產品嵌套在品牌下。這可能是問題。如果你可以提供更多的信息。我會非常感激。 – ns2016

+0

看到編輯答案 – Ren

+0

我做了你建議的其他更改。我懷疑我的問題在於我設置表格的方式。我想我沒有正確設置routes.rb鏈接。如果我在代碼中輸入以下內容,則屏幕呈現正確。 <%= f.collection_select:id,Brand.all,:id,:brand_name%>我附上了更改的routes.rb的副本。如果你看到任何明顯的東西讓我知道。我會和講師講話並獲得更多幫助。儘管感謝您的幫助。 – ns2016

相關問題