访问控制让我绊倒

发布于 2024-12-23 09:02:00 字数 738 浏览 1 评论 0原文

好吧,我正处于我的红宝石职业生涯的那个阶段,这应该会让我绊倒。

我有一个名为 distribution.rb 的模型,其中有以下 protected 方法:

  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>):

< code>distribution 对象确实是一个 EmailDistribution (定义该方法的 distribution 的子类)。我认为这会起作用。无论如何,我也尝试将该方法移动到子类 EmailDistribution 但没有成功。同样的错误消息。

我还想退一步说,我总体上想做的是存储更新分布模型中另一个字段的时间戳。如果有更简单的方法,请赐教。

ok, i'm about at that point in my ruby career where this should be tripping me up.

I have a model called distribution.rb where I have the follwoing protected method:

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

I then call this method from my controller:

 distribution.update_email_sent_on_date

however, I'm getting this error:

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

the distribution object is indeed an EmailDistribution (a subclass of distribution where the method is defined). I thought this would work. In any case, I also tried moving the method to the subclass EmailDistribution but no luck. Same error message.

I'd also like to step back and say that what I'm trying to do overall is store the timestamp of when another field in the distribution model is updated. If there's a simpler way, please enlighten me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

沉溺在你眼里的海 2024-12-30 09:02:00

我认为您被绊倒了,因为当您实际上需要 private 声明时,您正在使用 protected 声明。

Ruby 中的 protected 术语在其他传统语言中的作用有所不同.

在 Ruby 中,私有可见性就是 Java 中受保护的可见性。 Ruby 中的私有方法可由子级访问。这是一个明智的设计,因为在 Java 中,当方法是私有的时,它对于子类来说变得毫无用处:制定一条规则,所有方法都应该默认“受保护”,而不是私有的。然而,在 Ruby 中你不能拥有真正私有的方法;你不能完全隐藏一个方法。

受保护和私有之间的区别很微妙。如果方法受保护,则它可以由定义类或其子类的任何实例调用。如果方法是私有的,则只能在调用对象的上下文中调用它——永远不可能直接访问另一个对象实例的私有方法,即使该对象与调用者属于同一类。对于受保护的方法,可以从同一类(或子类)的对象访问它们。

恕我直言,这是一个稍微清晰的解释,来自 Russ Olsen 的Eloquent Ruby一书:

请注意,在 Ruby 中,私有方法可以从子类中调用。想一想:您不需要显式的对象引用来从子类调用超类方法。

受保护方法的规则更宽松,也更复杂:类的任何实例都可以调用该类的任何其他实例上的受保护方法。

最后,值得注意的是,在 ruby​​ 中,您始终可以调用私有或受保护的方法,无论它们是否可以使用 send 方法访问。因此,如果您手头紧要,只需要工作,您可以这样调用它,然后再担心 private/protected 声明:

distribution.send(:update_email_sent_on_date)

阅读本文以获得更多更好的解释。

I think you're getting tripped up because you are using the protected declaration when you actually want the private declaration.

The protected term in ruby acts differently in other conventional languages.

In Ruby, private visibility is what protected was in Java. Private methods in Ruby are accessible from children. This is a sensible design, since in Java, when method was private, it rendered it useless for children classes: making it a rule, that all methods should be "protected" by default, and never private. However, you can't have truly private methods in Ruby; you can't completely hide a method.

The difference between protected and private is subtle. If a method is protected, it may be called by any instance of the defining class or its subclasses. If a method is private, it may be called only within the context of the calling object---it is never possible to access another object instance's private methods directly, even if the object is of the same class as the caller. For protected methods, they are accessible from objects of the same class (or children).

This is a slightly clearer explanation IMHO, from the book Eloquent Ruby by Russ Olsen:

Note that in Ruby, private methods are callable from subclasses. Think about it: You don't need an explicit object reference to call a superclass method from a subclass.

The rules for protected methods are looser and a bit more complex: Any instance of a class can call a protected method on any other instance of the class.

Lastly, it's good to note that in ruby you can always call private or protected methods regardless of whether they are accessible by using the send method. So if you were in a pinch and just needed to work you could just call it like this and then worry about the private/protected declarations later:

distribution.send(:update_email_sent_on_date)

Read this for more a better explanation..

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文