Search code examples
ruby-on-rails-3mergenested-attributesparametersransack

Merge nested params via link_to


I'm using nested params (via ransack nested as q) alongside normal params to build links on a page and am having trouble with getting the two to play nicely when I try and merge the nested params with the other params.

For example if I have:

{"freq"=>"weekly", "loan_amount"=>"350000",
"q"=>{"lowEquity_true"=>"1", "s"=>"rate asc"}}

and try and build a link to change the param "lowEquity_true" with

rates_url(params[:q].merge(:lowEquity_true => '0'))

then I end up with the new params below, which looks like its updated q but dropped the rest of the params.

{"lowEquity_true"=>"0", "s"=>"rate asc"}

If I instead try to merge q & merge into the other params it doesn't update q, and just merges what was in q into the other params instead

rates_url(params[:q].merge(:lowEquity_true => '0').merge(params))

{"freq"=>"weekly", "loan_amount"=>"350000", "lowEquity_true"=>"0",
 "q"=>{"lowEquity_true"=>"1", "s"=>"rate asc"},
 "s"=>"rate asc"}

I've tried all sorts of various combinations and don't appear to be getting anywhere so am sure that I'm missing something basic!


Solution

  • You are doing it wrong.

    Let me explain with an example :

    params = {:a => 1, :b => 2, :q => {:x => 24, :y => 25}}
    

    At this point, params[:q] is

    {:x=>24, :y=>25}
    

    If I do,

    params[:q].merge(:x => 99)
    

    then my params[:q] will become

     {:x=>99, :y=>25}
    

    and this is what you are supplying as an argument to rates_url(params[:q].merge(:lowEquity_true => '0'))

    that's why only {"lowEquity_true"=>"0", "s"=>"rate asc"} is passed to rates_url as parameters.

    Now, if you do something like

    params[:q].merge(:x => 99).merge(params)
    

    then params[:q].merge(:x => 99) gives you {:x=>99, :y=>25} and then it merges {:x=>99, :y=>25} into the original params {:a => 1, :b => 2, :q => {:x => 24, :y => 25}} , so this results into

     {:x=>99, :y=>25, :a=>1, :b=>2, :q=>{:x=>24, :y=>25}}
    

    Now, let me explain you what you should do :-

    You params is

    {"freq"=>"weekly", "loan_amount"=>"350000",
    "q"=>{"lowEquity_true"=>"1", "s"=>"rate asc"}}
    

    So, you should do :

    params[:q].merge!(:lowEquity_true => '0')
    
    rates_url(params)
    

    That's it

    I hope you khow the difference between merge and merge! :- merge! is destructive, it will modify the original paramter where as merge will not unless you take it in a variable and use it.

    Alternatively, if you want to do the same thing stated above in a single line then, just do

    rates_url(params.merge!(:q => {:lowEquity_true => '0', "s"=>"rate asc"}))
    

    OR

    rates_url(params.merge(:q => params[:q].merge(:lowEquity_true => '0')))