`find_or_create_by`方法正在跳过模型验证。为什么?

时间:2012-04-19 16:05:04

标签: ruby-on-rails ruby-on-rails-3 activerecord

我的Tag模型对属性name有一些验证。在所有其他情况下,它都很好。但是当我以这种方式致电find_or_create_by_name时:

# The last value of this string (by coma) is empty.
# So this record should not be saved.
tags_line = 'ruby, javascript, '

tags_line.split(',').each do |tag_name|
  tag = Tag.find_or_create_by_name(tag_name.strip) do |new_tag|
    new_tag.update_attribute :user_id, member.user.id
  end

  # Just append tag to this model
  # through `has_and_belongs_to_many :tags`
  tags << tag if tag
end

但是这个空标签甚至被保存了。那么,这段代码可能有问题吗?

注意:当我删除该块时,它可以正常工作:

...
tags_line.split(',').each do |tag_name|
  # This way, invalid tag will not be created.
  tag = Tag.find_or_create_by_name(tag_name.strip)
  tags << tag if tag
end

3 个答案:

答案 0 :(得分:1)

问题是由于属性:name在模型中受到保护。所以,正如Rails Doc所说:

  

如果相同,可以使用相同的动态查找器样式来创建对象   尚不存在。这个动态查找器被调用   find_or_create_by_并返回该对象(如果已存在)   否则创建它,然后返回它。 受保护的属性不会   除非它们是在一个区块中给出的。

固定代码是......

tags_field.split(',').each do |tag_name|
  tag_name.strip!

  tag = General::Tag.find_or_create_by_name(tag_name) do |new_tag|
    # :name is attr_protected
    new_tag.name = tag_name
    new_tag.user_id = member.user.id
  end

  tags << tag if tag
end

答案 1 :(得分:1)

或者你可以使用以下类型的方法链接,而不是跳过块

tags_field.split(',').each do |tag_name|
  tag_name.strip!

  tag = General::Tag.find_or_create_by_name_and_user_id(tag_name, member.user.id)

  tags << tag if tag
end

答案 2 :(得分:0)

在最后一次迭代中,标签有字符串'',即空格。

尝试

 tags << tag unless tag.strip.blank?

只要您使用Ruby On Rails,我怀疑它是空白的?是一个rails扩展。 其他

 tags << tag unless tag.strip.empty?

编辑:

update_attribute不会运行验证。见this