Metodi protetti e privati ​​in Rails

La visibilità del metodo in Ruby (metodi pubblici, protetti e privati) è stata ben spiegata in posti come questo post del blog . Ma in Ruby on Rails sembra leggermente diverso da quello che sarebbe in una normale applicazione Ruby a causa del modo in cui il framework è impostato. Quindi, nei modelli Rails, controller, helper, test, ecc., Quando è / non è appropriato usare metodi protetti o privati?

Modifica : Grazie per le risposte finora. Capisco il concetto di protetto e privato in Ruby, ma cerco di dare una spiegazione del tipico modo in cui questi tipi di visibilità vengono utilizzati nel contesto dei vari pezzi di un’app Rails (modelli, controller, helper, test) . Ad esempio, i metodi del controller pubblico sono metodi di azione, i metodi protetti nel controller dell’applicazione vengono utilizzati per “metodi di supporto” che devono essere accessibili da più controller, ecc.

Per i modelli, l’idea è che i metodi pubblici siano l’interfaccia pubblica della class. I metodi pubblici sono destinati ad essere utilizzati da altri oggetti, mentre i metodi protetti / privati ​​devono essere nascosti dall’esterno.

Questa è la stessa pratica di altri linguaggi orientati agli oggetti.

Per controllori e test, fai come ti pare. Sia il controller che le classi di test sono solo istanziati e richiamati dal framework ( sì, so che puoi teoricamente ottenere il controller dalla vista, ma se lo fai, qualcosa è comunque strano ). Dal momento che nessuno creerà mai direttamente queste cose, non c’è nulla da “proteggere” contro.

Addendum / correzione: per i controllori, è necessario contrassegnare i metodi “helper” come privati protetti e solo le azioni stesse dovrebbero essere pubbliche. Il framework non instraderà mai alcuna chiamata HTTP in entrata a azioni / metodi che non sono pubblici, quindi i metodi di supporto dovrebbero essere protetti in questo modo.

Per gli helper non farà alcuna differenza se un metodo è protetto o privato, poiché vengono sempre chiamati “direttamente”.

Puoi contrassegnare le cose protette in tutti quei casi, se ciò rende le cose più facili da capire, ovviamente.

Usi un metodo privato se non vuoi che qualcun altro usi da solo un metodo. Si utilizza un metodo protetto se si desidera qualcosa solo self and is_a?(self) s può chiamare.

Un buon uso di protezione potrebbe essere se tu avessi un metodo di inizializzazione “virtuale”.

 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 classs have like a file handle or resource" end end class Derived < Base protected def set_defaults() @foo = 13 end end 

@foo avrà valori diversi. e le istanze derivate non avranno @baz

Aggiornamento: Da quando ho scritto questo, alcune cose sono cambiate in Ruby 2.0+ Aaron Patterson ha un eccellente articolo http://tenderlovemaking.com/2012/09/07/protected-methods-and-ruby-2-0.html

La differenza tra protetto e privato è sottile. Se un metodo è protetto, può essere chiamato da qualsiasi istanza della class che definisce o delle sue sottoclassi. Se un metodo è privato, può essere chiamato solo nel contesto dell’object chiamante — non è mai ansible accedere direttamente ai metodi privati ​​di un’altra istanza dell’object, anche se l’object è della stessa class del chiamante. Per i metodi protetti, sono accessibili da oggetti della stessa class (o figli).

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

Sembra che tu abbia una buona idea della semantica della visibilità della class (pubblica / protetta / privata) applicata ai metodi. Tutto quello che posso offrire è una breve descrizione del modo in cui la implemento nelle mie app Rails.

Implemento metodi protetti nel controller dell’applicazione di base in modo che possano essere richiamati da qualsiasi controller tramite filtri (ad es. Before_filter: method_foo). Analogamente, definisco metodi protetti per i modelli che voglio utilizzare in tutti loro in un modello base da cui ereditano tutti.

Sebbene le azioni debbano essere metodi pubblici di un controllore, non tutti i metodi pubblici sono necessariamente azioni. Puoi usare hide_action se stai usando un percorso catch-all come /:controller/:action/:id o se è disabilitato (il valore predefinito in Rails 3), verranno chiamati solo i metodi con percorsi espliciti.

Ciò può essere utile se si passa l’istanza del controller a qualche altra libreria come il motore di template Liquid, poiché è ansible fornire un’interfaccia pubblica piuttosto che dover inviare i propri filtri e tag di Liquid.