The most significant issue is you need to make sure you have the task names and task types correctly matched. That matching process will need to happen either by using the positions within the hashes or by matching based on keys that contain ordering information.
Hashes in Ruby 1.9+ are ordered, so it is possible to rely on position, but it would add some certainty if we could rely on ordering information in the keys themselves. Assuming the keys you receive actually contain sequential numbers as shown in the example, you can start by indexing each hash based on that number. First we'll assign the hashes to variables:
>> name_hash = {"task_1_name"=>"This is task no 1", "task_2_name"=>"This is task no 2", "task_3_name"=>"This is task no 3", "task_4_name"=>"This is task_no_4"}
>> type_hash = {"task_1_type"=>"T","task_2_type"=>"M","task_3_type"=>"D","task_4_type"=>"M"}
Next we'll index each hash based on the sequential number. We can extract that number using the String#split
method, picking the second element, and converting it to an integer so it sorts properly if the numbers go beyond a single digit:
>> indexed_name_hash = name_hash.index_by { |k,_| k.split('_').second.to_i }
-> {1=>["task_1_name", "This is task no 1"], 2=>["task_2_name", "This is task no 2"], 3=>["task_3_name", "This is task no 3"], 4=>["task_4_name", "This is task_no_4"]}
>> indexed_type_hash = type_hash.index_by { |k,_| k.split('_').second.to_i }
-> {1=>["task_1_type", "T"], 2=>["task_2_type", "M"], 3=>["task_3_type", "D"], 4=>["task_4_type", "M"]}
Now that we have a reliable way to pair names with types, we'll use Array#map
to build our desired attributes. Hash#keys
gives us just the keys of one of our hashes, which in this example will be [1, 2, 3, 4]
. We then map those integers to the values of the respective data:
>> paired_attributes = indexed_name_hash.keys.map { |number| {task_name: indexed_name_hash[number].last, task_type: indexed_type_hash[number].last} }
-> [{:task_name=>"This is task no 1", :task_type=>"T"}, {:task_name=>"This is task no 2", :task_type=>"M"}, {:task_name=>"This is task no 3", :task_type=>"D"}, {:task_name=>"This is task_no_4", :task_type=>"M"}]
Now that we have our attributes properly paired in an array of hashes, we simply iterate over the array and create Tasks:
>> paired_attributes.each { |attributes| Task.create(attributes) }
>> Task.all
#<ActiveRecord::Relation [#<Task id: 1, task_name: "This is task no 1", task_type: "T">, #<Task id: 2, task_name: "This is task no 2", task_type: "M">, #<Task id: 3, task_name: "This is task no 3", task_type: "D">, #<Task id: 4, task_name: "This is task_no_4", task_type: "M">]>