has_one relation collection_select未定义方法`department_id'for

时间:2013-11-18 15:19:20

标签: ruby-on-rails-4 mongoid

我有模型架构:

class Order
  include Mongoid::Document
  has_one :department
end
class Department
  include Mongoid::Document
  belongs_to :order
end

订单表格如下:

<%= form_for @order, :html => {} do |f| %>
  <%= f.collection_select(:department_id, Department.all, :id,:name) %>
  <%= f.submit nil %>
<% end %> 

提交会抛出此错误消息:

undefined method `department_id' for #<Order:0x007f993861e0f8>

我真的不知道为什么。任何的想法?谢谢

2 个答案:

答案 0 :(得分:1)

您应该更改模型定义。 belongs_to定义需要模型中的相应id值。 has_one没有,因为它依赖于对手。

因此,您应该设置模型,反转has_onebelongs_to来电:

class Order
  include Mongoid::Document
  belongs_to :department
end
class Department
  include Mongoid::Document
  has_one :order
end

我还担心Department应该有多个订单相关联。在这种情况下,您只需删除has_one :order语句。

现在,要使一切正常,您必须确保department_id模型中存在Order字段。我不知道Mongoid世界,但对于通常的数据库,你会做这样的事情

rails g migration AddDepartmentIdToOrders department_id:integer
rake db:migrate

那你应该没事。

答案 1 :(得分:1)

问题是你从关系的存储方向走向相反的方向。 实际存储了从Order到Department的关系存储 作为Department上的外键order_id,而不是订单上的department_id。 您可以在设置关系后检查模型的对象来验证这一点。 如果要使用collection_select,则需要转向另一个方向以使用外键。 下面的示例显示了如何从父母到孩子的前进方向。 希望它能帮助你前进。

应用程序/控制器/ demo_controller.rb

class DemoController < ApplicationController
  def show
    @order = Order.first
    render :show
  end
end

应用程序/视图/演示/ show.html.erb

<h1>Demo#show</h1>
<p>Find me in app/views/demo/show.html.erb</p>

<%= form_for @order, url: {action: "show"}, :html => {} do |order_form| %>
    <%= order_form.text_field :date %>
    <%= fields_for @order.department do |order_department_form| %>
        <%= order_department_form.text_field :name %>
    <% end %>
    <%= order_form.submit nil %>
<% end %>

测试/功能/ demo_controller_test.rb

require 'test_helper'

class DemoControllerTest < ActionController::TestCase
  def setup
    Order.delete_all
    Department.delete_all
    puts
  end
  test "0. mongoid version" do
    puts "Mongoid::VERSION:#{Mongoid::VERSION}\nMoped::VERSION:#{Moped::VERSION}"
  end
  test "should get show" do
    order = Order.create(date: Time.now)
    department = Department.create(name: 'Development')
    order.department = department
    assert_equal 1, Order.count
    assert_equal 1, Department.count
    get :show
    assert_response :success
    #puts @response.body
  end
end