Hi! i need a solution for this, it’s pretty simple but i can’t get it to
work…
suppose:
class Options
def self.define_an_option
# …don’t-know-how-implementation 
end
define_an_option :option1, String
define_an_option :option2, Array
end
Then, i want to do something like this:
opt= Options.new
opt.option1 => “”
opt.option2 => []
opt.option1 do |o|
o= “Hello”
end
opt.option2 do |o|
o << 10
end
options.option1 => “Hello”
options.option2 => [10]
Thats all! Seems pretty simple, but i tried with a lot of variants and I
don’t get it to work. Any ideas?
Thanks!
From: [email protected] [mailto:[email protected]] On Behalf
Of
Emmanuel O.
Sent: Wednesday, September 26, 2007 1:09 AM
end
Before you do it, you should understand your API examples seems
unnatural.
Why not to do
opt.option1 = “Hello”
opt.option2 << 10
?
Than, this example:
opt.option1 do |o|
o = “Hello”
end
is almost impossible to do (possible, but hard), because it should read
like: “pass reference option value into block though ‘o’ variable;
replace
‘o’ with reference to ‘Hello’ string” - option value will left
untouched.
V.
Hi –
On Wed, 26 Sep 2007, Emmanuel O. wrote:
opt.option1 do |o|
o= “Hello”
end
That’s just a re-assignment to the variable ‘o’. It’s not going to
have any impact on opt.option1.
opt.option2 do |o|
o << 10
end
options.option1 => “Hello”
options.option2 => [10]
Thats all! Seems pretty simple, but i tried with a lot of variants and I
don’t get it to work. Any ideas?
The block syntax seems a little odd. Is there any reason not to just
use attr_accessor? If you want it to default to a new instance of some
specific class, you could do something like:
class Options
def self.define_an_option(name, klass)
attr_writer name
iv = “@#{name}”
define_method(name) do
unless instance_variables.include?(iv)
instance_variable_set(iv, klass.new)
end
val = instance_variable_get(iv)
yield val if block_given? # if you really need this
val
end
end
define_an_option :option1, String
define_an_option :option2, Array
end
(and I suspect there are other versions of attr_reader with a default
value out there somewhere).
David
Hi! thanks for you replies. I’m going to analyze them. For the moment i
wanted to answer the question of the unnatural api. The reason i wan’t
to do it that way is because i’m not going to use String or array for
most of the options, but Structs. So i want a way to let the user do
this
Struct.new “Value”, :sub1, :sub2, :sub3 << In fact, the user may not
even know about the Struct::Value class.
class Options
…same as before…
define_option :an_option
end
opt= Options.new
opt.an_option do |o|
o.sub1= …
o.sub2= …
o.sub3= …
end
instead of
an_option.sub1= …
an_option.sub2= …
an_option.sub3= …
On Sep 25, 2007, at 6:09 PM, Emmanuel O. wrote:
end
Thats all! Seems pretty simple, but i tried with a lot of variants
and I
don’t get it to work. Any ideas?
Have you looked at the built-in class Struct? I think it will supply
what you need.
Options = Struct.new(:option1, :option2)
opt=Options.new("", [])
opt.option1 = "Hello"
opt.option2 << 10 < "Hello"
opt.option2 # => [10, 42]
Regards, Morton
From: [email protected] [mailto:[email protected]] On Behalf
Of
Emmanuel O.
Sent: Wednesday, September 26, 2007 2:51 AM
class Options
end
instead of
an_option.sub1= …
an_option.sub2= …
an_option.sub3= …
Acceptable explanation. Then, trying to answer:
- Defining the method you need “by hands”:
class Option
def an_option
@an_option ||= Value.new
yield @an_option if block_given?
@an_option
end
end
- Designing #define_option
class Option
def self.define_option(name, type)
class_eval %Q{
def #{name}
@#{name} ||= #{type.inspect}.new
yield @#{name} if block_given?
@#{name}
end
}
end
define_option :an_option, Array
end
o = Option.new
p o.an_option # => []
o.an_option { |opt|
opt << 1 << 2 << 3
}
p o.an_option # => [1,2,3]
Really, I think it can be done with more grace (without textual eval).
V.