Rails-一对一关联

时间:2019-05-10 12:03:18

标签: ruby-on-rails ruby-on-rails-5

让我们假设我有一个清单和一个路由器。 一个纪念碑有一个路由器,而路由器属于一个纪念碑。这是一对一的关系。通常的方法是在路由器表中使用外键(monument_id)。这很容易,我只需要选择带有古迹列表的路由器,就可以建立该路由器的关联。

但是现在让我们假设我要在纪念碑侧进行这些关联。例如,我将为纪念碑创建一个_form,并且在该表单中,我可以选择可用的路由器。我该如何实现?因为我知道这会产生错误,因为在纪念碑侧没有任何属性可保存所选路由器。

这是否是我想要实现的目标?如果是这样,您能举个例子吗?谢谢!

对不起英语。

3 个答案:

答案 0 :(得分:0)

类似的事情应该起作用。

def create
  monument = Monument.new(monument_params)
  if monument.save
    if router.present?
      router.monument = monument
      if router.save
        render json: monument, status: :ok
      else
        render json: router.errors, status: :unprocessable_entity 
      end
    else
      render json: monument, status: :ok
    end
  else
    render json: monument.errors, status: :unprocessable_entity 
  end
end

def permitted_params
  params.require(:monument).permit(:name,...,:router_id)
end

def monument_params
  permitted_params.except(:router_id)
end

def router_id
  permitted_params[:router_id]
end

def router
  if router_id
    Router.find router_id
  end
end

如果您的参数看起来像这样,您可能需要进行修改

params.require(:monument).permit(:name, {router_attributes: [:id]})

答案 1 :(得分:0)

您要描述的是沼泽标准has_one / belongs_to关系。

两个包含has_onebelongs_to的模型都可以管理关系,并且都具有用于更新关联的访问器。

假设您有这个...

class Monument
  belongs_to :router
end

class Router
  has_one :monument
end

然后这两种方法都将像您期望的那样完全起作用:

router.monument = <some monument>

monument.router = <some router>

答案 2 :(得分:0)

我最终会通过多种回答来解决我的问题,所以谢谢您的帮助。

我认为,如果我在router_id中添加monument_params,则Rails会选择具有相同名称的param并自行创建关联,但是看来Rails需要对象,而不是ID。所以这是我的解决方案:

  • 在我的纪念碑形式中,我可以选择一个路由器
<%= f.select :router_id, Router.all.collect { |s| [s.mac_address, s.id]}, {}, {class:"routerSelect", include_blank: true}  %>
  • 然后在我的monuments_controller中的创建和更新方法中,执行此操作:
def create
   @monument = Monument.new(monument_params)
   @monument.router = Router.find(params[:monument][:router_id])
   if @monument.save
   ...
end

def update
   if @monument.update(monument_params)
      @monument.router = Router.find(params[:monument][:router_id])
   ...
end

不是最好的解决方案,但它解决了我的问题。谢谢