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

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 :frowning:

Thanks for any suggestion.

Hi,

Iñaki Baz C. wrote:

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 :frowning:

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 H.

Hi –

On Sat, 3 May 2008, Iñaki Baz C. wrote:

“From”, “from”, “FROM”, “F”, “f” … => /^(from|f)$/i
end
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”)

That’s not legal Ruby. A method call isn’t an lvalue.

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 :frowning:

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 :slight_smile:

Specifically, I think you should stop thinking in terms of pointers.
Ruby doesn’t have them, so it’s never going to be an exact fit, and it
won’t take you very far in exploring Ruby techniques.

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.

David

El Sábado, 3 de Mayo de 2008, David A. Black escribió:

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”)

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 = 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 :slight_smile:

Well, in fact I’ve already done the parser (using TreeTop magic). But
it’s not
enought with parsing headers (as it would be in HTTP protocol) since I’m
doing a SIP stack and it can be a proxy (so some headers are modified,
new
added, some deleted… and the rest of message remains equal and is
forwarded
to other server.
That’s why I need an efficient way of accessing the @header array of
Header
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 “=” and use objects methods to
replace their content. Nice to know.

Thanks a lot.

Hi … <- private joke :slight_smile:

On Sat, 3 May 2008, Iñaki Baz C. wrote:

Please, let me know if I understand correctly why:

header(“From”) returns a value so I’m trying to do:
value1 = value2
that is not legal, is it?

Right; you can’t say, for example,

“a string” = 3

and every method call returns an object.

That’s why I need an efficient way of accessing the @header array of Header
Ok, so you mean that I should avoid using “=” and use objects methods to
replace their content. Nice to know.

You could combine these techniques, actually, if you did something
like:

class Message
def from_header=(h)
self.from_header.replace(h)
end
end

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

message.from_header = message.to_header

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

David

El Sábado, 3 de Mayo de 2008, David A. Black escribió:

  message.from_header = message.to_header

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

Great !!!