0

The params' hash keys are mix of camelcase, lowercase and uppercase characters:

params = {"RefreshTime"=>"0", "lang"=>"tr", "amount"=>"50", "ACQBIN"=>"490740"}

The array, which is a list of one of my models' column names, is all lowercase but exactly the same values with the keys of params hash =>

columns = ["refreshtime", "lang", "amount", "acqbin", ......]

I'm trying to match hash keys with the members of the array to create a new record in my controller =>

def create_transaction
   @transaction = OrderTransaction.new(
      params.each do |k, v|
        columns.each do |i|
          if i == k.downcase
            "#{i}: params[:#{k}],"
          end
        end
      end
    )
end

But this piece of code isn't working as I expected. It seems like I'm doing something wrong in the line of;

#{i}: #{v}

What am I missing here?

By the way, this was my old way to do this job, which causes many lines of code =>

@transaction = OrderTransaction.new(
  refreshtime: params[:RefreshTime],
  lang: params[:lang],
  amount: params[:amount],
  acqbin: params[:ACQBIN],
  ...
)
5
  • That line by itself is meaningless. You need to do something with it, like add the key/val to a hash or something. Commented Jun 3, 2014 at 22:29
  • @DaveNewton Edited that line, I'm trying to do the same thing with amount: params[:amount] in that line Commented Jun 3, 2014 at 22:38
  • Are you sure that k is a String and not a Symbol? Commented Jun 3, 2014 at 22:39
  • It should be a symbol, but how? Commented Jun 3, 2014 at 22:40
  • If it's a symbol, then I think that i == k is not going to be correct in any case. Commented Jun 3, 2014 at 22:42

4 Answers 4

3

You could do something like this

@transaction = OrderTransaction.new(Hash[params.map{|k,v|[k.downcase,v]}])

This creates a new hash with all lowercase keys and uses it to initialize the OrderTransaction.

To only include keys that appear in the columns array

@transaction = OrderTransaction.new(Hash[params.map{|k,v|[k.downcase,v]}.select{|k,v|columns.include?(k)}])
Sign up to request clarification or add additional context in comments.

5 Comments

This is quite cool! The only problem is the parameter key list is quite larger than my array. Only some of the parameters from the hash will be saved to my database. How can I do this?
I updated my answer to show you how to do that. This will only include the keys that appear in the columns array.
Hash[params.map{|k,v|[k.downcase,v]}].slice("foo", "bar") to filter out key value pairs other than 'foo' and 'bar'. You can then use the splat operator to do Hash[params.map{|k,v|[k.downcase,v]}].slice(*columns)
One last question, what if I would like to assign an extra and different key:value with using this structure? For example, @transaction = OrderTransaction.new(order_id: params[:description], Hash[params.map{|k,v|[k.downcase,v]}.select{|k,v|OrderTransaction.column_names.include?(k)}] )
You can save the params into a variable valid_params = Hash[params.map{|k,v|[k.downcase,v]}.select{|k,v|columns.include?(k)}], and then use the merge! command or use it like a normal hash to add additional keys
0

You're not creating a hash entry, you're creating a string.

I'd suggest...

eval "#{i}: params[:#{k}],"

Which hopefully will actually create the key value pair.

or for that matter, why not...

i.to_sym => params[k.to_sym]

Comments

0

I suggest a cleaner way to do it:

def create_transaction
    result_hash = {}
    params.each do |k,v|
        temp = k.to_s.downcase
        if columns.include? temp
            result_hash[temp] = v
        end
    end
    @transaction = OrderTransaction.new(result_hash)
end

Comments

0

Typically we'd create a mapping hash. Starting with:

params = {"RefreshTime"=>"0", "lang"=>"tr", "amount"=>"50", "ACQBIN"=>"490740"}

This is a fast way to do it if you know the maps are consistent:

cols_to_key = Hash[params.keys.map(&:downcase).zip(params.keys)]
# => {"refreshtime"=>"RefreshTime",
#     "lang"=>"lang",
#     "amount"=>"amount",
#     "acqbin"=>"ACQBIN"}

Or:

cols_to_key = params.keys.map(&:downcase).zip(params.keys).to_h
# => {"refreshtime"=>"RefreshTime",
#     "lang"=>"lang",
#     "amount"=>"amount",
#     "acqbin"=>"ACQBIN"}

Accessing values looks like:

params[cols_to_key['refreshtime']] # => "0"
params[cols_to_key['lang']] # => "tr"

You can even slice the params hash various ways. If you want everything:

params.values_at(*cols_to_key.values)
# => ["0", "tr", "50", "490740"]

If you want a few things:

params.values_at(*cols_to_key.values_at('amount', 'acqbin'))
# => ["50", "490740"]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.