Nano Hash - криптовалюты, майнинг, программирование

Какова ценность self в модели Rails и почему недоступны очевидные методы экземпляра?

У меня есть собственный метод доступа в моем приложении rails 3.1.6, который присваивает значение атрибуту, даже если значение отсутствует. Атрибут my_attr представляет собой сериализованный хэш, который должен быть объединен с заданным значением, если не указано пустое значение , и в этом случае для текущего значения будет установлено пустое значение. (Добавлены проверки, чтобы убедиться, что значения такие, какими они должны быть, но они удалены для краткости, поскольку они не являются частью моего вопроса.) Мой установщик определяется как:

def my_attr=(new_val)
  cur_val = read_attribute(:my_attr)  #store current value

  #make sure we are working with a hash, and reset value if a blank value is given
  write_attribute(:my_attr, {}) if (new_val.nil? || new_val.blank? || cur_val.blank?)

  #merge value with new 
  if cur_val.blank?
    write_attribute(:my_attr, new_val)
  else
    write_attribute(:my_attr,cur_val.deep_merge(new_val))
  end
  read_attribute(:my_attr)
end

Этот код хорошо работает как есть, но не тогда, когда я использую self.write_attribute(). Затем я получаю следующую ошибку:

NoMethodError:
       private method `write_attribute' called for #<MyModel:0x00000004f10528>

Мои вопросы таковы: кажется более логичным иметь write_attribute доступным для экземпляра, так почему же он доступен только для класса, а не для экземпляра? Чего-то не хватает в моих фундаментальных знаниях я в Ruby или Rails (или в обоих)?

12.07.2012

Ответы:


1

Внутри метода экземпляра self находится этот экземпляр. Однако, когда вы вызываете метод с явным приемником, срабатывает управление видимостью ruby ​​и запрещает вызов закрытого метода.

class Foo
  def implicit
    self # => #<Foo:0x007fc019091060>
    private_method
  end

  def explicit
    self # => #<Foo:0x007fc019091060>
    self.private_method
  end

  private
  def private_method
    "bar"
  end
end

f = Foo.new
f.implicit # => "bar"
f.explicit # => 
# ~> -:9:in `explicit': private method `private_method' called for #<Foo:0x007fc019091060> (NoMethodError)
# ~>    from -:25:in `<main>'

Если вы хотите вызывать приватные методы, используйте неявный приемник или send.

self.send :private_method

Обновлять

Выдержка из книги по метапрограммированию Ruby.

Что на самом деле означает частное

Теперь, когда вы знаете о себе, вы можете по-новому взглянуть на ключевое слово private в Ruby. Приватные методы управляются одним простым правилом: вы не можете вызывать приватный метод с явным получателем. Другими словами, каждый раз, когда вы вызываете приватный метод, он должен быть у неявного получателя — self. Давайте посмотрим на угловой случай:

class C
  def public_method
    self.private_method 
  end
  private
  def private_method; end
end
C.new.public_method

⇒ NoMethodError: private method ‘private_method' called [...]

Вы можете заставить этот код работать, удалив ключевое слово self.

Этот надуманный пример показывает, что приватные методы возникают из двух правил, работающих вместе: во-первых, вам нужен явный получатель для вызова метода для объекта, который не является вами, и во-вторых, приватные методы можно вызывать только с неявным получателем. Соедините эти два правила вместе, и вы увидите, что вы можете вызывать закрытый метод только для себя. Вы можете назвать это «частным правилом».

Приватные методы Ruby могут вызвать недоумение, особенно если вы пришли из Java или C#, где приватные методы ведут себя совсем по-другому. Когда вы сомневаетесь, просто вернитесь к частному правилу, и все обретет смысл. Может ли объект x вызвать закрытый метод для объекта y, если два объекта имеют один и тот же класс? Ответ — нет, потому что независимо от того, к какому классу вы принадлежите, вам все равно нужен явный получатель для вызова метода другого объекта. Можете ли вы вызвать закрытый метод, унаследованный от суперкласса? Ответ положительный, потому что вам не нужен явный получатель для вызова унаследованных методов у себя.

12.07.2012
Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

Как написать эффективное резюме
Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..