виртуальные атрибуты rails не будут считываться из формы для отправки - PullRequest
1 голос
/ 07 января 2012

Я пытаюсь реализовать модель маркировки рельсов, как описано в Railscast # 167 Райана Бэйта. http://railscasts.com/episodes/167-more-on-virtual-attributes

Это отличная система для использования. Тем не менее, я не могу получить форму для отправки tag_names в контроллер. Определение тэгов:

 def tag_names
   @tag_names || tags.map(&:name).join(' ')
 end

К сожалению, @tag_names никогда не назначается при отправке формы в моем случае. Я не могу понять, почему. Так что всегда по умолчанию это tags.map (&: name) .join (''). Это означает, что я не могу создавать Статьи, потому что их тэгов нет, и я также не могу редактировать эти тэги на существующих. Кто-нибудь может помочь?

1 Ответ

1 голос
/ 07 января 2012

Короче говоря, в вашем классе отсутствует сеттер (или в Ruby lingo, создателе атрибутов). Существует два способа определения сеттера и обработки преобразования строки разделенных пробелами имен тегов в объекты тегов и их сохранения в базе данных.

Раствор 1 (раствор Райана)

В вашем классе определите свой установщик, используя метод attr_writer Ruby, и преобразуйте строку имен тегов (например, "tag1 tag2 tag3") в объекты Tag и сохраните их в базе данных в обратном вызове после сохранения. Вам также понадобится метод получения, который преобразует массив объекта Tag для статьи в строковое представление, в котором теги разделены пробелами:

class Article << ActiveRecord::Base
  # here we are delcaring the setter
  attr_writer :tag_names

  # here we are asking rails to run the assign_tags method after
  # we save the Article
  after_save :assign_tags

  def tag_names
    @tag_names || tags.map(&:name).join(' ')
  end

  private

  def assign_tags
    if @tag_names
      self.tags = @tag_names.split(/\s+/).map do |name|
        Tag.find_or_create_by_name(name)
      end
    end
  end
end

Решение 2. Преобразование строки имен тегов в Tag объекты в установщике

class Article << ActiveRecord::Base
  # notice that we are no longer using the after save callback
  # instead, using :autosave => true, we are asking Rails to save
  # the tags for this article when we save the article
  has_many :tags, :through => :taggings, :autosave => true

  # notice that we are no longer using attr_writer
  # and instead we are providing our own setter
  def tag_names=(names)
     self.tags.clear
     names.split(/\s+/).each do |name|
       self.tags.build(:name => name)
     end
  end

  def tag_names
    tags.map(&:name).join(' ')
  end
end
...