Come accennato in this answer, in Ruby 2.1 o versioni successive, questo codice:È possibile ispezionare dinamicamente l'ambito di visibilità del metodo (privato/pubblico/protetto)?
class SimpleTest
private
define_method :foo do
42
end
end
definiranno foo
come un metodo privato di SimpleTest
casi. (In Ruby 2.0 e precedenti non sarà privato.) Tuttavia, sto cercando di fare qualcosa di un po 'meno banale. Mi piacerebbe definire un DSL che le classi possano estendere e vorrebbe i metodi che il DSL definisce internamente per rispettare la visibilità privata/protetta del contesto chiamante. Che non può essere chiaro, ecco un esempio:
module Dsl
def has_a(name)
define_method name do
42
end
end
end
class Test
extend Dsl
private
has_a :thing
end
Come scritto, che il codice definisce un metodo di pubblico thing
su Test
istanze. Invece, mi piacerebbe che has_a
fosse in grado di riflettere sulla visibilità del metodo in cui è stato chiamato (private
in questo caso) e definire thing
sotto la stessa visibilità del metodo.
Non ho familiarità con il codice sorgente di Ruby C, ma ho dato una rapida occhiata e ho trovato this function che sembra possa fare ciò che voglio, ma non penso sia accessibile da Ruby. (Sembra essere utilizzato solo here.) Ho anche guardato la documentazione per define_method
(dal momento che il primo esempio funziona come desiderato) here e sembra che la variabile noex
dichiarato e impostare qui:
int noex = NOEX_PUBLIC;
const NODE *cref = rb_vm_cref_in_context(mod, mod);
if (cref) {
noex = (int)cref->nd_visi;
}
potrebbe essere la valore che voglio, ma ancora non so come lo otterrei in Ruby, o anche se sarebbe in grado di riflettere sull'ambito di chiamata (in Test
). Supponendo di avere la visibilità, potrei semplicemente chiamare private name
(o protected name
) dopo la chiamata define_method
all'interno di has_a
se non è stato chiamato in un contesto public
.
Pensieri? C'è un modo per farlo, o sono sfortunato?
Grazie per avermi segnalato. Non l'ho visto quando ho cercato prima di chiedere. È una soluzione interessante, anche se preferirei non dover anteporre qualcosa a 'Module'. – rmacklin