Jay
Jay

Reputation: 948

Rails merge multiple params together

How can I merge two params together from my permissions hash that share the same "school_id" and "plan_type'. Then delete the permission that was merged from the hash, just leaving one. There can also be more than two that match.

[{"school_id"=>"1",
  "plan_type"=>"All",
  "view"=>"true",
  "create"=>"true",
  "approve"=>"true",
  "grant"=>"true",
  "region_id"=>nil},
 {"school_id"=>"1", "plan_type"=>"All", "edit"=>"true", "region_id"=>nil},
 {"school_id"=>"2",
  "plan_type"=>"All",
  "edit"=>"true",
  "grant"=>"true",
  "region_id"=>nil}]

def create_permissions(user, params)
  permissions = params[:permissions].values.map { |perm|
    if perm[:plan_type] == "" || perm[:plan_type] == "All Plans"
      perm[:plan_type] = "All"
    end
    @perm_type = get_permission_type(perm)
    case
    when 'school' then perm.merge(region_id: nil)
    when 'region' then perm.merge(school_id: nil)
    end
  }.tap { |permissions|
    new_permissions = []
    permissions.each do |perm|
      set_permissions = permissions.find {|x| (x != perm && x[:school_id] == perm[:school_id] && x[:plan_type] == perm[:plan_type]) }
    end
    params[:user][:region_ids] = permissions.map { |perm| perm[:region_id] }.compact
    params[:user][:school_ids] = permissions.map { |perm| perm[:school_id] }.compact
  }
end

Output:

[{"school_id"=>"1",
  "plan_type"=>"All",
  "view"=>"true",
  "create"=>"true",
  "approve"=>"true",
  "grant"=>"true",
  "region_id"=>nil},
  "edit"=>"true"
 {"school_id"=>"2",
  "plan_type"=>"All",
  "edit"=>"true",
  "grant"=>"true",
  "region_id"=>nil}]

Upvotes: 1

Views: 2027

Answers (2)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121010

Group by school_id and then reduce by merging hashes:

input.group_by { |e| e['school_id'] }
     .values
     .map { |v| p v.reduce(&:merge) }

To group by many fields, one might use an array of desired fields, a concatenated string, whatever:

input.group_by { |e| [e['school_id'], e['plan_type']] }
     .values
     .map { |v| p v.reduce(&:merge) }

or, to keep nifty captions:

input.group_by { |e| "School: #{e['school_id']}, Plan: #{e['plan_type']}" }
     .map { |k,v| [k, v.reduce(&:merge)] }
     .to_h

#⇒ {
#  "School: 1, Plan: All" => {
#      "approve" => "true",
#       "create" => "true",
#         "edit" => "true",
#        "grant" => "true",
#    "plan_type" => "All",
#    "region_id" => nil,
#    "school_id" => "1",
#         "view" => "true"
#  },
#  "School: 2, Plan: All" => {
#         "edit" => "true",
#        "grant" => "true",
#    "plan_type" => "All",
#    "region_id" => nil,
#    "school_id" => "2"
#  }
#}

Upvotes: 1

pangpang
pangpang

Reputation: 8831

arr1 = arr.group_by { |e| [e["school_id"],e["plan_type"]] }.values
=> {["1", "All"]=>[{"school_id"=>"1", "plan_type"=>"All", "view"=>"true", "create"=>"true", "approve"=>"true", "grant"=>"true", "region_id"=>nil}, {"school_id"=>"1", "plan_type"=>"All", "edit"=>"true", "region_id"=>nil}], ["2", "All"]=>[{"school_id"=>"2", "plan_type"=>"All", "edit"=>"true", "grant"=>"true", "region_id"=>nil}]}

arr1.map{ |i| i.inject({}) { |sum, e| sum.merge e}}
=> [{"school_id"=>"1", "plan_type"=>"All", "view"=>"true", "create"=>"true", "approve"=>"true", "grant"=>"true", "region_id"=>nil, "edit"=>"true"}, {"school_id"=>"2", "plan_type"=>"All", "edit"=>"true", "grant"=>"true", "region_id"=>nil}]

Upvotes: 0

Related Questions