контроль доступа сбивает меня с толку - PullRequest
0 голосов
/ 29 декабря 2011

хорошо, я нахожусь в тот момент в моей рубиновой карьере, где это должно было сбить меня с толку.

У меня есть модель под названием distribution.rb, где у меня есть следующий защищенный метод:

  def update_email_sent_on_date
    if self.send_to_changed?
      self.date_email_delivered = DateTime.now
    end
  end

Затем я вызываю этот метод из моего контроллера:

 distribution.update_email_sent_on_date

однако я получаю эту ошибку:

NoMethodError (protected method `update_email_sent_on_date' called for #<EmailDistribution:0x131a1be90>):

объект distribution действительно является EmailDistribution (подклассом распределения, в котором определен метод). Я думал , что это сработает. В любом случае я также пытался переместить метод в подкласс EmailDistribution, но не повезло. То же сообщение об ошибке.

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

1 Ответ

1 голос
/ 29 декабря 2011

Я думаю, что вас запутали, потому что вы используете декларацию protected, когда вы действительно хотите декларацию private.

Термин protected в ruby ​​действует по-другому в других традиционных языках.

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

Разница между защищенным и частным невелика. Если метод защищен, он может быть вызван любым экземпляром определяющего класса или его подклассов. Если метод является закрытым, он может быть вызван только в контексте вызывающего объекта - невозможно получить прямой доступ к закрытым методам другого экземпляра объекта, даже если объект того же класса, что и вызывающий объект. Для защищенных методов они доступны из объектов одного и того же класса (или дочерних элементов).

Это немного более ясное объяснение ИМХО из книги Красноречивый Руби Русса Олсена :

Обратите внимание, что в Ruby частные методы могут вызываться из подклассов. Подумайте об этом: вам не нужна явная ссылка на объект для вызова метода суперкласса из подкласса.

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

Наконец, хорошо отметить, что в ruby ​​вы всегда можете вызывать закрытые или защищенные методы независимо от того, доступны ли они с помощью метода send. Так что, если вы были в затруднении и просто нуждались в работе, вы можете просто назвать это так, а потом позаботиться о декларациях private/protected:

distribution.send(:update_email_sent_on_date)

Прочитайте это для более лучшего объяснения. .

...