【问题标题】:How do I create the view for the has_one association?如何为 has_one 关联创建视图?
【发布时间】:2011-07-31 04:03:19
【问题描述】:

所以,想象一下我有这个模型:

class Car
  has_one :engine
end

以及发动机型号:

class Engine
  belongs_to :car
end

当我向用户展示表单以便他可以创建一辆新车时,我只想让他从一个可用的引擎中进行选择(可用的引擎将在 select 中,由collection_select)。问题是,如果我这样构建字段:

<%= f.collection_select :engine,Engine.all,:id,:name %>

当我尝试保存它时,我会得到一个 AssociationTypeMismatch,说它需要一个引擎,但它收到了一个字符串。

这样可以吗?

def create
  car = Car.new(params[:car])
  engine = Engine.find(params[:engine])
  car.engine = engine
  if car.save
     # redirect somewhere
  else
     # do something with the errors
  end
end

我一直觉得诸如将引擎与汽车关联起来之类的事情是由 Rails 自动完成的,但我不知道如何让他这样做。

切换has_onebelongs_to 关联是实现此目的的唯一方法吗?

我迷路了,我觉得我在这里遗漏了一些非常基本的东西。

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    你应该使用engine_id

    <%= f.collection_select :engine_id, Engine.all, :id, :name %>
    

    UPD

    至于Engine 不属于Car,所以你应该在这里使用嵌套属性。此截屏视频对您非常有用:

    结帐接口:http://apidock.com/rails/ActiveRecord/NestedAttributes/ClassMethods/accepts_nested_attributes_for

    简介:

    class Car
      has_one :engine
      accepts_nested_attributes_for :engine
    end
    

    并以您的形式:

    <%= form_for @car ... do |f| %>
      ...
      <%= f.fields_for :engine do |b| %>
        <%= b.collection_select :id, Engine.all, :id, :name %>
        ...
      <% end %>
      ...
    <% end %>
    

    【讨论】:

    • 那么,即使 Engine 是持有关联的那个,我也需要在 Car 模型中有一个 engine_id 字段?
    • 不! :) 你应该在这里使用accepts_nested_attributes_for。我会更新我的答案
    • 当我保存汽车时,我也可以使用.engine 方法访问关联的引擎,对吗?
    • 但是如何从collection_select 填充引擎?我必须在fields_for 中写:engine_id 吗?或者只是id
    • fields for 正在寻找存在的引擎,所以如果你没有任何 for @car - 什么都不会出现,你应该初始化它。喜欢f.fields_for :engine, @car.build_ingine do |f| ...
    【解决方案2】:

    对 Kyle 先前回答的回应——我喜欢这种简单的方法,但是我必须按如下方式更改它以适用于我的应用程序(我在 Rails 3.2.13 中)。要点是地图需要返回一个数组——所以我认为这可能是一个错字,将两个数组用逗号分隔。我还将对 id 属性的字符串引用更改为符号,但我不确定这是必不可少的还是只是另一个选项。在某种程度上,这对我有用。

    <%= f.select :class_location_id, ClassLocation.all.map {|e| [e.place, e.id]} %>
    

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题,这是我的解决方案(基于 fl00r 答案的改进):

      1. 按照fl00r所说的去做。

      2. 在类描述中添加optional: true

      class Engine belongs_to :car, optional: true end

      更多信息请访问:http://blog.bigbinary.com/2016/02/15/rails-5-makes-belong-to-association-required-by-default.html

      1. 修改
      <%= f.fields_for :engine do |b| %>
        <%= b.collection_select :id, Engine.all, :id, :name %>
        ... 
      <% end %>
      

      <%= f.fields_for :engine, :include_id => false do |b| %>
        <%= b.collection_select :id, Engine.all, :id, :name %>
        ...
      <% end %>
      

      更多信息请访问:Stop rails from generating hidden field for fields_for method

      1. 修改引擎控制器

      3.1。修改

      def car_params
        params.require(:car).permit(:name)
      end
      

      def car_params
        params.require(:car).permit(:name, engine_attributes: [:id, :name])
      end
      

      更多信息请访问:Rails 4 Nested Attributes Unpermitted Parameters

      3.1。添加函数(私有)

      def set_engine
      
        engine_id = car_params[:engine_attributes][:id]
      
        @engine = Engine.find(engine_id)
      
        @car.engine = @engine
      
        @car.save
      end
      

      3.2。修改EngineController#update

        def update
          respond_to do |format|
      
            if @car.update(car_params)
              format.html { redirect_to @car, notice: 'Car was successfully updated.' }
              format.json { render :show, status: :ok, location: @car }
            else
              format.html { render :edit }
              format.json { render json: @car.errors, status: :unprocessable_entity }
            end
          end
        end
      

        def update
          respond_to do |format|
      
            if set_engine && @car.update(car_params)
              format.html { redirect_to @car, notice: 'Car was successfully updated.' }
              format.json { render :show, status: :ok, location: @car }
            else
              format.html { render :edit }
              format.json { render json: @car.errors, status: :unprocessable_entity }
            end
          end
        end
      

      【讨论】:

        猜你喜欢
        • 2017-11-12
        • 2011-04-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多