如何为has_one关联创建视图?

时间:2011-04-06 20:41:09

标签: ruby-on-rails activerecord

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

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关联是实现此目的的唯一方法吗?

我迷失了,我觉得我在这里缺少一些非常基本的东西。

3 个答案:

答案 0 :(得分:8)

您应该使用engine_id

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

<强> UPD

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

Checkout api: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 %>

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

  1. fl00r 说的那样做。

  2. optional: true添加到班级说明

  3.   

    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. 修改
    2. <%= 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. 修改您的EngineController
      2. 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