From: David MacMahon Date: 2013-02-08T02:34:05+09:00 Subject: [ruby-core:51994] Re: [ruby-trunk - Feature #7792] Make symbols and strings the same thing On Feb 7, 2013, at 3:00 AM, rosenfeld (Rodrigo Rosenfeld Rosas) wrote: > > Issue #7792 has been updated by rosenfeld (Rodrigo Rosenfeld Rosas). > > > rosenfeld (Rodrigo Rosenfeld Rosas) wrote: > >> cache = Redis.new >> users = cache['users'] || begin >> db = Sequel.connect('postgres://user:password@localhost/mydb') >> cache['users'] = db[:users].select(:id, :name).map{|r| id: r[:id], >> name: r[:name]} # or just select(:id, :name).all > > Sorry, I forgot the JSON conversion in the example above: > > cache = Redis.new > db = Sequel.connect('postgres://user:password@localhost/mydb') > users = if cached = cache['users'] > JSON.parse cached > else > db[:users].select(:id, :name).all.tap{|u| cache['users'] = JSON.unparse u} > end I still think the fundamental issue is that Sequel is returning something that contains symbols, but JSON.parse(JSON.unparse(x)) will never return anything containing a symbol even if x does. Because of this the "users" variable is assigned something that contains symbols in one case and something that contains no symbols in all other cases. IMHO, the example shows not a deficiency in the Ruby language itself but rather a (subtle, easy to fall victim to) coding pitfall of not properly managing/reconciling the incompatible return types from the two libraries. > I know the code above could be simplified, but I'm avoid the parse -> unparse operation when it is not required (although it would make the code always work in this case): > > users = JSON.parse (cache['users'] ||= JSON.unparse db[:users].select(:id, :name).all) This seems an excellent solution IMHO as it clearly results in "users" being assigned the return value of JSON.parse every time and only results in one extra JSON.parse call only on the first time through. That seems a pretty small price to pay for reconciling the two libraries' incompatible return return types. Dave