Rails'de korumalı ve özel yöntemler


81

Ruby'de yöntem görünürlüğü (genel, korumalı ve özel yöntemler) bu blog yazısı gibi yerlerde iyi açıklanmıştır . Ancak Ruby on Rails'de, çerçevenin kurulma şekli nedeniyle normal bir Ruby uygulamasındakinden biraz farklı görünüyor. Peki, Rails modellerinde, denetleyicilerinde, yardımcılarında, testlerinde vb. Korumalı veya özel yöntemlerin kullanılması ne zaman uygun / değildir?

Düzenleme : Şimdiye kadarki cevaplar için teşekkürler. Ruby'de korumalı ve özel kavramını anlıyorum, ancak bu tür görünürlük türlerinin bir Rails uygulamasının çeşitli parçaları (modeller, denetleyiciler, yardımcılar, testler) bağlamında kullanılma biçiminin tipik bir açıklamasını arıyorum. . Örneğin, genel denetleyici yöntemleri eylem yöntemleridir, uygulama denetleyicisindeki korumalı yöntemler, birden çok denetleyici tarafından erişilmesi gereken "yardımcı yöntemler" için kullanılır.

Yanıtlar:


106

Modeller için fikir, genel yöntemlerin sınıfın genel arayüzü olmasıdır. Genel yöntemler diğer nesneler tarafından kullanılmak üzere tasarlanırken, korumalı / özel yöntemler dışarıdan gizlenecektir.

Bu, diğer nesne yönelimli dillerdeki ile aynı uygulamadır.

İçin kontrolörler ve siz lütfen testler, sadece yap. Hem denetleyici hem de test sınıfları yalnızca çerçeve tarafından başlatılır ve çağrılır ( evet, denetleyiciyi teorik olarak görünümden alabileceğinizi biliyorum, ancak bunu yaparsanız, yine de garip bir şeyler olur ). Hiç kimse bunları doğrudan yaratmayacağına göre, "korunacak" hiçbir şey yoktur.

Ek / Düzeltme: Denetleyiciler için, "yardımcı" yöntemleri korumalı özel olarak işaretlemelisiniz ve yalnızca eylemlerin kendileri genel olmalıdır. Çerçeve, gelen HTTP çağrılarını hiçbir zaman genel olmayan eylemlere / yöntemlere yönlendirmez, bu nedenle yardımcı yöntemleriniz bu şekilde korunmalıdır.

Yardımcılar için, bir yöntemin korumalı mı yoksa özel mi olduğu, her zaman "doğrudan" olarak adlandırıldıkları için hiçbir fark yaratmaz.

Elbette, her şeyi anlamanızı kolaylaştırıyorsa, tüm bu durumlarda korunan şeyleri işaretleyebilirsiniz.


" Denetleyiciler için," yardımcı "yöntemleri korumalı olarak işaretlemelisiniz ve yalnızca eylemlerin kendileri herkese açık olmalıdır. " Denetleyicilerde herhangi bir özel yöntemin olmamasını tavsiye ediyor musunuz? Yoksa tam anlamıyla okumamalı mıyım?
Dennis

2
Bugünlerde sadece özel kullanıyorum. korumalı ve özel, çoğu yerde birbirinin yerine kullanılır; ama korunmak, gerçek dünyada hiç ihtiyaç duymadığım garip bir davranışı getiriyor.
averell

2
Ben de sadece özel olanı kullanma eğilimindeyim. Bu ayrıca, Thoughtbot'un "Denetleyici yöntemlerini tanımlarken korumalı yerine özel kullanın"
Dennis

68

Bir yöntem kullanmaktan başka kimseyiself istemiyorsanız özel bir yöntem kullanırsınız. Yalnızca self and is_a?(self)kullanıcıların arayabileceği bir şey istiyorsanız, korumalı bir yöntem kullanırsınız .

Korunmanın iyi bir kullanımı, "sanal" bir başlatma yöntemine sahip olmanız olabilir.

class Base
    def initialize()
        set_defaults()
        #other stuff
    end

    protected
    def set_defaults()
        # defaults for this type
        @foo = 7
        calculate_and_set_baz()
    end

    private
    def calculate_and_set_baz()
        @baz = "Something that only base classes have like a file handle or resource"
    end
end

class Derived < Base
    protected
    def set_defaults()
        @foo = 13
    end
end

@foo farklı değerlere sahip olacaktır. ve Türetilmiş örneklerde @baz olmayacak

Güncelleme: Bunu yazdığımdan beri, Ruby 2.0+ sürümünde bazı şeyler değişti Aaron Patterson'un mükemmel bir yazımı var http://tenderlovemaking.com/2012/09/07/protected-methods-and-ruby-2-0.html


10
Söylediğin gibi seviyorum self and is_a?(self). Her zaman korumalı yöntemlerin çocuk sınıflarında mevcut olduğunu açıkladım.
Tate Johnson

16
Dikkat burada! Bu, diğer dillerden önemli bir farktır: Özel yöntemler de çocuk sınıflarında mevcuttur. Özel ve korumalı arasındaki tek fark, korumalı yöntemleri "self.set_defaults" ile çağırabilirken, özel yöntemler yalnızca "set_defaults" olarak adlandırılabilir.
averell

Güzel bir cevap, ancak sorunun özü olan Rails kelimesini bile içermiyor
Bryan Ash

5
Sorusunun Düzenleme zaman damgasına dikkat edin. Gelecekte, cevaplarımı sorularını değiştirirken güncellemek için özel bir yöntem tanımlayacağım :)
EnabrenTane

Averell'in dediği gibi, bu açıklama yakut için geçerli değildir. Özel yöntemlerin çocuk sınıflarında da görülebildiği yerler.
Miguel

10

Korunan ve özel arasındaki fark ince. Bir yöntem korunuyorsa, tanımlayıcı sınıfın veya alt sınıflarının herhangi bir örneği tarafından çağrılabilir. Bir yöntem özelse, yalnızca çağıran nesnenin bağlamı içinde çağrılabilir --- nesne, çağıranla aynı sınıfta olsa bile, başka bir nesne örneğinin özel yöntemlerine doğrudan erişmek asla mümkün değildir. Korumalı yöntemler için, aynı sınıftaki (veya çocuklar) nesnelerden erişilebilir.

http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Classes#Declaring_Visibility


2
Bağlantı için teşekkürler. Ancak bunların Ruby on Rails'de özel olarak nasıl çalıştığını merak ediyorum (genel denetleyici yöntemleri eylem yöntemleri olarak değerlendirilir, uygulama denetleyicisindeki korumalı yöntemler diğer denetleyiciler tarafından kullanılabilir, vb.)
jrdioko

3
Son durumda, "uygulama denetleyicisindeki korumalı yöntemler diğer denetleyiciler tarafından kullanılabilir" çünkü diğer denetleyiciler (genellikle) ApplicationController'dan miras alırlar, böylece tüm bu yöntemlerin kendilerine gerçekten sahip olurlar. Onlara application_controller'dan erişmiyorlar: bu hiçbir zaman somutlaştırılmaz. Tamamen miras almak için bir ebeveyn olarak kullanılır.
Max Williams

3

Yöntemlere uygulandığı haliyle sınıf görünürlüğünün (genel / korumalı / özel) semantiği hakkında iyi bir fikriniz var gibi görünüyor. Tek önerebileceğim, onu Rails uygulamalarıma uygulama şeklimin hızlı bir özeti.

Temel uygulama denetleyicisinde korumalı yöntemler uyguluyorum, böylece herhangi bir denetleyici tarafından filtreler aracılığıyla çağrılabilirler (örn. Before_filter: method_foo). Benzer şekilde, hepsinde kullanmak istediğim modeller için korumalı yöntemler, hepsinin miras aldığı bir temel modelde tanımlıyorum.


2

Eylemlerin bir denetleyicinin genel yöntemleri olması gerekmesine rağmen, tüm genel yöntemler mutlaka eylemler değildir. Sen kullanabilirsiniz hide_actionsizin gibi bir catch-all rotayı kullanıyorsanız /:controller/:action/:idveya daha sonra kesin yollara yalnızca yöntemler çağrılır (Rails 3 varsayılan) devre dışı ise.

Bu, denetleyici örneğini Liquid şablon motoru gibi başka bir kitaplığa geçiriyorsanız yararlı olabilir, çünkü Liquid filtrelerinizde ve etiketlerinizde gönder kullanmak zorunda kalmadan genel bir arabirim sağlayabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.