2012/3/2 Iwan B. [email protected]:
Volevo vedere e capire come viene realizzata la lettura della parte
contenuta nel blocco.
Vedo ad esempio che nel suo esempio Gabriele fa uso della variabile
‘config’ (in config.difficulty = :hard), mentre Luca non la usa…
fondamentalmente lo stesso, nel mio caso avresti fatto una cosa cos:
class App
Config = Struct.new(:foo, :bar, :baz)
attr_reader :config
def initialize
@config = Config.new
end
def configure_with_implicit_config(&block)
instance_eval &block
end
end
MyApp = App.new
MyApp.configure_with_implicit_config do
#questo codice eseguito nel contesto dell’oggetto MyApp, e accede
a @config tramite il suo accessor, come se le righe avessero
“self.” davanti
config.foo= ‘foo!’
config.bar= ‘bar!’
end
p MyApp
=> #<App:0x0000010086c440 @config=#<struct App::Config foo=“foo!”,
bar=“bar!”, baz=nil>>
oppure puoi passare config come parametro al blocco, che per me meglio:
def configure_with_explicit_config
yield config
end
MyApp.configure_with_implicit_config do |config|
nessun cambio di contesto
config.foo= ‘foo!’
config.bar= ‘bar!’
end
Il modo in cui fa luca usa come contesto l’oggetto config stesso, cio
sarebbe come fare
def configure_with_even_more_implicit_config(&block)
config.instance_eval(&block)
end
ma a questo punto non puoi usare la sintassi cos:
MyApp.configure_with_even_more_implicit_config do
foo = ‘foo!’
bar = ‘bar!’
end
perch ruby interpreta l’assegnamento come se fossero variabili
locali, non come se tu stessi invocando “self.foo=”
Infatti se diventi esplicito funziona:
MyApp.configure_with_even_more_implicit_config do
siccome hai fatto config.instance_eval qui self corrisponde a
config
self.foo = ‘foo!’
self.bar = ‘bar!’
end
e a questo punto il trick standard, come ha fatto luca, di non usare
la sintassi “=” ma di usare una sintassi che forzi ruby a interpretare
le cose come metodi, cio:
MyApp.configure_with_even_more_implicit_config do
siccome sembra un’invocazione di un
metodo “qualcosa” ruby lo interpreta cos
foo ‘foo!’
bar ‘bar!’
end
Per usare questo trick devi definirti i metodi per i vari attributi
(non puoi usare una Struct come ho fatto io che li definisce da se, n
attr_accessor), oppure lo stesso approccio di Luca, usi
#method_missing e viene una cosa cos
class App
class Config
def method_missing(name, *arguments, &block)
if arguments.size != 1 && block.nil?
super
else
instance_variable_set “@#{name}”, arguments.first
end
end
end
attr_reader :config
def initialize
@config = Config.new
end
def configure_with_more_implicit_config(&block)
config.instance_eval &block
end
end
MyApp = App.new
MyApp.configure_with_more_implicit_config do
foo ‘foo!’
bar ‘bar!’
end
p MyApp
–
twitter: @riffraff
blog (en, it): www.riffraff.info riffraff.blogsome.com
work: cascaad.com circleme.com