Merging hashes using both symbols and strings as keys

Discussion in 'Ruby' started by shenry, Oct 30, 2009.

  1. shenry

    shenry Guest

    I'm trying to merge to hashes, one using symbols as keys (the defined
    default values for my class) and the other using strings as keys
    (taken from the params hash).

    default = { :name => "Joe", :age => 50 }

    params = { "name" => "Bill" }

    new_hash = default.merge(params)
    >> { :name => "Joe", :age => 50, "name" => "Bill }


    What's the Ruby way to handle this so that it overwrites :name with
    "name"? Do I need to implement a stringify_keys or symbolize_keys
    method like in Rails? I'd like to avoid using strings as the keys in
    my default hash.

    Any help greatly appreciated.

    Stu
    shenry, Oct 30, 2009
    #1
    1. Advertising

  2. shenry wrote:
    > I'm trying to merge to hashes, one using symbols as keys (the defined
    > default values for my class) and the other using strings as keys
    > (taken from the params hash).
    >
    > default = { :name => "Joe", :age => 50 }
    >
    > params = { "name" => "Bill" }
    >
    > new_hash = default.merge(params)
    >>> { :name => "Joe", :age => 50, "name" => "Bill }

    >
    > What's the Ruby way to handle this so that it overwrites :name with
    > "name"? Do I need to implement a stringify_keys or symbolize_keys
    > method like in Rails? I'd like to avoid using strings as the keys in
    > my default hash.


    I would think it would be easiest to use something like symbolize_keys.
    Or just lift the whole HashWithIndifferentAccess class from Rails.

    >
    > Any help greatly appreciated.
    >
    > Stu


    Best,
    --
    Marnen Laibow-Koser
    http://www.marnen.org

    --
    Posted via http://www.ruby-forum.com/.
    Marnen Laibow-Koser, Oct 30, 2009
    #2
    1. Advertising

  3. shenry

    7stud -- Guest

    shenry wrote:
    > I'd like to avoid using strings as the keys in
    > my default hash.
    >


    h1 = { :name => "Joe", :age => 50 }
    h2 = { "name" => "Bill", :phone => "123-4567"}

    h2.each do |key, val|
    h1[key.to_sym] = val
    end

    p h1

    --output:--
    {:age=>50, :phone=>"123-4567", :name=>"Bill"}

    --
    Posted via http://www.ruby-forum.com/.
    7stud --, Oct 30, 2009
    #3
  4. shenry

    Intransition Guest

    On Oct 30, 12:10=A0pm, shenry <> wrote:
    > I'm trying to merge to hashes, one using symbols as keys (the defined
    > default values for my class) and the other using strings as keys
    > (taken from the params hash).
    >
    > default =3D { :name =3D> "Joe", :age =3D> 50 }
    >
    > params =3D { "name" =3D> "Bill" }
    >
    > new_hash =3D default.merge(params)
    >
    > >> { :name =3D> "Joe", :age =3D> 50, "name" =3D> "Bill }

    >
    > What's the Ruby way to handle this so that it overwrites :name with
    > "name"? Do I need to implement a stringify_keys or symbolize_keys
    > method like in Rails? I'd like to avoid using strings as the keys in
    > my default hash.
    >
    > Any help greatly appreciated.


    require 'facets/hash/rekey'

    default.merge(params.rekey)

    rekey takes a block, without a block it is the same as:

    rekey(&:to_sym)
    Intransition, Nov 1, 2009
    #4
  5. 2009/10/30 7stud -- <>:
    > shenry wrote:
    >> I'd like to avoid using strings as the keys in
    >> my default hash.
    >>

    >
    > h1 =3D =A0{ :name =3D> "Joe", :age =3D> 50 }
    > h2 =3D { "name" =3D> "Bill", :phone =3D> "123-4567"}
    >
    > h2.each do |key, val|
    > =A0h1[key.to_sym] =3D val
    > end
    >
    > p h1
    >
    > --output:--
    > {:age=3D>50, :phone=3D>"123-4567", :name=3D>"Bill"}


    Typically you do not want to modify defaults so I'd probably do

    irb(main):001:0> default =3D { :name =3D> "Joe", :age =3D> 50 }.freeze
    =3D> {:name=3D>"Joe", :age=3D>50}
    irb(main):002:0> params =3D { "name" =3D> "Bill" }
    =3D> {"name"=3D>"Bill"}
    irb(main):003:0> new_hash =3D default.dup
    =3D> {:name=3D>"Joe", :age=3D>50}
    irb(main):004:0> params.each {|k,v| new_hash[k.to_sym]=3Dv}
    =3D> {"name"=3D>"Bill"}
    irb(main):005:0> new_hash
    =3D> {:name=3D>"Bill", :age=3D>50}

    If you are allowed to change params you could do

    irb(main):001:0> default =3D { :name =3D> "Joe", :age =3D> 50 }.freeze
    =3D> {:name=3D>"Joe", :age=3D>50}
    irb(main):002:0> params =3D { "name" =3D> "Bill" }
    =3D> {"name"=3D>"Bill"}
    irb(main):003:0> default.each {|k,v| params[k.to_s] ||=3D v}
    =3D> {:name=3D>"Joe", :age=3D>50}
    irb(main):004:0> params
    =3D> {"name"=3D>"Bill", "age"=3D>50}

    Kind regards

    robert


    --=20
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
    Robert Klemme, Nov 2, 2009
    #5
  6. shenry

    Josh Cheek Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Fri, Oct 30, 2009 at 11:10 AM, shenry <> wrote:

    > I'm trying to merge to hashes, one using symbols as keys (the defined
    > default values for my class) and the other using strings as keys
    > (taken from the params hash).
    >
    > default = { :name => "Joe", :age => 50 }
    >
    > params = { "name" => "Bill" }
    >
    > new_hash = default.merge(params)
    > >> { :name => "Joe", :age => 50, "name" => "Bill }

    >
    > What's the Ruby way to handle this so that it overwrites :name with
    > "name"? Do I need to implement a stringify_keys or symbolize_keys
    > method like in Rails? I'd like to avoid using strings as the keys in
    > my default hash.
    >
    > Any help greatly appreciated.
    >
    > Stu
    >
    >


    Hi, I made a small module called SymbolizeKeys that will allow you to extend
    the hash you are interested in applying this behaviour to, you can then use
    it like this:

    default = { :name => "Joe", :age => 50 }.extend(SymbolizeKeys)

    params = { "name" => "Bill" }

    default.merge(params) # => {:age=>50, :name=>"Bill"}


    I'm going through "Ruby Best Practices" right now, which touches on testing
    in the first chapter. This seemed like a good opportunity to practice that
    (while I eagerly await PragProg's RSpec book), so I'll include the tests I
    wrote.

    If anyone has relevant thoughts / criticisms, I welcome them (I don't
    promise to agree, though). Is extending the object a wise approach? Are my
    tests appropriate / follow good testing methodologies? Is there a better way
    to implement anything I've done?




    # file: symbolize_keys.rb

    module SymbolizeKeys

    # converts any current string keys to symbol keys
    def self.extended(hash)
    hash.each do |key,value|
    if key.is_a?(String)
    hash.delete key
    hash[key] = value #through overridden []=
    end
    end
    end

    # assigns a new key/value pair
    # converts they key to a symbol if it is a string
    def []=(*args)
    args[0] = args[0].to_sym if args[0].is_a?(String)
    super
    end

    # returns new hash which is the merge of self and other hashes
    # the returned hash will also be extended by SymbolizeKeys
    def merge(*other_hashes , &resolution_proc )
    merged = Hash.new.extend SymbolizeKeys
    merged.merge! self , *other_hashes , &resolution_proc
    end

    # merges the other hashes into self
    # if a proc is submitted , it's return will be the value for the key
    def merge!( *other_hashes , &resolution_proc )

    # default resolution: value of the other hash
    resolution_proc ||= proc{ |key,oldval,newval| newval }

    # merge each hash into self
    other_hashes.each do |hash|
    hash.each{ |k,v|
    # assign new k/v into self, resolving conflicts with resolution_proc
    self[k] = self.has_key?(k) ? resolution_proc[k,self[k],v] : v
    }
    end

    self
    end

    end


    --------------------------------------------------


    # file: symbolize_keys_test.rb

    require 'test/unit'
    require 'symbolize_keys'

    # this method was written by Gregory Brown
    # and comes from
    http://github.com/sandal/rbp/blob/7...e2432f0db7cb8/testing/test_unit_extensions.rb
    module Test::Unit
    # Used to fix a minor minitest/unit incompatibility in flexmock
    AssertionFailedError = Class.new(StandardError)

    class TestCase

    def self.must(name, &block)
    test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
    defined = instance_method(test_name) rescue false
    raise "#{test_name} is already defined in #{self}" if defined
    if block_given?
    define_method(test_name, &block)
    else
    define_method(test_name) do
    flunk "No implementation provided for #{name}"
    end
    end
    end

    end
    end


    class ExtendingWithSymbolizeKeysTest < Test::Unit::TestCase
    def setup
    @default = {
    :age => 50 ,
    'initially a string' => 51 ,
    /neither string nor symbol/ => 52 ,
    }
    @default.extend SymbolizeKeys
    end

    must "convert string keys to symbols when extended" do
    assert_nil @default[ 'initially a string']
    assert_equal @default[:'initially a string'] , 51
    end

    must "leave symbol keys as symbols" do
    assert_equal @default[:age] , 50
    end

    must 'leave non symbols / strings as they are' do
    assert_equal @default[/neither string nor symbol/] , 52
    end

    end


    class SettingKeysWithSymbolizeKeysTest < Test::Unit::TestCase
    def setup
    @default = Hash.new.extend SymbolizeKeys

    end

    must "convert string keys to symbols" do
    @default['foo'] = :bar
    assert_equal @default[:foo] , :bar
    end

    must "leave symbol keys as symbols" do
    @default[:foo] = :bar
    assert_equal @default[:foo] , :bar
    end

    must 'leave non symbols / strings as they are' do
    @default[/foo/] = :bar
    assert_equal @default[/foo/] , :bar
    end

    end


    class MergingWithSymbolizeKeysTest < Test::Unit::TestCase
    def setup
    @default = {
    :name => 'Joe' ,
    :age => 50 ,
    'initially a string' => 51 ,
    /neither string nor symbol/ => 52 ,
    :'from default' => :default ,
    }
    @params1 = {
    :name => 'Bill' ,
    'alias' => 'Billy' ,
    :'from params1' => :params1 ,
    }
    @params2 = {
    'name' => 'Sam' ,
    'alias' => 'Sammy' ,
    12 => 'favourite number' ,
    :'from params2' => :params2 ,
    }
    @default.extend SymbolizeKeys
    end

    must "retain new keys for merge" do
    merged = @default.merge(@params2)
    assert_equal merged[12] , 'favourite number'
    end

    must "retain new keys for merge!" do
    @default.merge!(@params2)
    assert_equal @default[12] , 'favourite number'
    end

    must "replace current values with new values for merge" do
    merged = @default.merge(@params1)
    assert_equal merged[:name] , 'Bill'
    end

    must "replace current values with new values for merge!" do
    @default.merge!(@params1)
    assert_equal @default[:name] , 'Bill'
    end

    must "not change original hash for merge" do
    @default.merge(@params1)
    assert_equal @default[:name] , 'Joe'
    end

    must "receive [key,oldval,newval] as params to block" do
    h1 = {:no_conflict_1 => 1 , :conflict => 2 }.extend(SymbolizeKeys)
    h2 = {:conflict => 3 , :no_conflict_2 => 4}
    resolution_proc_params = nil
    h1.merge(h2){ |*params| resolution_proc_params = params }
    assert_equal resolution_proc_params , [:conflict,2,3]
    end

    must "replace resolve conflicts with block for merge" do
    merged = @default.merge(@params1){ |key,oldval,newval| oldval }
    assert_equal merged[:name] , 'Joe'

    merged = @default.merge(@params1){ |key,oldval,newval| newval }
    assert_equal merged[:name] , 'Bill'
    end

    must "replace resolve conflicts with block for merge!" do
    @default.merge!(@params1){ |key,oldval,newval| oldval }
    assert_equal @default[:name] , 'Joe'

    @default.merge!(@params1){ |key,oldval,newval| newval }
    assert_equal @default[:name] , 'Bill'
    end

    must "convert string keys to symbols for merge" do
    merged = @default.merge(@params1)
    assert_nil merged['alias']
    assert_equal merged[ :alias] , 'Billy'
    end

    must "convert string keys to symbols for merge!" do
    @default.merge!(@params1)
    assert_nil @default['alias']
    assert_equal @default[ :alias] , 'Billy'
    end

    must "merge with multiple hashes" do
    merged = @default.merge(@params1,@params2)
    assert_equal merged[:'from default'] , :default
    assert_equal merged[:'from params1'] , :params1
    assert_equal merged[:'from params2'] , :params2
    end

    must "merge! with multiple hashes" do
    @default.merge!(@params1,@params2)
    assert_equal @default[:'from default'] , :default
    assert_equal @default[:'from params1'] , :params1
    assert_equal @default[:'from params2'] , :params2
    end

    must "return object that is extended with SymbolizeKeys, for merge" do
    merged = @default.merge(@params1)
    assert_kind_of SymbolizeKeys , merged
    end

    must "not modify original hash, for merge" do
    original = @default.dup
    @default.merge(@params1,@params2)
    assert_equal original , @default
    end

    end
    Josh Cheek, Nov 3, 2009
    #6
  7. shenry

    Josh Cheek Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Fri, Oct 30, 2009 at 11:10 AM, shenry <> wrote:

    > I'm trying to merge to hashes, one using symbols as keys (the defined
    > default values for my class) and the other using strings as keys
    > (taken from the params hash).
    >
    > default = { :name => "Joe", :age => 50 }
    >
    > params = { "name" => "Bill" }
    >
    > new_hash = default.merge(params)
    > >> { :name => "Joe", :age => 50, "name" => "Bill }

    >
    > What's the Ruby way to handle this so that it overwrites :name with
    > "name"? Do I need to implement a stringify_keys or symbolize_keys
    > method like in Rails? I'd like to avoid using strings as the keys in
    > my default hash.
    >
    > Any help greatly appreciated.
    >
    > Stu
    >
    >

    I decided that I wasn't happy with the tests, it should be able to access
    the same object through either a string or a symbol (previously it just
    turned everything into a symbol, then if you tried to access that object w/
    the string, it would not find it).

    So I overrode [] and has_key? also, and changed some of the tests.

    Here is the updated version



    # file: symbolize_keys.rb

    module SymbolizeKeys

    # converts any current string keys to symbol keys
    def self.extended(hash)
    hash.each do |key,value|
    if key.is_a?(String)
    hash.delete key
    hash[key] = value #through overridden []=
    end
    end
    end

    #considers string keys and symbol keys to be the same
    def [](key)
    key = convert_key(key)
    super(key)
    end

    #considers string keys and symbol keys to be the same
    def has_key?(key)
    key = convert_key(key)
    super(key)
    end

    # assigns a new key/value pair
    # converts they key to a symbol if it is a string
    def []=(*args)
    args[0] = convert_key(args[0])
    super
    end

    # returns new hash which is the merge of self and other hashes
    # the returned hash will also be extended by SymbolizeKeys
    def merge(*other_hashes , &resolution_proc )
    merged = Hash.new.extend SymbolizeKeys
    merged.merge! self , *other_hashes , &resolution_proc
    end

    # merges the other hashes into self
    # if a proc is submitted , it's return will be the value for the key
    def merge!( *other_hashes , &resolution_proc )

    # default resolution: value of the other hash
    resolution_proc ||= proc{ |key,oldval,newval| newval }

    # merge each hash into self
    other_hashes.each do |hash|
    hash.each{ |k,v|
    # assign new k/v into self, resolving conflicts with resolution_proc
    self[k] = self.has_key?(k) ? resolution_proc[k.to_sym,self[k],v] : v
    }
    end

    self
    end

    private

    def convert_key(key)
    key.is_a?(String) ? key.to_sym : key
    end

    end


    --------------------------------------------------


    # file: symbolize_keys_test.rb

    require 'test/unit'
    require 'symbolize_keys'

    # this method was written by Gregory Brown
    # and comes from
    http://github.com/sandal/rbp/blob/7...e2432f0db7cb8/testing/test_unit_extensions.rb
    module Test::Unit
    # Used to fix a minor minitest/unit incompatibility in flexmock
    AssertionFailedError = Class.new(StandardError)

    class TestCase

    def self.must(name, &block)
    test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
    defined = instance_method(test_name) rescue false
    raise "#{test_name} is already defined in #{self}" if defined
    if block_given?
    define_method(test_name, &block)
    else
    define_method(test_name) do
    flunk "No implementation provided for #{name}"
    end
    end
    end

    end
    end


    class ExtendingWithSymbolizeKeysTest < Test::Unit::TestCase
    def setup
    @default = {
    :age => 50 ,
    'initially a string' => 51 ,
    /neither string nor symbol/ => 52 ,
    }
    @default.extend SymbolizeKeys
    end

    must "convert string keys to symbols when extended" do
    assert_equal @default[:'initially a string'] , 51
    end

    must "sym/str keys can access through either, but only one key" do
    assert_equal @default[ 'initially a string'] , 51
    assert_equal @default[:'initially a string'] , 51
    assert_equal @default[:'initially a string'] , @default['initially a
    string']
    assert_equal @default.size , 3
    end

    must "leave symbol keys as symbols" do
    assert_equal @default[:age] , 50
    end

    must 'leave non symbols / strings as they are' do
    assert_equal @default[/neither string nor symbol/] , 52
    end

    end


    class SettingKeysWithSymbolizeKeysTest < Test::Unit::TestCase
    def setup
    @default = Hash.new.extend SymbolizeKeys
    end

    must "enable access to strings through symbols" do
    @default['foo'] = 'bar'
    assert_equal @default[:foo] , 'bar'
    assert_same @default[:foo] , @default['foo']
    end

    must "enable access to symbols through strings" do
    @default[:foo] = 'bar'
    assert_equal @default['foo'] , 'bar'
    assert_same @default[:foo] , @default['foo']
    end

    must 'leave non symbols / strings as they are' do
    @default[/foo/] = :bar
    assert_equal @default[/foo/] , :bar
    end

    end


    class MergingWithSymbolizeKeysTest < Test::Unit::TestCase
    def setup
    @default = {
    :name => 'Joe' ,
    :age => 50 ,
    'initially a string' => 51 ,
    /neither string nor symbol/ => 52 ,
    :'from default' => :default ,
    }
    @params1 = {
    :name => 'Bill' ,
    'alias' => 'Billy' ,
    :'from params1' => :params1 ,
    }
    @params2 = {
    'name' => 'Sam' ,
    'alias' => 'Sammy' ,
    12 => 'favourite number' ,
    :'from params2' => :params2 ,
    }
    @default.extend SymbolizeKeys
    end

    must "retain new keys for merge" do
    merged = @default.merge(@params2)
    assert_equal merged[12] , 'favourite number'
    end

    must "retain new keys for merge!" do
    @default.merge!(@params2)
    assert_equal @default[12] , 'favourite number'
    end

    must "replace current values with new values for merge" do
    merged = @default.merge(@params1)
    assert_equal merged[:name] , 'Bill'
    end

    must "replace current values with new values for merge!" do
    @default.merge!(@params1)
    assert_equal @default[:name] , 'Bill'
    end

    must "not change original hash for merge" do
    @default.merge(@params1)
    assert_equal @default[:name] , 'Joe'
    end

    must "receive [key,oldval,newval] as params to block" do
    h1 = {:no_conflict_1 => 1 , :conflict => 2 }.extend(SymbolizeKeys)
    h2 = {:conflict => 3 , :no_conflict_2 => 4}
    resolution_proc_params = nil
    h1.merge(h2){ |*params| resolution_proc_params = params }
    assert_equal resolution_proc_params , [:conflict,2,3]
    end

    must "only invoke the resolution proc on conflicts" do
    conflict_count = 0
    conflicts = { :name => false , :alias => false }
    @params1.extend(SymbolizeKeys).merge(@params2) do |k,ov,nv|
    conflict_count += 1
    conflicts[k] = true
    end
    assert_equal conflict_count , 2
    assert conflicts[:name]
    assert conflicts[:alias]
    end

    must "replace resolve conflicts with block for merge" do
    merged = @default.merge(@params1){ |key,oldval,newval| oldval }
    assert_equal merged[:name] , 'Joe'

    merged = @default.merge(@params1){ |key,oldval,newval| newval }
    assert_equal merged[:name] , 'Bill'
    end

    must "replace resolve conflicts with block for merge!" do
    @default.merge!(@params1){ |key,oldval,newval| oldval }
    assert_equal @default[:name] , 'Joe'

    @default.merge!(@params1){ |key,oldval,newval| newval }
    assert_equal @default[:name] , 'Bill'
    end

    must "convert string keys to symbols for merge" do
    unique_keys = @default.keys.map{|k|k.to_s.to_sym} |
    @params1.keys.map{|k|k.to_s.to_sym}
    merged = @default.merge(@params1)
    assert_equal merged['alias'] , 'Billy'
    assert_equal merged[ :alias] , 'Billy'
    assert_equal merged.size , unique_keys.size
    end

    must "convert string keys to symbols for merge!" do
    unique_keys = @default.keys.map{|k|k.to_s.to_sym} |
    @params1.keys.map{|k|k.to_s.to_sym}
    @default.merge!(@params1)
    assert_equal @default['alias'] , 'Billy'
    assert_equal @default[ :alias] , 'Billy'
    assert_equal @default.size , unique_keys.size
    end

    must "merge with multiple hashes" do
    merged = @default.merge(@params1,@params2)
    assert_equal merged[:'from default'] , :default
    assert_equal merged[:'from params1'] , :params1
    assert_equal merged[:'from params2'] , :params2
    end

    must "merge! with multiple hashes" do
    @default.merge!(@params1,@params2)
    assert_equal @default[:'from default'] , :default
    assert_equal @default[:'from params1'] , :params1
    assert_equal @default[:'from params2'] , :params2
    end

    must "return object that is extended with SymbolizeKeys, for merge" do
    merged = @default.merge(@params1)
    assert_kind_of SymbolizeKeys , merged
    end

    must "not modify original hash, for merge" do
    original = @default.dup
    @default.merge(@params1,@params2)
    assert_equal original , @default
    end

    end
    Josh Cheek, Nov 3, 2009
    #7
  8. 2009/11/3 Josh Cheek <>:

    > Here is the updated version


    Josh, I believe it's better to create a gist for code of that length
    and paste the link only. That makes it easier to follow - especially
    since you'll get code highlighting and versioning for free.

    Kind regards

    robert

    --
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
    Robert Klemme, Nov 3, 2009
    #8
  9. shenry

    Josh Cheek Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Tue, Nov 3, 2009 at 7:06 AM, Robert Klemme <>wrote:

    > 2009/11/3 Josh Cheek <>:
    >
    > > Here is the updated version

    >
    > Josh, I believe it's better to create a gist for code of that length
    > and paste the link only. That makes it easier to follow - especially
    > since you'll get code highlighting and versioning for free.
    >
    > Kind regards
    >
    > robert
    >
    > --
    > remember.guy do |as, often| as.you_can - without end
    > http://blog.rubybestpractices.com/
    >
    >

    Hi, Robert, I always thought that too, but I was told I should put them in
    the email in case the host site went down (
    http://www.ruby-forum.com/topic/192987#841723 )

    Is there some standard that I can follow, because there seems to be
    conflicts of opinion regarding the best approach.
    Josh Cheek, Nov 3, 2009
    #9
  10. shenry

    Paul Smith Guest

    On Tue, Nov 3, 2009 at 1:22 PM, Josh Cheek <> wrote:
    > On Tue, Nov 3, 2009 at 7:06 AM, Robert Klemme <=
    >wrote:
    >
    >> 2009/11/3 Josh Cheek <>:
    >>
    >> > Here is the updated version

    >>
    >> Josh, I believe it's better to create a gist for code of that length
    >> and paste the link only. =A0That makes it easier to follow - especially
    >> since you'll get code highlighting and versioning for free.
    >>
    >> Kind regards
    >>
    >> robert
    >>
    >> --
    >> remember.guy do |as, often| as.you_can - without end
    >> http://blog.rubybestpractices.com/
    >>
    >>

    > Hi, Robert, I always thought that too, but I was told I should put them i=

    n
    > the email in case the host site went down (
    > http://www.ruby-forum.com/topic/192987#841723 )
    >
    > Is there some standard that I can follow, because there seems to be
    > conflicts of opinion regarding the best approach.
    >


    A big difference here is that a pastie is only available through
    pastie.org, a gist is a git repository that can be cloned.

    --=20
    Paul Smith
    http://www.nomadicfun.co.uk

    Paul Smith, Nov 3, 2009
    #10
  11. shenry

    Josh Cheek Guest

    [Note: parts of this message were removed to make it a legal post.]

    On Tue, Nov 3, 2009 at 7:27 AM, Paul Smith <> wrote:

    >
    > A big difference here is that a pastie is only available through
    > pastie.org, a gist is a git repository that can be cloned.
    >



    Here is the code in a gist http://gist.github.com/225048
    Josh Cheek, Nov 3, 2009
    #11
  12. 2009/11/3 Josh Cheek <>:
    > On Tue, Nov 3, 2009 at 7:06 AM, Robert Klemme <=
    >wrote:
    >
    >> 2009/11/3 Josh Cheek <>:
    >>
    >> > Here is the updated version

    >>
    >> Josh, I believe it's better to create a gist for code of that length
    >> and paste the link only. =A0That makes it easier to follow - especially
    >> since you'll get code highlighting and versioning for free.


    > Hi, Robert, I always thought that too, but I was told I should put them i=

    n
    > the email in case the host site went down (
    > http://www.ruby-forum.com/topic/192987#841723 )


    Well, it seems both sides have valid and good arguments. :) The only
    footnote I'd put on that statement is: the real disadvantage of
    pastebin and similar services is that they are typically intended for
    short lived data only and may or actually do delete older content. A
    gist on the other hand belongs to an account and lives as long as that
    account lives or the gist is deleted. Of course, since this is
    separate from the posting the issue remains that the posting can be
    available and the code not...

    > Is there some standard that I can follow, because there seems to be
    > conflicts of opinion regarding the best approach.


    No written standard as far as I know. So you're back to square and
    have to decide yourself. :)

    Kind regards

    robert

    --=20
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
    Robert Klemme, Nov 3, 2009
    #12
  13. On Tue, Nov 3, 2009 at 8:40 AM, Josh Cheek <> wrote:
    > On Tue, Nov 3, 2009 at 7:27 AM, Paul Smith <> wrote:
    >
    >>
    >> A big difference here is that a pastie is only available through
    >> pastie.org, a gist is a git repository that can be cloned.
    >>

    >
    >
    > Here is the code in a gist http://gist.github.com/225048


    It might be of interest to note that this code basically take the
    opposite tack from the HashWithIndifferentAccess which is part of
    ActiveSupport and therefore Rails.

    HashWithIndifferentAccess (which I'll abbreviate to HWIA) converts
    symbol keys to strings in the access methods ([], []= etc.) Contrary
    to some people's thinking (including mine when I first encountered it)
    the actual keys in the hash are strings, not symbols.

    The trade-offs between the two approaches include:

    1) Symbols once created can't be garbage collected. Since Rails uses
    HWIA for things like the params hash, and the keys come from parts of
    arbitrary client provided URIs this could be an opening for a DOS
    attack which creates tons of useless extra parameters which result in
    non-GCable symbols. Since HWIA uses strings, for the keys, keys
    coming from query parameters and the like never get turned into
    symbols. The only symbols will be those coming from the application
    itself.

    2) Using strings for the keys is slightly slower on access because
    computing the hash value of a string is O(length of the string) while
    the hash value of a symbol is computed once and is O(1) subsequently.
    On the other hand this only becomes significant if the same key is
    used to access the hash multiple times, since interning a string as a
    symbol requires computing the hash of the string anyway.

    In practice, and particularly for the typical usage in Rails apps, I
    doubt that there's any real effect on performance from storing strings
    rather than symbols for the keys. The main advantage of HWIA is that
    it allows you to save a keystroke

    params[:id]
    vs
    params['id']

    and some think the former looks a little bit nicer. Although this is
    no doubt a potential source of controversy. I for one have a slight
    preference for the :id form, but that might be the result of Stockholm
    syndrome having worked on so many Rails apps.
    --
    Rick DeNatale

    Blog: http://talklikeaduck.denhaven2.com/
    Twitter: http://twitter.com/RickDeNatale
    WWR: http://www.workingwithrails.com/person/9021-rick-denatale
    LinkedIn: http://www.linkedin.com/in/rickdenatale
    Rick DeNatale, Nov 3, 2009
    #13
  14. Hi --

    On Tue, 3 Nov 2009, Rick DeNatale wrote:

    > params[:id]
    > vs
    > params['id']
    >
    > and some think the former looks a little bit nicer. Although this is
    > no doubt a potential source of controversy. I for one have a slight
    > preference for the :id form, but that might be the result of Stockholm
    > syndrome having worked on so many Rails apps.


    When it involves Rails, we call it "Copenhagen Syndrome" :)


    David

    --
    The Ruby training with D. Black, G. Brown, J.McAnally
    Compleat Jan 22-23, 2010, Tampa, FL
    Rubyist http://www.thecompleatrubyist.com

    David A. Black/Ruby Power and Light, LLC (http://www.rubypal.com)
    David A. Black, Nov 3, 2009
    #14
  15. On Tue, Nov 3, 2009 at 9:31 AM, David A. Black <> wrote:
    > Hi --
    >
    > On Tue, 3 Nov 2009, Rick DeNatale wrote:
    >
    >> =A0params[:id]
    >> vs
    >> =A0params['id']
    >>
    >> and some think the former looks a little bit nicer. =A0Although this is
    >> no doubt a potential source of controversy. =A0I for one have a slight
    >> preference for the :id form, but that might be the result of Stockholm
    >> syndrome having worked on so many Rails apps.

    >
    > When it involves Rails, we call it "Copenhagen Syndrome" :)


    I dunno, there IS a bit of Chicago mixed in.

    I have to repeat the story I told at the end of my RubyConf
    presentation last year, about the classification of OO languages by
    geographic origin:

    Smalltalk (which came from Xerox Parc in California) is the surfer's
    language, Smalltalk programmers wear baggy swimsuits, and hang loose.

    ObjectiveC (which came from an ITT lab in Connecticut) was a "New
    England Yankee" language, it did just what it had to do and nothing
    more. (Not sure this is still true)

    Eiffel (the brainchild of Bertrand Meyer) was/is "quintessentially French=
    ")

    and

    C++ (from Bjarne Stroustrup, a compatriot of DHH, and who at the
    time was at Bell/ATT labs) is like Haagen Dazs Ice Cream, you think
    it's from Scandanavia, but it's really an industrial product from New
    Jersey!


    --=20
    Rick DeNatale

    Blog: http://talklikeaduck.denhaven2.com/
    Twitter: http://twitter.com/RickDeNatale
    WWR: http://www.workingwithrails.com/person/9021-rick-denatale
    LinkedIn: http://www.linkedin.com/in/rickdenatale
    Rick DeNatale, Nov 3, 2009
    #15
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Steven Arnold

    using hashes as keys in hashes

    Steven Arnold, Nov 23, 2005, in forum: Ruby
    Replies:
    3
    Views:
    158
    Mauricio Fernández
    Nov 23, 2005
  2. Giles Bowkett
    Replies:
    13
    Views:
    234
    Jacob Fugal
    Mar 15, 2007
  3. Andy Pipes
    Replies:
    6
    Views:
    122
    Andy Pipes
    Sep 30, 2008
  4. Tim O'Donovan

    Hash of hashes, of hashes, of arrays of hashes

    Tim O'Donovan, Oct 27, 2005, in forum: Perl Misc
    Replies:
    5
    Views:
    202
  5. Derek Basch

    Merging potentially undefined hashes

    Derek Basch, Jun 9, 2006, in forum: Perl Misc
    Replies:
    15
    Views:
    195
    Brad Baxter
    Jun 13, 2006
Loading...

Share This Page