代码之家  ›  专栏  ›  技术社区  ›  auralbee

如何避免保存属性可以为空的空白模型

  •  1
  • auralbee  · 技术社区  · 14 年前

    我有两个与哈布特姆协会的模特,比如书和作家。

    class Book
      has_and_belongs_to_many :authors
    end
    
    class Author
      has_and_belongs_to_many :books
    end
    

    作者有一组属性(例如名字、姓氏、年龄),这些属性都可以为空(参见验证)。

    validates_length_of :first_name, :maximum => 255, :allow_blank => true, :allow_nil => false
    

    在Books_控制器中,我执行以下操作,一步将所有作者附加到一本书:

    @book = Book.new(params[:book])
    @book.authors.build(params[:book][:authors].values)
    

    我的问题是:什么是避免保存作者的最简单方法?哪些字段都是空白的,以防止数据库中出现过多的“噪音”?

    目前,我做以下工作:

    validate :must_have_some_data
    
    def must_have_some_data
      empty = true
      hash = self.attributes
      hash.delete("created_at")
      hash.delete("updated_at")
      hash.each_value do |value|
        empty = false if value.present?
      end
    
      if (empty)
        errors.add_to_base("Fields do not contain any data.")
      end
    end
    

    也许有一种更优雅的,像铁轨一样的方法。

    谢谢。

    3 回复  |  直到 13 年前
        1
  •  1
  •   fl00r    14 年前

    稍微短一点

    def must_have_some_data
      hash = self.attributes
      hash.delete("created_at")
      hash.delete("updated_at")
      errors.add_to_base("Fields do not contain any data.") if hash.select{|k,v| !v.blank?}.empty?
    end
    

    实际上,我认为,你应该验证,而不是 全部的 属性,但仅限于您希望存在的特定属性

    def must_have_some_data
      valid_fields = ['first_name', 'second_name', 'last_name']
      errors.add_to_base("Fields do not contain any data.") if self.attributes.select{|k,v| valid_fields.include? k and !v.blank?}.empty?
    end
    

    UPD 在这种情况下,您还应该检查控制器中的authors字段。所以您的作者字段必须在单独的参数组中。

    def create
      book = Book.new(params[:book])
      params[:authors].each do |author|
        book.authors.build(author) unless author.attributes.each{|k,v| !v.blank?}.empty?
      end
      if book.save
        ...
      end
    end
    
        2
  •  1
  •   inkdeep    14 年前

    把这个放到书本模型中:

    validates_associated :authors, :on => :create
    

    除非您希望无效的作者对象被静默忽略,但不保存。那么,当前的解决方案是解决问题的一种方法。

    您使用的是什么版本的Rails? accepts_nested_attributes_for 在这种情况下可能有用。

        3
  •  1
  •   Adam Trhon    13 年前

    您可以更改一行:)

    def create
      book = Book.new(params[:book])
      params[:authors].each do |author|
        # book.authors.build(author) unless author.attributes.each{|k,v| !v.blank?}.empty?
        book.authors.build(author) unless author.all? {|key,val| val.empty?}
      end
      if book.save
        ...
      end
    end