开发者

How to avoid saving a blank model which attributes can be blank

I have two models with a HABTM association, let´s say book and author.

class Book
  has_and_belongs_to_many :authors
end

class Author
  has_and_belongs_to_many :books
end

The author has a set of attributes (e.g. first-name,last-name,age) that can all be blank (see validation).

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

In the books_controller, I do the following to append all authors to a book in one step:

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

My question: What would be the easiest way to avoid the saving of authors which fields are all blank to prevent too much "noise" in the database?

At the moment, I do the follow开发者_如何学JAVAing:

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

Maybe there is an more elegant, Rails-like way to do that.

Thanks.


A little shorter

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

Actually I think, that you should validate not all attributes, but just specific attributes, which you are expecting to presence

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 In this situation you should also check authors fields in controller. So your authors fields must be in separate params group.

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


put this in the books model:

validates_associated :authors, :on => :create

Unless you want invalid author objects to be silently ignored but not saved. Then the current solution is one way of solving it.

What version of rails are you using? accepts_nested_attributes_for might be of use in this situation.


You can change one line :)

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜