Ruby on rails 如何在Rails中批量验证关联

Ruby on rails 如何在Rails中批量验证关联,ruby-on-rails,Ruby On Rails,我有以下情况: 我的一个模型,我们称之为“Post”,它有多个相关的模型和图像 这些图像中的一个(且只有一个)可以是其帖子的关键图像(在图像模型上表示为布尔标志,并通过对使用帖子作为其作用域的图像模型进行验证来强制执行) 当然,当我想更新主映像标志时,一个映像模型的键标志被设置为true,验证失败,因为还有另一个映像的键标志被设置为true 我知道,这东西需要在Post模型上转换为关联,它链接到关键图像,但是有没有一种方法可以在Rails中批量验证关联 您的看法是,是将关键图像作为Post模型上

我有以下情况:

我的一个模型,我们称之为“Post”,它有多个相关的模型和图像

这些图像中的一个(且只有一个)可以是其帖子的关键图像(在图像模型上表示为布尔标志,并通过对使用帖子作为其作用域的图像模型进行验证来强制执行)

当然,当我想更新主映像标志时,一个映像模型的键标志被设置为true,验证失败,因为还有另一个映像的键标志被设置为true

我知道,这东西需要在Post模型上转换为关联,它链接到关键图像,但是有没有一种方法可以在Rails中批量验证关联


您的看法是,是将关键图像作为Post模型上的单独关联,还是使用布尔标志?

您可以在Post模型中执行此操作:

# Post.rb
has_many :images, :conditions => ['primary = ?', false]
has_one :primary_image, :conditions => ['primary = ?', true]
如果要更改主映像,请执行以下操作:

# Post.rb
def new_primary_image(image_id)
    primary_image.primary = false
    Image.find(image_id).primary = true
end

有一个简单的解决方案,但需要一些信任:

  • 删除验证“是否只有一个主映像?”
  • 通过添加过滤器确保只有一个主映像
最大的好处是,您不必检查控制器或post模型中的任何内容。只需拍摄一张图像,将
is_primary
设置为true并保存即可

因此,设置可能如下所示:

class Post < ActiveRecord::Base
  has_many  :images 

  # some sugar, @mypost.primary_image gets the primary image
  has_one   :primary_image, 
            :class_name => "Image", 
            :conditions => {:is_primary => true }
end

class Image < ActiveRecord::Base
  belongs_to :post

  # Image.primary scopes on primary images only
  scope :primary, where(:is_primary => true)

  # we need to clear the old primary if:
  # this is a new record and should be primary image
  # this is an existing record and is_primary has been changed to true

  before_save :clear_primary, 
              :if => Proc.new{|r| (r.new_record? && r.is_primary) || (r.is_primary_changed? && r.is_primary) }

  def clear_primary
    # remove old primary image
    Image.update_all({:is_primary => false}, :post_id => self.post_id)
  end
end
class Post“Image”,
:conditions=>{:is_primary=>true}
结束
类映像true)
#如果出现以下情况,我们需要清除旧的主设备:
#这是一个新记录,应该是主映像
#这是一条现有记录,并且is_primary已更改为true
保存前:清除\u主,
:if=>Proc.new{r|(r.new|u record?&r.is|u primary){124;(r.is|u primary|u changed?&r.is|u primary)}
def清除_主
#删除旧的主映像
Image.update_all({:is_primary=>false},:post_id=>self.post_id)
结束
结束
编辑:

这在任何情况下都会起作用——为什么

  • 只有在所有验证成功时才会调用before\u save
  • 整个保存被包装在一个事务中,这意味着如果清除主映像或保存映像本身失败,所有内容都将回滚到其原始状态

哇,谢谢你!唯一的问题是,我需要跳过上次update_属性调用中的回调,这在Rails 3中似乎不再受支持。您好,我还没有意识到在Rails 3中update_属性已经更改。我更改了代码,使其也能与Rails 3一起使用。我如何通过嵌套形式的单选按钮集设置主映像?我尝试了image\u form.radio\u button(:is\u primary,true),但是rails给每个单选按钮赋予了不同的名称,从而将每个单选按钮分成了自己的组。