一个/或关联与两个单独行的多态关联,其中一个为空

时间:2018-04-20 02:44:19

标签: ruby-on-rails

我是rails的新手并且正在尝试实现多态关联。基本上,我有一个设备对象,可以属于插座或端口,但不能同时属于两者。根据我的理解,多态关联将是这样做的方式,所以我这样建模:

class Device < ApplicationRecord
    belongs_to :io, polymorphic: true
end

class Outlet < ApplicationRecord
    has_one :device, as: :io
end

class Port < ApplicationRecord
  has_one :device, as: :io
end


  create_table "devices", force: :cascade do |t|
        ...
        t.integer "io_id"
        t.index ["io_id"], name: "index_devices_on_io_id"
      end

现在,我在尝试将outletport分配给设备io时遇到了一些麻烦:

  

无法写出未知属性io_type

  @outlet = Outlet.where(id: @outlet_id).first

  @device.io = @outlet

  if @device.save
  redirect_to @device

来自

class DevicesController < ApplicationController
    def new
        @device = Device.new(io_id: params[:io_id])
    end

    def create
        @outlet_id = params[:device][:io_id]
        @device = Device.new(device_params)

        @outlet = Outlet.where(id: @outlet_id).first

        @device.io = @outlet

        if @device.save
        redirect_to @device
      else
        render 'new'
      end

  end

现在,我很乐意接受一些关于为什么会抛出此错误的帮助,但这不是我的主要问题。调试时我有一个想法 - 如果我不在这里使用多态关联,这是否有意义?在我的device表上创建两个单独的关联,一个指向port表,另一个指向outlet表并使它们都是可选的,这也没关系吗?一个将保持为null而另一个将被分配,然后我可以检查我的业务逻辑中的哪个字段!= null。我会在这条路上遇到问题吗?

1 个答案:

答案 0 :(得分:1)

Device需要io_idio_type。否则,Device将如何知道io_id属于哪种类型的东西?

目前,如迁移所示,您只有io_id。因此,您收到了io_type的未知属性错误。

你应该将io_type添加到你的桌子上,你应该好好去。

我建议您将create操作修改为更像(有一些评论):

class DevicesController < ApplicationController
  def new
    @device = Device.new(io_id: params[:io_id])
  end

  def create

    # how do you know the :io_id is for an Outlet and not a Port?
    # if you add a hidden field that includes io_type, so that
    # params[:device] = {io_id: x, io_type: 'Outlet'}, then you 
    # should be able to do something like:
    @io = params[:device][:io_type].constantize.find_by(id: params[:device][:io_id])

    # the has_one association provides the build_device method.
    # if you use this method, then io_id and io_type will 
    # automatically be set on @device
    @device = @io.build_device(device_params)

    if @device.save
      redirect_to @device
    else
      render 'new'
    end

end