Перезаписать все стандартные методы доступа в модели рельсов

0
 class Song < ActiveRecord::Base
    # Uses an integer of seconds to hold the length of the song

    def length=(minutes)
      write_attribute(:length, minutes.to_i * 60)
    end

    def length
      read_attribute(:length) / 60
    end
  end

Это простой пример с помощью rails api doc.

Возможно ли перезаписать все атрибуты для модели без перезаписывания каждого из них?

Теги:
activerecord
ruby-on-rails-3

2 ответа

0

Я не уверен в случае использования, когда это будет хорошей идеей. Тем не менее, все модели рельсов динамически присваивают свои свойства (предполагая, что они еще не находятся в классе). Ответ частично на ваш вопрос.

Вы можете переопределить методы read_attribute() и write_attribute(). Это применило бы ваши преобразования к каждому атрибуту независимо от того, был ли он написан аксессуаром или заполнен массовым в контроллере. Просто будьте осторожны, чтобы не мутировать важные атрибуты, такие как атрибут id.

Ruby имеет ярлык, который используется в коде rails, который может вам помочь. Это ключевое слово% w. % w создаст массив слов, основанный на символах внутри круглых скобок. Поскольку это массив, вы можете делать такие полезные вещи:

@excludes = %w(id, name)

def read_attribute name
    value = super
    if(not @excludes.member? name)
        value = value.to_i * 60
    end

    value
end

def write_attribute name, value
    if(not @excludes.member? name)
        value = value.to_i / 60
    end

    super
end

Это должно заставить вас начать. Существуют более продвинутые конструкции, такие как использование лямбда и т.д. Имейте в виду, что вы должны написать подробные модульные тесты, чтобы убедиться, что у вас нет непредвиденных последствий. Возможно, вам придется включить больше имен атрибутов в список исключений.

edit: (read | write) _attributes → (read | write) _attribute

  • 0
    Я думаю (читай | пиши) _attribute используется внутри AR. Распространены методы доступа, поэтому я думаю, что это более безопасно. Мне было бы интересно узнать, если это работает, хотя.
  • 0
    Это единственный механизм, который заботится обо всех путях управления атрибутами. Т.е. когда вы делаете @post = Post.new (params [: post]), редактируйте атрибут напрямую или делайте @ post.update_attributes (params [: post]). По этой причине раньше был способ делать такие вещи. Не уверен, изменился ли он в более новых версиях.
0

Вы ищете что-то подобное? Не знаю, почему вы хотели бы это сделать, но здесь вы идете:)

class Song < ActiveRecord::Base

  self.columns_hash.keys.each do |name|
    define_method :"#{name}=" do
      # set
    end

    define_method :"#{name}" do
      # get
    end

    # OR

    class_eval(<<-METHOD, __FILE__, __LINE__ + 1)
       def #{name}=
         # set
       end

       def #{name}
         # get
       end
    METHOD

  end

end
  • 0
    В данном случае у меня есть таблица с полями, в которой хранится интернационализированный контент (title, title_portuguse, title_english), и я хочу изменить поведение этих методов для отображения данных в соответствии с языком без изменения представлений.
  • 1
    Вы можете взглянуть на плагин globalize2, который позволяет использовать локализованные атрибуты, такие как content.title . Мне не очень нравится их подход. По сути, они создают таблицу content_translations, где все переведенные атрибуты являются столбцами, а затем загружают записи перевода, соответствующие I18n.locale. Затем content.title становится прокси для content.translation(locale).title . В моем следующем локализованном приложении я пропущу плагин и просто создаю эти таблицы вручную и создаю модель ContentTranslation. Это более понятно, и вы знаете, с каким объектом вы имеете дело.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню