Rails: Opposite of Hash#To_Param

Rails: Opposite of Hash#to_param

You're looking for Rack::Utils.parse_nested_query(query), which will convert it back into a Hash. You can get it by using this line:

require 'rack/utils'

Ruby: How to turn a hash into HTTP parameters?

Update: This functionality was removed from the gem.

Julien, your self-answer is a good one, and I've shameless borrowed from it, but it doesn't properly escape reserved characters, and there are a few other edge cases where it breaks down.

require "addressable/uri"
uri = Addressable::URI.new
uri.query_values = {:a => "a", :b => ["c", "d", "e"]}
uri.query
# => "a=a&b[0]=c&b[1]=d&b[2]=e"
uri.query_values = {:a => "a", :b => [{:c => "c", :d => "d"}, {:e => "e", :f => "f"}]}
uri.query
# => "a=a&b[0][c]=c&b[0][d]=d&b[1][e]=e&b[1][f]=f"
uri.query_values = {:a => "a", :b => {:c => "c", :d => "d"}}
uri.query
# => "a=a&b[c]=c&b[d]=d"
uri.query_values = {:a => "a", :b => {:c => "c", :d => true}}
uri.query
# => "a=a&b[c]=c&b[d]"
uri.query_values = {:a => "a", :b => {:c => "c", :d => true}, :e => []}
uri.query
# => "a=a&b[c]=c&b[d]"

The gem is 'addressable'

gem install addressable

Hash remove all except specific keys

Some other options:

h.select {|k,v| ["age", "address"].include?(k) }

Or you could do this:

class Hash
def select_keys(*args)
select {|k,v| args.include?(k) }
end
end

So you can now just say:

h.select_keys("age", "address")

Rails hashes with unknown keys and strong parameters

Your need is completely opposite of objective of strong parameter,
when we define strong parameter then basically we are going to whitelist the coming params.

and here in your case we exactly don't know the keys, so there is no need to put strong parameter check over there. that will solve your problem.

Params hash keys as symbols vs strings

In Rails, the params hash is actually a HashWithIndifferentAccess rather than a standard ruby Hash object. This allows you to use either strings like 'action' or symbols like :action to access the contents.

You will get the same results regardless of what you use, but keep in mind this only works on HashWithIndifferentAccess objects.

Rails what is the oppsite of the to_query method?

This is a duplicate of this questions: Just use:

Rack::Utils.parse_query(my_query_string)

In order to decode the line in your example, be sure to unescape the string first:

require 'rack'

my_string = 'fields%5B%5D=exhb_0&fields%5B%5D=exh0_1&fields%5B%5D=t_g_a&fields%5B%5D=hp_1&fields%5B%5D=s1&fields%5B%5D=overflade_0&railing%5B%5D=A-3&railing_m=0&type%5B%5D=ltrappa&wood%5B%5D=wood_6'

unescaped_string = URI.unescape(my_string)
# => "fields[]=exhb_0&fields[]=exh0_1&fields[]=t_g_a&fields[]=hp_1&fields[]=s1&fields[]=overflade_0&railing[]=A-3&railing_m=0&type[]=ltrappa&wood[]=wood_6"

params_hash = Rack::Utils.parse_query(unescaped_string)
# => {"fields[]"=>["exhb_0", "exh0_1", "t_g_a", "hp_1", "s1", "overflade_0"], "railing[]"=>"A-3", "railing_m"=>"0", "type[]"=>"ltrappa", "wood[]"=>"wood_6"}

Rails flat params to hash

Try this:

params.map { |k,v| [k.split('.').reverse,v] }.map { |keys,val| keys.inject(val) { |val, e| { e => val }} }.inject({}) { |hsh, h| hsh.deep_merge(h) }

It may not be the most optimal way, but - unless we're talking about millions of items in the cart - it still does the job faster than a single DB query.

For your sample params the result should be:

{"shopping-cart"=>{"items"=>{"item-1"=>{"item-name"=>"Item one", "item-description"=>"An item", "unit-price"=>{"currency"=>"GBP"}, "quantity"=>"1"}, "item-2"=>{"item-name"=>"Item two", "item-description"=>"Another item", "unit-price"=>{"currency"=>"GBP"}, "quantity"=>"3"}, "item-3"=>{"item-name"=>"Item three", "item-description"=>"Yet another item", "unit-price"=>{"currency"=>"GBP"}, "quantity"=>"2"}}}, "edit_url"=>"http://somerailsapp/store/buy", "_charset_"=>"UTF-8", "controller"=>"order", "action"=>"process"}

You may also use

k.split('.').reverse.map { |k| sanitize_key(k) }

where sanitize_key gets rid of item- prefix and/or changes the item number to integer.

Edit: I just noticed that the price goes missing - so you may want to add '.amount' to the
keys ending with unit-price. Somehow this cart hash is not sanely structured...

Enjoy!

Is there an opposite function of slice function in Ruby?

Use except:

a = {"foo" => 0, "bar" => 42, "baz" => 1024 }
a.except("foo")
# returns => {"bar" => 42, "baz" => 1024}

How to remove a key from Hash and get the remaining hash in Ruby/Rails?

Rails has an except/except! method that returns the hash with those keys removed. If you're already using Rails, there's no sense in creating your own version of this.

class Hash
# Returns a hash that includes everything but the given keys.
# hash = { a: true, b: false, c: nil}
# hash.except(:c) # => { a: true, b: false}
# hash # => { a: true, b: false, c: nil}
#
# This is useful for limiting a set of parameters to everything but a few known toggles:
# @person.update(params[:person].except(:admin))
def except(*keys)
dup.except!(*keys)
end

# Replaces the hash without the given keys.
# hash = { a: true, b: false, c: nil}
# hash.except!(:c) # => { a: true, b: false}
# hash # => { a: true, b: false }
def except!(*keys)
keys.each { |key| delete(key) }
self
end
end


Related Topics



Leave a reply



Submit