String to symbol

S

Sergey Sheypak

Hello, I'm working with yaml and objects.
Please, see my model:

#Base class for all models.
class DataBean
#list allowed fields for model
def allowed_fields
[]
end

def is_attr_allowed!(attr)
raise(ValidationException, "Attribute with name [#{attr}] is not
allowed for model #{self.class}.
Allowed fields are
#{allowed_fields}", caller) unless allowed_fields.include?(attr)
end

def initialize(options)
options.each_pair { |attr_name , value|
is_attr_allowed!(attr_name)
self.class.send:)define_method, attr_name, Proc.new{value})
}
end

end

class Dates < DataBean
def allowed_fields
[:start, #project beginning
:end, #project ending
:current] #last modification date "T", means current date
end
end

So I can use 'rails like intializers'
Dates.new:)start=>Date.new, :end=>Dates.new+100)

The problem is that I'm reading Dates class fields from yaml file.

Dates:
class: Dates
fields_ordered: [start, current, end]

And I pass String (read from yaml) as a hash key to initializer:
Dates.new('start'=>Date.new)

As I read, :symbols are constants, they are immutable and have int
representation. These facts help to spend less memory and resources.

Do I have any opportunity to pass Strings into my initializers?
 
R

Robert Klemme

2010/2/12 Sergey Sheypak said:
Hello, I'm working with yaml and objects.
Please, see my model:

#Base class for all models.
class DataBean
=A0#list allowed fields for model
=A0def allowed_fields
=A0 =A0[]
=A0end

=A0def is_attr_allowed!(attr)

IMHO that method would rather be called ensure_attr_allowed - if you
call it is_... I would expect it to return a boolean.
=A0 =A0raise(ValidationException, "Attribute with name [#{attr}] is not
allowed for model #{self.class}.
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 A= llowed fields are
#{allowed_fields}", caller) unless allowed_fields.include?(attr)
=A0end

=A0def initialize(options)
=A0 =A0 =A0options.each_pair { |attr_name , value|
=A0 =A0 =A0 =A0is_attr_allowed!(attr_name)
=A0 =A0 =A0 =A0self.class.send:)define_method, attr_name, Proc.new{value}= )
=A0 =A0 =A0}
=A0end

Are you sure this is what you want? It seems you change the accessor
method for *all* instances to return the *same* value. I don't think
this is a good idea.
end

class Dates < DataBean
=A0def allowed_fields
=A0 =A0[:start, =A0#project beginning
=A0 =A0 :end, =A0 =A0#project ending
=A0 =A0 :current] #last modification date "T", means current date
=A0end
end

So I can use 'rails like intializers'
Dates.new:)start=3D>Date.new, :end=3D>Dates.new+100)

The problem is that I'm reading Dates class fields from yaml file.

Dates:
=A0class: Dates
=A0fields_ordered: [start, current, end]

And I pass String (read from yaml) as a hash key to initializer:
Dates.new('start'=3D>Date.new)

As I read, :symbols are constants, they are immutable and have int
representation. These facts help to spend less memory and resources.

Do I have any opportunity to pass Strings into my initializers?

Did you try it out with your code? Was there an issue, if so, which one?

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
S

Sergey Sheypak

Robert said:
IMHO that method would rather be called ensure_attr_allowed - if you
call it is_... I would expect it to return a boolean.
I've added "!" to show that it can throw exception (like in rails)
Are you sure this is what you want? It seems you change the accessor
method for *all* instances to return the *same* value. I don't think
this is a good idea.
I have a bean. Bean can accept certain fields in his constructor.
List of certain fields is overriden in each subclass of DataBean.
I read source (csv) file and try to construct bean using dats from
source and my bean.
Did you try it out with your code? Was there an issue, if so, which
one?
Code works fine.
I've just added to config.yaml:
---
Dates:
class: Dates
fields_ordered: [:start, :current, :end]

and
@conf = YAML::load( File.open( 'config.yml' ) ) #keeps parsed YAML
#some code
#block_name id a current 'top' name like 'Dates'
@struct[:fields] = @conf[block_name]['fields_ordered']
#and later...
private
def init_hash(arr)
Hash[*@struct[:fields].collect {|v| [v,
arr[@struct[:fields].index(v)]]}.flatten]
end

It's method for converting csv line:
lol, 123,lolo, 123.45
to hash using appopriate bean field names as keys
 
R

Robert Klemme

2010/2/12 Sergey Sheypak said:
I've added "!" to show that it can throw exception (like in rails)
I have a bean. Bean can accept certain fields in his constructor.
List of certain fields is overriden in each subclass of DataBean.
I read source (csv) file and try to construct bean using dats from
source and my bean.

I understood that. But the point you are probably missing is this:
you are mixing class and instance information in an unfortunate way:

irb(main):031:0* d1 =3D Dates.new:)start=3D>1,:end=3D>2,:current=3D>3)
=3D> #<Dates:0x101bbb5c>
irb(main):032:0> d1.start
=3D> 1
irb(main):033:0> d1.end
=3D> 2
irb(main):034:0> d1.current
=3D> 3
irb(main):035:0> d2 =3D Dates.new:)start=3D>99,:end=3D>98,:current=3D>97)
=3D> #<Dates:0x1017fde4>
irb(main):036:0> d2.start
=3D> 99
irb(main):037:0> d2.end
=3D> 98
irb(main):038:0> d2.current
=3D> 97
irb(main):039:0> d1.start # ooops!
=3D> 99
irb(main):040:0> d1.end # ooops!
=3D> 98
irb(main):041:0> d1.current # ooops!
=3D> 97
irb(main):042:0>

You are changing state of an already created instance as a side effect
of creating a new instance. This is not a good idea!
Code works fine.

I referred to passing strings to #initialize. This certainly works.
But the more dramatic issue persists (see above).

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
J

Jesús Gabriel y Galán

Seems like I got it here:
http://www.ruby-forum.com/topic/204068

Is there any opportunity to add attributes to instance, not to class?

Send the define method to the singleton class of the object, instead
of sending it to the class:

irb(main):001:0> class Task
irb(main):002:1> def initialize options
irb(main):003:2> options.each_pair do |k,v|
irb(main):004:3* (class << self; self; end).send:)define_method, k, Proc.ne=
w{v})
irb(main):005:3> end
irb(main):006:2> end
irb(main):007:1> end
=3D> nil
irb(main):008:0> t =3D Task.new:)id =3D> 1)
=3D> #<Task:0xb7d4aca8>
irb(main):009:0> t.id
=3D> 1
irb(main):010:0> t2 =3D Task.new:)id =3D> 2)
=3D> #<Task:0xb7d3ecdc>
irb(main):012:0> t.id
=3D> 1
irb(main):013:0> t2.id
=3D> 2

Jesus.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top