【问题标题】:Ruby: create a parent only if at least 1 child existsRuby:仅当至少存在 1 个孩子时才创建父母
【发布时间】:2013-05-14 03:50:01
【问题描述】:

Repairs 和 RepairItems 之间存在父子关系。

修复必须至少有 1 个 RepairItem 才能保存。我制作了一个嵌套(简单)表单来创建一个修复并显示 3 个空白修复项。

我正在尝试确定如何确保一个 Repair 至少输入了 1 个 repair_item 以允许用户保存该修复。否则我需要提示用户至少输入1个repair_item才能保存修复..

谁能指出我正确的验证方向,以便用户在没有输入任何修复项目的情况下无法保存修复?谢谢

class Repair < ActiveRecord::Base
attr_accessible :repair_id, :repairer_id, :fault_num, :vehicle_id, :date_reported, :date_closed, :hours_open, :mileage_open, :reported_to, :reported_by,
   :repair_items_attributes

   belongs_to :vehicle
   belongs_to :repairer

   has_many :repair_items, :dependent => :destroy

   validates_presence_of :vehicle_id
   validates_associated :repair_items

   accepts_nested_attributes_for :repair_items, :reject_if => lambda { |a| a[:repair_type_id].blank? }, :allow_destroy => true

end

class RepairItem < ActiveRecord::Base
attr_accessible :repair_id, :problem, :solution, :repair_type_id, :priority, :repairer_id, :invoice, :cost, :tax,
 :item_state_id, :mileage_closed, :hours_closed, :date_closed

   belongs_to :repair
   belongs_to :repairer
   belongs_to :repair_type
   belongs_to :item_state

   #validates_presence_of :repair_id
   validates_presence_of :repair_type_id   

   scope :open, where(:item_state_id => 1)
   scope :monitor, where(:item_state_id=> 2)
   scope :deferred, where(:item_state_id => 3)
   scope :closed, where(:item_state_id => 4)
   scope :cancelled, where(:item_state_id => 5)

end

class RepairsController < ApplicationController

    before_filter :authorise
    layout :resolve_layout

def index
    #status = 1
    @repairItems = RepairItem.open
end

def monitor
    #status = 2
    @repairItems = RepairItem.monitor
end

def deferred
    #status = 3
    @repairItems = RepairItem.deferred
end

def closed
    #status = 4
    @repairItems = RepairItem.closed
end

def cancelled
    #status = 5
    @repairItems = RepairItem.cancelled
end

def new
    @repair = Repair.new
    3.times { @repair.repair_items.build }
end

def create
    # Instantiate a new object using form parameters
    @repair = Repair.new(params[:repair])

    # Save the object
if @repair.save
    # If the save suceeds, redirect to the list action

    redirect_to(repairs_path, :notice => 'Repair Created.')

else
  # If the save fails, redisplay the form so user can fix problems
  render :action => :new
end

end

<%= simple_form_for( @repair, :defaults => { :disabled => @current_user.read_only, :input_html => { :class => "span10" } }) do |f| %> 

<fieldset>      
  <!-- This will display some text in red at the top of the form telling the user -->
  <%= f.error_notification %>
  <div class="st-row-fluid">

    <div class="span2">
      <%= f.association :vehicle, label_method: :fleet_num, value_method: :id, include_blank: true, label: 'Vehicle'%>
    <p>Current Kms</p>
    <p>Current Hours</p>
    <p class="muted">Warranty Expires</p>
    <p class="muted">Contract Maintenance</p>

  </div>

      <div class="span2">
        <%= f.input :date_reported, :as => :date_picker, :input_html => { :class => "span10 st-datepicker"} %>
        <%= f.input :mileage_open, :label => "Km/Miles" %>
        <%= f.input :hours_open %>
      </div>
    <div class="span2">
      <%= f.input :fault_num %>
      <%= f.input :reported_to %>
      <%= f.input :reported_by %>
    </div>

  </div>

<div class="row-fluid">
  <h4> Items</h4>
  <%= f.simple_fields_for :repair_items do |p| %>
     <table class="table table-condensed">
        <tr>
           <%= render "repair_items", :p => p %>
       </tr>
    </table>
  <% end %>
</div>  


    <%= f.error :base %>
    <div class="st-form-actions">
       <% if @current_user.read_only == false %>
        <%= f.submit nil, :class => 'btn btn-success pull-right' %>
       <% end %>
      <%= link_to 'Cancel', repairs_path, :class => 'btn btn-danger pull-right' %>
    </div>
</fieldset>
  <% end %>

部分

<td><%= p.association :repair_type, label_method: :repair_type_label, value_method: :id, include_blank: true, label: 'Repair Type'%></td>
<td><%= p.input :problem %></td>
<td><%= p.input :solution %></td>
<td><%= p.input :priority %></td>
<td><%= p.association :repairer, label_method: :rep_name, value_method: :id, include_blank: true, label: 'Repairer'%></td>
</tr>
<tr>
<td><%= p.input :invoice %></td>
<td><%= p.input :cost %></td>
<td><%= p.input :tax %></td>
<td><%= p.input :date_closed, :as => :date_picker, :input_html => { :class => "span10 st-datepicker"} %></td>
<td><%= p.input :mileage_closed, :label => "Km/Miles" %></td>
<td><%= p.input :hours_closed %></td>
<td><%= p.association :item_state, label_method: :state_label, value_method: :id, label: 'Status', :default => 1 %></td>

【问题讨论】:

  • 我们可以尝试一下吗?还是代码?

标签: ruby-on-rails ruby oop validation inheritance


【解决方案1】:

在修复中使用validates_associated :repair_items 来验证修复项。该操作必须使用repair.RepairItem.build 构造修复项目,以便在尝试保存修复之前将这些项目与修复相关联。修复先于修复项目构建,但repair_items 会阻止关联的修复保存。

【讨论】:

  • 感谢 isaach1000,我已将其添加到修复模型中,但它仍然让父母在没有孩子的情况下通过
  • 上面的代码似乎只检查修复项目的修复 ID。如果正确,则留空的维修项目将被视为有效,维修将保存。
猜你喜欢
  • 1970-01-01
  • 2016-11-25
  • 2011-02-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多