Rails通过两种模型进行验证

时间:2013-09-13 18:56:52

标签: ruby-on-rails ruby-on-rails-4

好吧,对如何解决这个问题感到困惑。

我有一个表格和两个型号。这是我的表格:

<% if @booking.errors.any? %>
  <% @booking.errors.full_messages.each do |msg| %>
    <p class="error"><%= msg %></p>
  <% end %>
<% end %>

<% if @guest.errors.any? %>
  <% @guest.errors.full_messages.each do |msg| %>
    <p class="error"><%= msg %></p>
  <% end %>
<% end %>

<%= form_for :booking, url: bookings_path do |f| %>
  <%= label_tag :email, "Guest's Email Address" %>
  <%= text_field_tag :email %>
  <%= f.label :nights, "Nights" %>
  <%= f.text_field :nights %>
  <%= f.label :nights, "People" %>
  <%= f.text_field :people %>
  <%= f.label :nights, "Arrival Date" %>
  <%= f.text_field :arrival %>
<% end %>

如您所见,电子邮件字段不是表单构建器的一部分。如果电子邮件尚不存在,则电子邮件地址将用于创建新的访客记录。一旦我有了客人的身份证,那么也可以预订记录。

以下是我的BookingController中创建操作的代码 - 表单提交给...

...

def create
  accommodation = current_user.accommodation
  guest = Guest.find_or_create_by(:email => params[:email])
  @booking = accommodation.bookings.new(post_params.merge(:guest_id => guest.id))

  if @booking.save
    flash[:success] = 'The booking has been added successfully.'  
    redirect_to :controller => 'bookings', :action => 'index'
  else
    render 'new'
  end
end

...

我确实意识到这个问题不是新问题,但我无法在我的问题的任何地方找到一个好的解决方案 - 我希望能够正确设置表格(如果需要)和验证使用这两个模型的所有字段。然后我需要显示错误消息。目前,我的电子邮件在验证期间被忽略,我不知道下一步该做什么。

任何帮助都非常感激。

2 个答案:

答案 0 :(得分:1)

在我看来,最简单的方法是在控制器本身验证电子邮件,并将任何验证错误添加到预订变量中。像这样:

def create
  accommodation = current_user.accommodation
  guest = Guest.find_or_create_by(:email => params[:email])
  @booking = accommodation.bookings.new(post_params.merge(:guest_id => guest.id))

  if @booking.save
    flash[:success] = 'The booking has been added successfully.'  
    redirect_to :controller => 'bookings', :action => 'index'
  else
    <% if params[:email].blank> %>
       @booking.errors.add(:email, "can't be blank.")
    <% end %>

    #You can do the same thing for whatever other validation errors you have

    render 'new'
  end
end

注意:我没有测试代码

这可能不是最好的方法,但它可以完成工作并且很容易。您可以使用accept_nested_attributes_for,但考虑到您只验证电子邮件,我觉得有点不必要。不过,如果你想以最干净的方式做到这一点,请坚持使用accept_nested_attributes_for。

修改

实际上,您的代码是正确的。你刚刚发了一个语法错误。您的guest虚拟机错误未显示的真正原因是您使用了局部变量而不是实例变量。试试这个:

@guest = Guest.find_or_create_by(:email => params[:email])

您的错误消息应与您已有的代码一起显示

<% if @guest.errors.any? %>
  <% @guest.errors.full_messages.each do |msg| %>
    <p class="error"><%= msg %></p>
  <% end %>
<% end %>

编辑2

为了避免在客人电子邮件无效的情况下保存预订实例,您可以执行以下操作:

if !@guest.errors.any? && @booking.save
    flash[:success] = 'The booking has been added successfully.'  
    redirect_to :controller => 'bookings', :action => 'index'
  else

因此,如果guest虚拟机有任何错误,if语句将在执行@ booking.save语句之前终止。

答案 1 :(得分:0)

您可以尝试进行交易。如果其中一个无效,rails将执行回滚,您可以渲染错误。

关注this question代码,看看是否有帮助。