ruby-on-rails - rails 验证嵌套属性

标签 ruby-on-rails validation

艺术家有很多事件。事件有很多艺术家。这两个模型之间的连接称为性能。

目前事件表单创建表演,但为添加到事件表单的每个艺术家创建一个新艺术家。

我希望事件表单能够:

  1. 验证一个艺术家只能被添加到一个事件中一次
  2. 如果 Artists 表中已存在同名的 Artist,则在连接表(Performances)中创建关联,但不要创建另一个 Artist
  3. 如果不存在同名艺术家,请创建它和表演

我已尝试将“validates_uniqueness_of :name”添加到 artist.rb,但这会阻止事件被保存。如果加入(表演)不存在,则应创建它;如果艺术家不存在,则应创建它,但艺术家的存在不应阻止创建加入/关联。

事件.rb

validates_presence_of :name, :location
has_many :performances, :dependent => :destroy
has_many :artists, :through => :performances
accepts_nested_attributes_for :artists, :reject_if => proc {|a| a['name'].blank?},     :allow_destroy => true

艺术家.rb

has_many :performances
has_many :events, :through => :performances

性能.rb

belongs_to :artist
belongs_to :event

events_controller.rb

def create
  @event = Event.new(params[:event])

  respond_to do |format|
    if @event.save
      flash[:notice] = 'Event was successfully created.'
      format.html { redirect_to(admin_events_url) }
      format.xml  { render :xml => @event, :status => :created, :location => @event }
    else
      format.html { render :action => "new" }
      format.xml  { render :xml => @event.errors, :status => :unprocessable_entity }
    end
  end
end

_form.html.erb

<% form_for([:admin,@event]) do |f| %>
<p>
    <%= f.label :name %><br />
    <%= f.text_field :name %>
</p>
<p>
    <%= f.label :location %><br/>
    <%= f.text_field :location %>
</p>
<p>
    <%= f.label :date %><br />
    <%= f.date_select :date %>
</p>
<p>
    <%= f.label :description %><br />
    <%= f.text_area :description %>
</p>
<% f.fields_for :artists do |builder| %>
    <%= render 'artist_fields', :f => builder %>
<% end %>
<p><%= link_to_add_fields "Add Artist", f, :artists %></p>
<p>
    <%= f.submit 'Submit' %> <%= link_to 'Cancel', admin_events_path %>
</p>
<% end %>

artist_fields.html.erb

<p class="fields">   
<%= f.label :name, "Artist"%><br/>
<%= f.text_field :name %>
<%= link_to_remove_fields "remove", f %>
</p>

最佳答案

您真的应该看看这些 Railscast:

  1. 不要创造各种各样的艺术家。只需使用现有的(或根据需要创建):

    http://railscasts.com/episodes/167-more-on-virtual-attributes

  2. 您还可以检查这些嵌套形式的 railscasts(第一部分链接在这里):

    http://railscasts.com/episodes/196-nested-model-form-part-1

  3. 对于验证,您可以只使用一个方法为您执行事件中仅执行一次的验证。类似的东西(在 Event.rb):

    validate :artists_appear_just_once
    
    private
    def artists_appear_just_once
      self.artists.size == self.artists.uniq.size
    end
    

或者,您可以使用 uniq 使艺术作品默认只出现一次!保存前的方法。只需调用 before_save Hook 并处理艺术家数组...

 before_save :make_artists_unique

 private
 def make_artists_unique
   artists.uniq!
 end

希望我得到了你需要的东西:P

关于ruby-on-rails - rails 验证嵌套属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3077290/

相关文章:

ruby-on-rails - 限制 Sidekiq 中每个队列的工作人员数量

sql - 是否可以使用范围方法生成 SQL `OR` 子句?

ruby-on-rails - Rails - 装饰器内部验证

ruby-on-rails - 如何编辑旧的 Rails 迁移以添加引用?

java - 如何在没有 xml 的情况下验证使用 @ManagedProperty 注入(inject)的 bean 属性?

ruby-on-rails - 如何告诉TextMate忽略 “Go to File”中我的Katz的Bundler文件夹?

node.js - 如何使用 AdonisJS 验证号码

javascript - 为什么我的 javascript 不验证我的 html 表单?

javascript - 视障人士无法访问 Asp 验证摘要

asp.net-mvc - ASP.NET MVC3 自定义不显眼的客户端验证不会阻止 Ajax 表单发布