[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Help with the DSL (ish) config class

goodieboy

2/28/2008 7:51:00 PM

Hi,

I experimenting with this config class. I'm hoping to get something
really easy to write and I'm on to something here, well at least I
thought I was. This class allows me to build a nested Has like:

Config.new do
simple_setting 'the value'
nested {
nested_key 'nested_value'
deep_nesting {
deep_nested_key 'deep nested value'
}
}
end

The problem is that if I have a key that matches the name of the Hash
class method set, problems arise. Currently, the only way that the
settings can be made is if the method doesn't exist (using
method_missing). Obviously, this is a problem. Would someone mind
kicking in here and giving me a clue as to how I could solve this
problem? Is it possible to do what I want, with out having to use
method_missing?

Thanks - matt

class Config < Hash
def initialize(init_data=nil, &block)
update init_data if init_data.respond_to?(:each_pair)
configure(&block)
end

def configure(&block)
instance_eval(&block) if block_given?
end

def method_missing(method, data=nil, &block)
self[method] = data
if data.nil?
# if data.nil?, create a skelton using the method as key (method
chaining)
return self[method] = self.class.new(data, &block)
end
self
end
end

8 Answers

ara.t.howard

2/28/2008 8:49:00 PM

0



On Feb 28, 12:50 pm, goodieboy <goodie...@gmail.com> wrote:
> Hi,
>
> I experimenting with this config class. I'm hoping to get something
> really easy to write and I'm on to something here, well at least I
> thought I was. This class allows me to build a nested Has like:
>
> Config.new do
> simple_setting 'the value'
> nested {
> nested_key 'nested_value'
> deep_nesting {
> deep_nested_key 'deep nested value'
> }
> }
> end
>
> The problem is that if I have a key that matches the name of the Hash
> class method set, problems arise. Currently, the only way that the
> settings can be made is if the method doesn't exist (using
> method_missing). Obviously, this is a problem. Would someone mind
> kicking in here and giving me a clue as to how I could solve this
> problem? Is it possible to do what I want, with out having to use
> method_missing?
>
> Thanks - matt
>
> class Config < Hash
> def initialize(init_data=nil, &block)
> update init_data if init_data.respond_to?(:each_pair)
> configure(&block)
> end
>
> def configure(&block)
> instance_eval(&block) if block_given?
> end
>
> def method_missing(method, data=nil, &block)
> self[method] = data
> if data.nil?
> # if data.nil?, create a skelton using the method as key (method
> chaining)
> return self[method] = self.class.new(data, &block)
> end
> self
> end
> end

i've already done it for you:

http://codeforpeople.com/lib/ruby/configuration/configuration-0....

gem install configuration

cheeers

goodieboy

2/28/2008 9:15:00 PM

0

Hi that's great! I'm wondering though, is it possible to turn the
whole thing into a Hash?

What I'd like to be able to do is:

1. create a default config with only the code to be evaluated
2. push that code into a file (no problem)
3. load it into a hash later

With #1, here is an example:
Configuration.for('a'){
a 40
b 4
c 2
}

I'd like to have a file with only this in it:
a 40
b 4
c 2

Is that possible? Without calling self?

Thanks again, I'm going to pick this apart and see if I can learn
something from it! :)

Matt

On Feb 28, 3:49 pm, -a <ara.t.how...@gmail.com> wrote:
> On Feb 28, 12:50 pm, goodieboy <goodie...@gmail.com> wrote:
>
>
>
> > Hi,
>
> > I experimenting with this config class. I'm hoping to get something
> > really easy to write and I'm on to something here, well at least I
> > thought I was. This class allows me to build a nested Has like:
>
> > Config.new do
> > simple_setting 'the value'
> > nested {
> > nested_key 'nested_value'
> > deep_nesting {
> > deep_nested_key 'deep nested value'
> > }
> > }
> > end
>
> > The problem is that if I have a key that matches the name of the Hash
> > class method set, problems arise. Currently, the only way that the
> > settings can be made is if the method doesn't exist (using
> > method_missing). Obviously, this is a problem. Would someone mind
> > kicking in here and giving me a clue as to how I could solve this
> > problem? Is it possible to do what I want, with out having to use
> > method_missing?
>
> > Thanks - matt
>
> > class Config < Hash
> > def initialize(init_data=nil, &block)
> > update init_data if init_data.respond_to?(:each_pair)
> > configure(&block)
> > end
>
> > def configure(&block)
> > instance_eval(&block) if block_given?
> > end
>
> > def method_missing(method, data=nil, &block)
> > self[method] = data
> > if data.nil?
> > # if data.nil?, create a skelton using the method as key (method
> > chaining)
> > return self[method] = self.class.new(data, &block)
> > end
> > self
> > end
> > end
>
> i've already done it for you:
>
> http://codeforpeople.com/lib/ruby/configuration/configurati......
>
> gem install configuration
>
> cheeers

Drew Olson

2/28/2008 11:06:00 PM

0

M.W. Mitchell wrote:
> Hi,
>
> I experimenting with this config class. I'm hoping to get something
> really easy to write and I'm on to something here, well at least I
> thought I was. This class allows me to build a nested Has like:

I threw this together in a few minutes, doesn't support nested hashes
though :( It writes out your hash to a .yaml file that you can read in
later.

- Drew

require 'yaml'

class Configuration
def initialize(filename)
@filename = filename
@hash = {}
end

def method_missing(name,*args)
@hash[name] = args.first
end

def store
File.open(@filename,"w") do |out|
out << YAML::dump(@hash)
end
end
end

def Configuration filename,&block
config = Configuration.new(filename)
config.instance_eval(&block)
end

Configuration "my_app.yaml" do
a 10
b 20
c 30

store
end

--
Posted via http://www.ruby-....

Drew Olson

2/28/2008 11:11:00 PM

0

Drew Olson wrote:
> M.W. Mitchell wrote:
>> Hi,
>>
>> I experimenting with this config class. I'm hoping to get something
>> really easy to write and I'm on to something here, well at least I
>> thought I was. This class allows me to build a nested Has like:
>
> I threw this together in a few minutes, doesn't support nested hashes
> though :(

I spoke too soon, it does now :)

require 'yaml'

class Configuration
def initialize(filename=nil)
@filename = filename
@hash = {}
end

def method_missing(name,*args,&block)
if block
config = Configuration.new
config.instance_eval(&block)
@hash[name] = config.hash_value
else
@hash[name] = args.first
end
end

def store
File.open(@filename,"w") do |out|
out << YAML::dump(@hash)
end
end

def hash_value
@hash
end
end

def Configuration filename=nil,&block
config = Configuration.new(filename)
config.instance_eval(&block)
end

Configuration "my_app.yaml" do
a 10
b 20
c 30
d do
d1 10
d2 20
end

store
end

--
Posted via http://www.ruby-....

goodieboy

3/2/2008 3:34:00 PM

0

Hi,

Thanks Drew. I had something like that working too. But the problem is
method_missing. What if I want to create a key that happens to have
the same name as a method that actually exists? Also, how would you
convert that to a hash?

Thanks again,
Matt

On Feb 28, 6:11 pm, Drew Olson <olso...@gmail.com> wrote:
> Drew Olson wrote:
> > M.W. Mitchell wrote:
> >> Hi,
>
> >> I experimenting with thisconfigclass. I'm hoping to get something
> >> really easy to write and I'm on to something here, well at least I
> >> thought I was. This class allows me to build a nested Has like:
>
> > I threw this together in a few minutes, doesn't support nested hashes
> > though :(
>
> I spoke too soon, it does now :)
>
> require 'yaml'
>
> class Configuration
> def initialize(filename=nil)
> @filename = filename
> @hash = {}
> end
>
> def method_missing(name,*args,&block)
> if block
> config= Configuration.new
> config.instance_eval(&block)
> @hash[name] =config.hash_value
> else
> @hash[name] = args.first
> end
> end
>
> def store
> File.open(@filename,"w") do |out|
> out << YAML::dump(@hash)
> end
> end
>
> def hash_value
> @hash
> end
> end
>
> def Configuration filename=nil,&block
> config= Configuration.new(filename)
> config.instance_eval(&block)
> end
>
> Configuration "my_app.yaml" do
> a 10
> b 20
> c 30
> d do
> d1 10
> d2 20
> end
>
> store
> end
>
> --
> Posted viahttp://www.ruby-....

Drew Olson

3/2/2008 4:27:00 PM

0

M.W. Mitchell wrote:
> Hi,
>
> Thanks Drew. I had something like that working too. But the problem is
> method_missing. What if I want to create a key that happens to have
> the same name as a method that actually exists? Also, how would you
> convert that to a hash?
>
> Thanks again,
> Matt

Matt -

That code actually produces a hash, we are just storing it in a file. If
you wanted to grab the file and use the hash, you would do something
along the lines of:

my_hash = YAML::load(File.read("my_file.yaml"))

As far as the method_missing issues, this is a typical example of where
using something like BlankSlate would be helpful. You can read more
about it here:
http://onestepback.org/index.cgi/Tech/Ruby/Blank...

- Drew
--
Posted via http://www.ruby-....

goodieboy

3/14/2008 5:10:00 PM

0

Cool that's exactly what I was looking for! I came up with this simple
little piece:

class Config

instance_methods.each { |m| undef_method m unless (m =~ /^__/) or
['class', 'instance_eval'].include?(m) }

def initialize(init_data=nil, &block)
@d = init_data || {}
instance_eval(&block) if block_given?
end

def to_hash; @d; end

def method_missing(method, data=nil, &block)
@d[method] = data
return @d[method] = self.class.new(data, &block).to_hash if
data.nil?
@d
end

end

c = Config.new do
simple_setting 'the value'
send 'Testing send'
nested {
new 'Testing new, make sure it gets passed to method_missing'
nested_key 'nested_value'
deep_nesting {
deep_nested_key 'deep nested value'
o 'Test'
instance_variables 'test'
}
}
end

puts c.to_hash.inspect

Thanks for all of your help and suggestions. I learned quite a bit
from this :)

Matt



On Mar 2, 12:27 pm, Drew Olson <olso...@gmail.com> wrote:
> M.W. Mitchell wrote:
> > Hi,
>
> > Thanks Drew. I had something like that working too. But the problem is
> > method_missing. What if I want to create a key that happens to have
> > the same name as a method that actually exists? Also, how would you
> > convert that to a hash?
>
> > Thanks again,
> > Matt
>
> Matt -
>
> That code actually produces a hash, we are just storing it in a file. If
> you wanted to grab the file and use the hash, you would do something
> along the lines of:
>
> my_hash = YAML::load(File.read("my_file.yaml"))
>
> As far as the method_missing issues, this is a typical example of where
> using something like BlankSlate would be helpful. You can read more
> about it here:http://onestepback.org/index.cgi/Tech/Ruby/Blank...
>
> - Drew
> --
> Posted viahttp://www.ruby-....

goodieboy

3/14/2008 5:22:00 PM

0

Thought I'd just update this as it's exactly what I was trying to do -
have the config settings in a file, but only the block contents. Now
in your config file, you can do:

# my_config.rb
rows 10
query_fields [:name,:address]
facets {
fields [:business,:product_category]
offset 0
}

And to turn that into a Hash:
Config.load_from_file('my_config.rb').to_hash

Neat!

-matt


============

class Config

instance_methods.each { |m| undef_method m unless (m =~ /^__/) or
['class', 'instance_eval'].include?(m) }

def initialize(init_data=nil, &block)
@d = init_data || {}
instance_eval(&block) if block_given?
end

def to_hash; @d; end

def self.load_from_file(file)
self.new.instance_eval File.read(file)
end

protected

def method_missing(method, data=nil, &block)
@d[method] = data
return @d[method] = self.class.new(data, &block).to_hash if
data.nil?
@d
end

end