Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails—一次具有单个值的自定义验证_Ruby On Rails_Validation - Fatal编程技术网

Ruby on rails Rails—一次具有单个值的自定义验证

Ruby on rails Rails—一次具有单个值的自定义验证,ruby-on-rails,validation,Ruby On Rails,Validation,所以我有两个模型: class Tag < ActiveRecord::Base has_many :event_tags attr_accessible :tag_id, :tag_type, :value end class EventTag < ActiveRecord::Base belongs_to :tag attr_accessible :tag_id, :event_id, :region end 我想做的是编写一个自定义验证,在其中检查以查看: 每个事件id只

所以我有两个模型:

class Tag < ActiveRecord::Base
has_many :event_tags
attr_accessible :tag_id, :tag_type, :value
end

class EventTag < ActiveRecord::Base
belongs_to :tag
attr_accessible :tag_id, :event_id, :region
end
我想做的是编写一个自定义验证,在其中检查以查看:

  • 每个事件id只有一个附加的“funLevel”标记类型,但可以有多个“通用”标记
例如:

t1 = EventTag.new(:tag_id => 1, :event_id =>777, :region => 'US')
t1.save  # success

t2 = EventTag.new(:tag_id => 2, :event_id =>777, :region => 'US')
t2.save  # failure 
         # because (event_id: 777) already has a tag_type of 
         # "funLevel" associated with it

t3 = EventTag.new(:tag_id => 4, :event_id =>777, :region => 'US')
t3.save  # success, because as (tag_id:4) is not "funLevel" type
我想出了一个丑陋的解决方案:

def cannot_have_multiple_funLevel_tag
  list_of_tag_ids = EventTag.where("event_id = ?", event_id).pluck(:tag_id)
  if(Tag.where("tag_id in ?", list_of_tag_ids).pluck(:tag_type).include? "funLevel")
    errors.add(:tag_id, "Already has a Fun Level Tag!")
end

作为rails的新手,有没有更好/更优雅/更便宜的方法?

您的数据结构化方式意味着内置的rails验证可能不会对您有很大帮助如果
funLevel
属性可由
EventTag
类直接访问,则可以使用如下内容:

# event_tag.rb
validate :tag_type, uniqueness: { scope: :event_id },
    if: Proc.new { |tag| tag.tag_type == "funLevel" }
(不幸的是,通过快速测试,您似乎无法验证虚拟属性的唯一性。)

如果没有这一点,您可能无法使用自定义验证。对自定义验证的明显改进(假设您希望在
EventTag
上进行验证)是不运行验证,除非
EventTag
funLevel
标记:

def cannot_have_multiple_funLevel_tag
  return unless self.tag.tag_type == "funLevel"
  ...
end

是的,由于没有对数据库的完全控制,我不得不使用我所拥有的。我很喜欢你的自定义验证器,我不认为我可以使用标记模型作为属性。是的,关联添加了一系列方法,使得访问关联模型和与关联模型交互非常容易。如果您有阅读的心情,请查看Rails指南,尤其是。
def cannot_have_multiple_funLevel_tag
  return unless self.tag.tag_type == "funLevel"
  ...
end