I’m a little tired so I’m probably making a mistake:
module MyModule
class << self
attr_accessor :foo
alias_method :foo?, :foo
# def configure(&block); yield; end # doesn’t work
end
end
doesn’t work either
#class << MyModule
def configure(&block); yield; end
#end
Thanks in advance for any advice. I’d rather not use any
Active*/Rails-specific method and don’t want to use Struct, OpenStruct,
etc. I just want to be able to call the methods created by the
attr_accessor I used to set and get attributes. The reasons I’m doing
this to a module and not a class is it is convenient since it is the
module that my Gem’s classes use.
first off, you’re not that wrong with your idea. There are two things
which need to be changed.
MyModule.configure do
foo = false
end
The local variable foo is just that - a local variable. You want it to
be a class instance variable, so you need to precede it with an @.
etc. I just want to be able to call the methods created by the
attr_accessor I used to set and get attributes. The reasons I’m doing
this to a module and not a class is it is convenient since it is the
module that my Gem’s classes use.
You don’t need to use an external library. The thing you did wrong in
your configure method is that it executes the block in the scope of it’s
creation, so even if you use the @, it is not a variable in the
class/module scope. So what you need to do is call class_eval with the
block as a parameter:
def configure( &block ); class_eval █ end
Such that MyModule.foo would then return false:
end
attr_accessor I used to set and get attributes. The reasons I’m doing
this to a module and not a class is it is convenient since it is the
module that my Gem’s classes use.
That just creates a block local variable which is destroyed when the
block ends.
Is there a way to make things in the block execute as if they were being
called on MyModule, i.e.
MyModule.foo = 1
MyModule.bar = 2
could be alternatively:
MyModule.do
foo = 1
bar = 2
end
You could do this:
module MyModule
class <<self
attr_accessor :foo
def configure(hash)
hash.each {|key, val| send(:"#{key}=", val)}
end
end
end
p MyModule.foo
MyModule.configure ‘foo’ => false
p MyModule.foo
–output:–
nil
false
That is helpful, but I have a way to do a hash easily already via
another method, with the idea that the following might be interesting:
MyModule.do
foo = 1
def bar
2 # imagine a more interesting and dynamic result
end
end
I understand it might require some changes, so syntax might not be
exactly like that, but originally I thought this would be doable, and am
just kind of stuck. Ilia had suggested ActiveSupport::Configurable on
the list but it requires config to be sent in as a parameter and I was
hoping to allow method definition and not have to specify the
config.varname = …
…gets its bindings from the surrounding scope at the time the block
is created, and at that time self is ‘main’ and the ‘main’ object has no
method foo=() defined for it.
You could do this:
module MyModule
class <<self
attr_accessor :foo
def configure(hash)
hash.each {|key, val| send(:"#{key}=", val)}
end
end
end
p MyModule.foo
MyModule.configure ‘foo’ => false
p MyModule.foo
That is helpful, but I have a way to do a hash easily already via
exactly like that, but originally I thought this would be doable, and am
just kind of stuck. Ilia had suggested ActiveSupport::Configurable on
the list but it requires config to be sent in as a parameter and I was
hoping to allow method definition and not have to specify the
config.varname = …
I don’t know if my previous message got through. If you can handle
some changes in the syntax, using self. before the attributes and the
method names should work if you do a class_eval:
1.9.2p290 :013 > module MyModule
1.9.2p290 :014?> class << self
1.9.2p290 :015?> attr_accessor :foo
1.9.2p290 :016?> alias_method :foo?, :foo
1.9.2p290 :017?> def configure(&blk)
1.9.2p290 :018?> class_eval(&blk)
1.9.2p290 :019?> end
1.9.2p290 :020?> end
1.9.2p290 :021?> end
=> nil
1.9.2p290 :022 > MyModule.configure do
1.9.2p290 :023 > def self.test; puts “test”; end
1.9.2p290 :024?> end
=> nil
1.9.2p290 :025 > MyModule.test
test
=> nil
That is helpful, but I have a way to do a hash easily already via
exactly like that, but originally I thought this would be doable, and am
just kind of stuck. Ilia had suggested ActiveSupport::Configurable on
the list but it requires config to be sent in as a parameter and I was
hoping to allow method definition and not have to specify the
config.varname = …
I don’t know if my previous message got through. If you can handle
some changes in the syntax, using self. before the attributes and the
method names should work if you do a class_eval:
1.9.2p290 :013 > module MyModule
1.9.2p290 :014?> class << self
1.9.2p290 :015?> attr_accessor :foo
1.9.2p290 :016?> alias_method :foo?, :foo
1.9.2p290 :017?> def configure(&blk)
1.9.2p290 :018?> class_eval(&blk)
1.9.2p290 :019?> end
1.9.2p290 :020?> end
1.9.2p290 :021?> end
=> nil
1.9.2p290 :022 > MyModule.configure do
1.9.2p290 :023 > def self.test; puts “test”; end
1.9.2p290 :024?> end
=> nil
1.9.2p290 :025 > MyModule.test
test
=> nil
Jesus.
Thank you, Jesus! That’s exactly what I was looking for!
module MyModule
class << self
attr_accessor :foo, :time
alias_method :foo?, :foo
def configure(&blk)
class_eval(&blk)
end
end
end
MyModule.foo # nil
MyModule.time # nil
MyModule.configure do
self.foo = false
def self.time; Time.now; end
end
MyModule.foo # false
MyModule.time # current date and time
first off, you’re not that wrong with your idea. There are two things
which need to be changed.
MyModule.configure do
foo = false
end
The local variable foo is just that - a local variable. You want it to
be a class instance variable, so you need to precede it with an @.
etc. I just want to be able to call the methods created by the
attr_accessor I used to set and get attributes. The reasons I’m doing
this to a module and not a class is it is convenient since it is the
module that my Gem’s classes use.
You don’t need to use an external library. The thing you did wrong in
your configure method is that it executes the block in the scope of it’s
creation, so even if you use the @, it is not a variable in the
class/module scope. So what you need to do is call class_eval with the
block as a parameter:
def configure( &block ); class_eval █ end
Calvin,
Thanks! That is even shorter. It is nice to have both options available,
so when do:
module MyModule
class << self
attr_accessor :foo
alias_method :foo?, :foo
def configure(&blk)
class_eval(&blk)
end
end
end
can do either:
MyModule.configure do @foo = false
def self.time; Time.now; end
end
or
MyModule.configure do
self.foo = false
def self.time; Time.now; end
end
That is so awesome! Thanks for everyone’s help!
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.