Tag: Ruby 1.9.2

Converting nested hash into HTTP url params hash version in Ruby

We cannot send nested hash as a param in HTTP requests. For example, when we would like to send something like this:

{:key => "value", :nested => {:nest => "value"}}

It would be (or should be) mapped like this:

/url/?key=value&nested=%7B%3Anest%3D%3E%5C%22value%5C%22%7D

Doesn't look to good ;) However there is a simple way to convert a nested hash into a params acceptable form. We can convert it to a form, that can be mapped into params like this:

/url/?key=value&nested[nest]=value

Here is method to convert any nested hash to a "one level" equivalent:

  module HashConverter

    def self.encode(value, key = nil, out_hash = {})
      case value
      when Hash  then 
        value.each { |k,v| encode(v, append_key(key,k), out_hash) }
        out_hash
      when Array then 
        value.each { |v| encode(v, "#{key}[]", out_hash) }
        out_hash
      when nil   then ''
      else
        out_hash[key] = value
        out_hash
      end
    end

    private

    def self.append_key(root_key, key)
      root_key.nil? ? :"#{key}" : :"#{root_key}[#{key.to_s}]"
    end

  end

And usage example:

hash = {:level0 => 'value', :nested => {:nest1 => "val1", :nest2 => "val2"}}
HashConverter.encode(hash)
#=> {:level0=>"value", :"nested[nest1]"=>"val1", :"nested[nest2]"=>"val2"}

This form can be easily mapped into a HTTP url params

Easy way to extend and overwrite bb-ruby bbcode gem translations in Ruby on Rails

When you go to bb-ruby gem readme, there is an instruction how to extend it with your own translations:

my_block = {
  'Quote' => [
    /\[quote(:.*)?=(.*?)\](.*?)\[\/quote\1?\]/mi,
    '<div class="quote"><p>\2</p><block>\3</block></div>',
    'Quote with citation',
    '[quote=mike]please quote me[/quote]',
    :quote
  ],      
}

text.bbcode_to_html(my_blockquote)

This method works quite good but well... it's way to inconvenient. Where should we put our translation? In our model? Should we create a different model which would store our costume translations? Nah... There is really easy and clean way to add new (and overwrite already existing) translations into a bbcode parser.

Create in your app initializers directory (/config/initializers/) a file called bb-ruby.rb. Below you can see an example with [spoiler][/spoiler] tag:

module BBRuby
  if @@tags
    @@tags['Spoiler'] = [
      /\[spoiler\](.*?)\[\/spoiler\1?\]/mi,
      '<span class="spoiler">\1</span>',
      'spoiler',
      '[spoiler]spoiler[/spoiler]',
      :spoiler]
  end
end

And how to overwrite existing translation? Just replace it with new one. Below example which replaces standard "Link" rule, with same rule but with rel="nofollow":

@@tags['Link'] = [
  /\[url=(.*?)\](.*?)\[\/url\]/mi,
  '<a href="\1" rel="nofollow">\2</a>',
  'Hyperlink to somewhere else',
  'Maybe try looking on [url=http://google.com]Google[/url]?',
  :link]

Copyright © 2025 Closer to Code

Theme by Anders NorenUp ↑