Recursive function problem

Hi all!

I have a problem with this function, which should return a formatted
string of an hash given as an argument:

def show_params(params, tabs_num)
params_str = String.new if tabs_num == -1
tabs_num++
params.each do |key, value|
tabs_num.times { params_str += “\t” }
if params.class != value.class
params_str += "#{key} => " + value.to_s + “\n”
else
params_str += “#{key} => \n”
show_params(value, tabs_num)
end
end
return params_str
end

I call the function with this:
show_params(params, -1)

obtaining thish error (in Rails):

undefined method `+@’ for {“action”=>“edit”, “id”=>“51”,
“controller”=>“items”}:HashWithIndifferentAccess

I cannot guess the reason! Any idea?

Thanks!

I don’t really know how to read the docs, but this seems like the kind
of
thing that I would expect the pp library to do for us. I tried about 15
different ways to get it to do this, and only ever got the same as the
default p function. If pp does address this issue, can someone explain
how
to get it to work?

Bravo!!!

I come from PHP and my first need was a function similar to print_r() (I
develop with Rails 2 now), so I just started (very lazily :slight_smile: ) to write
it… and you are giving me the code, written with a ruby philosophy!
Many thanks!!! Anyway, it’s less bizarre that a such modern language
doesn’t implement in native libraries these prehistorical functions, I
think…

On Tue, Oct 20, 2009 at 4:32 AM, Maurizio De santis <
[email protected]> wrote:

 if params.class != value.class

show_params(params, -1)
Posted via http://www.ruby-forum.com/.

In Ruby ++ isn’t defined
tabs_num++
should instead use += like this
tabs_num+=1


Also, you can specify default values for parameters, so
def show_params(params, tabs_num)
could be rewritten:
def show_params(params, tabs_num = -1)

Which would allow you to take the current call of
show_params(params, -1)
and instead call it like this
show_params(params)

This allows you to keep internal knowledge inside, people calling the
function shouldn’t have to know that they need to initialize some
internal
variable to -1


You still have an issue in that you only initialize the variable
params_str
on the first call to the function, so in the future calls, this variable
is
not defined, and you cannot then concatenate additional string to it. To
resolve this, remove the if on it, so that it is initialized for each
recursive call. Then you actually get some output. Now, what to do with
this
variable? Well, we want to take the results of the recursive calls, and
add
them into the current string. Notice right now you are saying

params_str += “#{key} => \n”
show_params(value, tabs_num)

But this second line does nothing, it calculates the substring, then
returns
it but nothing receives it or does anything with it. So instead, try

params_str += “#{key} => \n”
params_str += show_params(value, tabs_num)


Anyway, here is what I have, and it does what I think you are wanting it
to
do:

def show_params( params , tabs_num = -1 )
tabs_num += 1
params_str = String.new
params.each do |key, value|
params_str << “\t” * tabs_num
if value.is_a? Hash
params_str << “#{key.inspect} =>\n#{show_params value , tabs_num}”
else
params_str << “#{key.inspect} => #{value.inspect}\n”
end
end
params_str
end

params = { :abc => ‘def’ , 3 => {1=>true,2=>{‘xyz’=>/xyz/}} , 5 => 5 }
puts show_params(params)


I don’t really know how to read the docs, but this seems like the kind
of
thing that I would expect the pp library to do for us. I tried about 15
different ways to get it to do this, and only ever got the same as the
default p function. If pp does address this issue, can someone explain
how
to get it to work?

On Tue, Oct 20, 2009 at 9:30 AM, Aurora S.r.l.
[email protected]wrote:

I come from PHP and my first need was a function similar to print_r() (I
develop with Rails 2 now), so I just started (very lazily :slight_smile: ) to write
it… and you are giving me the code, written with a ruby philosophy!
Many thanks!!! Anyway, it’s less bizarre that a such modern language
doesn’t implement in native libraries these prehistorical functions, I
think…

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

Well, if you just need to look at it, inspect usually works. It’s just
when
you get long lists or lots of nesting, using inspect sometimes still
isn’t
enough. I really think that pp should do it, but can’t figure out how.

If I were doing it, myself, I would monkey patch it into the hash class,
something like this:

class Hash
def readable( tabs_num = -1 )
tabs_num += 1
self.inject(String.new)do | str , ( key , value ) |
rhs = value.is_a?(Hash) ? “\n#{value.readable tabs_num}” :
“#{value.inspect}\n”
str << “#{”\t" * tabs_num}#{key.inspect} => #{rhs}"
end
end
end

params = { :abc => ‘def’ , 3 => {1=>true,2=>{‘xyz’=>/xyz/}} , 5 => 5 }
puts params.readable

But some people here hate monkey patching, so I didn’t post that
earlier.

Also, I found that YAML gives something very similar to what we are
doing
here, with

require ‘yaml’
puts params.to_yaml