Как избежать сохранения пустой модели, атрибуты которой могут быть пустыми - PullRequest
1 голос
/ 20 апреля 2010

У меня есть две модели с ассоциацией HABTM, скажем, книга и автор.

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_controller я делаю следующее, чтобы добавить всех авторов в книгу за один шаг:

@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

Может быть, есть более элегантный, подобный Rails способ сделать это.

Спасибо.

Ответы [ 3 ]

1 голос
/ 21 апреля 2010

поместите это в модель книги:

validates_associated :authors, :on => :create

Если вы не хотите, чтобы недействительные авторские объекты игнорировались, но не сохранялись. Тогда текущее решение является одним из способов его решения.

Какую версию рельсов вы используете? accepts_nested_attributes_for может быть полезно в этой ситуации.

1 голос
/ 14 ноября 2011

Вы можете изменить одну строку:)

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
1 голос
/ 20 апреля 2010

немного короче

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 В этой ситуации вы также должны проверить авторские поля в контроллере. Поэтому поля ваших авторов должны находиться в отдельной группе параметров.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...