Rails 4嵌套表单,保存belongs_to问题

时间:2016-04-08 18:11:01

标签: ruby-on-rails-4 nested-forms nested-attributes strong-parameters belongs-to

我正在开发一个新的Rails 4应用程序,并且很难让所有部分正确地协同工作。我有一个模型(示例)与另一个模型(lat_long)的belongs_to关联,我试图从示例视图(编辑默认生成的视图)对两者进行CRUD操作。问题是lat_long可能是空白的;一切正常,如果它不是,但是当它在模型中进行验证时,所以我认为它试图保存一个空白lat_long而不是将其设置为零。更新和编辑是问题。

以下是代码中的相关部分:
机型:

class Sample < ActiveRecord::Base
  belongs_to :lat_long
  accepts_nested_attributes_for :lat_long 
end

class LatLong < ActiveRecord::Base
  validates_each :west_longitude do |record, attr, value|
    record.errors.add attr, "must be within range." if (value < 110.0 or value > 115.0)   
  end   
  validates_each :north_latitude do |record, attr, value|
    record.errors.add attr, "must be within range." if (value < 38.0 or value > 42.0)   
  end 
end
编辑中使用的

samples / _form.html.erb和new:

<%= form_for(@sample) do |f| %>
    <%= f.fields_for :lat_long do |g| %>
        <div class="field">
          <%= g.label :north_latitude %><br>
          <%= g.text_field :north_latitude %>
        </div>
        <div class="field">
          <%= g.label :west_longitude %><br>
          <%= g.text_field :west_longitude %>
        </div>
    <% end %>
<% end %>

samples_controller.rb:

class SamplesController < ApplicationController
 # GET /samples/new
  def new
    @sample = Sample.new
    @sample.build_lat_long
    @sample.build_trap
  end
  # GET /samples/1/edit
  def edit
    @sample.lat_long || @sample.build_lat_long
    @sample.trap || @sample.build_trap
  end
  # POST /samples
  # POST /samples.json
  def create
    @sample = Sample.new(sample_params)
    puts sample_params
    respond_to do |format|
      if @sample.save
        format.html { redirect_to @sample, notice: 'Sample was successfully created.' }
        format.json { render :show, status: :created, location: @sample }
      else
        format.html { render :new }
        format.json { render json: @sample.errors, status: :unprocessable_entity }
      end
    end
  end
  # PATCH/PUT /samples/1
  # PATCH/PUT /samples/1.json
  def update
    respond_to do |format|
      if @sample.update(sample_params)
        format.html { redirect_to @sample, notice: 'Sample was successfully updated.' }
        format.json { render :show, status: :ok, location: @sample }
      else
        format.html { render :edit }
        format.json { render json: @sample.errors, status: :unprocessable_entity }
      end
    end
  end
  def sample_params
    params.require(:sample).permit(...,
                                   lat_long_attributes: [:id,
                                   :west_longitude, :north_latitude])
  end
end

我可以在更新前对控制器进行检查,但这是正确的做法吗?它“感觉”应该有一种让Rails处理这个问题的方法,但是看看很多StackOverflow问题并且文档没有给我任何想法。大多数例子都使用has_one或has_many,所以我不知道这是不是问题?根据{{​​3}},belongs_to与accepts_nested_attributes_for一起使用是新的,所以也许它根本没有为此设置。

我想知道这种情况的最佳做法是什么,最“Railsy”要做的事情。哦,我想我已经包含了所有相关的代码,但是如果还有什么需要让我知道的话。

1 个答案:

答案 0 :(得分:1)

我做的事情如下:

class Sample < ActiveRecord::Base
  belongs_to :lat_long
  accepts_nested_attributes_for :lat_long, reject_if: proc { |attributes| attributes['west_longitude'].blank? && attributes['north_latitude'].blank? }
end

class LatLong < ActiveRecord::Base
  validates :west_longitude, numericality: { greater_than_or_equal_to: 110,
                             less_than_or_equal_to: 115,
                             message: "must be within range" },
                             allow_nil: true

  validates :north_latitude, numericality: { greater_than_or_equal_to: 38,
                             less_than_or_equal_to: 42,
                             message: "must be within range" },
                             allow_nil: true
end