How to access to an Array element without doing "find" each time

  • Thread starter Iñaki Baz Castillo
  • Start date
I

Iñaki Baz Castillo

Hi, I've an Array containing complex objects of Header class:

=2D------------------------------------
class Header
#attributes:
# - @name
# - @original_value
# - @parsed_value
# ...
end

class Message
#attributes:
# - @first_line
# - @headers =3D
# [header_1, header_2, header_3...]
# - @body
end
=2D------------------------------------

Just some headers are parsed, and for a header "From", @name attribute can =
be:
"From", "from", "FROM", "F", "f" ... =3D> /^(from|f)$/i


Now I need to access a specifi header ("From" for example) several times an=
d I=20
want to avoid doing a "Header.find { |h| h.name =3D~ /^(from|f)$/i }" for =
each=20
access,so:

class Message
def header(name)
Header.find { |h| h.name =3D~ /^(from|f)$/i }
end
end


But doing message.header("From") for each access will be not very efficient=
=20
and I try to avoid it. Is there any other way?

I could doing an assigment just the first time:

message.hdr_from =3D message.header("From")
...do_somethig_with_hdr_from... :
message.hdr_from.parsed_value.uri
message.hdr_from.parsed_value.uri.name
message.hdr_from.parsed_value.display_name
...

So "hdr_from" is like a pointer to header("From"), but it's not valid for m=
e=20
since I need the possibility of doing a re-assignement:

header("From") =3D header("To")

So if after doing that I use "message.hdr_from" I will access to the previo=
us=20
value of "From" header instead of the new one.


In fact, what I'm looking for is a persister pointer, concept that I alread=
y=20
know doesn't exist in Ruby :(

Thanks for any suggestion.



=2D-=20
I=C3=B1aki Baz Castillo
 
H

Heesob Park

Hi,

Iñaki Baz Castillo said:
Hi, I've an Array containing complex objects of Header class:

-------------------------------------
class Header
#attributes:
# - @name
# - @original_value
# - @parsed_value
# ...
end

class Message
#attributes:
# - @first_line
# - @headers =
# [header_1, header_2, header_3...]
# - @body
end
-------------------------------------

Just some headers are parsed, and for a header "From", @name attribute
can be:
"From", "from", "FROM", "F", "f" ... => /^(from|f)$/i


Now I need to access a specifi header ("From" for example) several times
and I
want to avoid doing a "Header.find { |h| h.name =~ /^(from|f)$/i }" for
each
access,so:

class Message
def header(name)
Header.find { |h| h.name =~ /^(from|f)$/i }
end
end


But doing message.header("From") for each access will be not very
efficient
and I try to avoid it. Is there any other way?

I could doing an assigment just the first time:

message.hdr_from = message.header("From")
...do_somethig_with_hdr_from... :
message.hdr_from.parsed_value.uri
message.hdr_from.parsed_value.uri.name
message.hdr_from.parsed_value.display_name
...

So "hdr_from" is like a pointer to header("From"), but it's not valid
for me
since I need the possibility of doing a re-assignement:

header("From") = header("To")

So if after doing that I use "message.hdr_from" I will access to the
previous
value of "From" header instead of the new one.


In fact, what I'm looking for is a persister pointer, concept that I
already
know doesn't exist in Ruby :(
How about use class variable something like this:

class Message
def initialize

@@header = {}
end
def header(name)
return @@header[name] ||= @headers.find { |h| h.name =~
/^(from|f)$/i }
end
end

Thanks for any suggestion.

Regards,
Park Heesob
 
I

Iñaki Baz Castillo

El S=C3=A1bado, 3 de Mayo de 2008, David A. Black escribi=C3=B3:
That's not legal Ruby. A method call isn't an lvalue.

Oh, yes, you are right!
Please, let me know if I understand correctly why:

header("From") returns a value so I'm trying to do:
value1 =3D value2
that is not legal, is it?

My advice is to try to learn to think in Ruby, so that you don't keep
experiencing frustration because of what you perceive Ruby as not
having. Believe me, Ruby is definitely feature-rich enough to parse
headers :)

Well, in fact I've already done the parser (using TreeTop magic). But it's =
not=20
enought with parsing headers (as it would be in HTTP protocol) since I'm=20
doing a SIP stack and it can be a proxy (so some headers are modified, new=
=20
added, some deleted... and the rest of message remains equal and is forward=
ed=20
to other server.
That's why I need an efficient way of accessing the @header array of Header=
=20
objets, parse just one of them and keep the whole message as it arrived.


A lot of Ruby objects need to change their state or contents, without
changing what object they are. Methods like Array#replace,
String#replace, and many others, do exactly that. Maybe your message
objects could "replace" headers with each other, or something like
that.

Ok, so you mean that I should avoid using "=3D" and use objects methods to=
=20
replace their content. Nice to know.


Thanks a lot.






=2D-=20
I=C3=B1aki Baz Castillo
 
I

Iñaki Baz Castillo

El S=C3=A1bado, 3 de Mayo de 2008, David A. Black escribi=C3=B3:
You could combine these techniques, actually, if you did something
like:

=C2=A0 =C2=A0class Message
=C2=A0 =C2=A0 =C2=A0def from_header=3D(h)
=C2=A0 =C2=A0 =C2=A0 =C2=A0self.from_header.replace(h)
=C2=A0 =C2=A0 =C2=A0end
=C2=A0 =C2=A0end

That's almost pseudo-code, but the point is you could then do:

=C2=A0 =C2=A0message.from_header =3D message.to_header

or whatever. That's the great thing about the "=3D"-methods; they let
you use assignment semantics for method calls, and you can of course
define the method yourself.


Great !!!

=2D-=20
I=C3=B1aki Baz Castillo
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top