Reputation: 3472
I am creating an array of fields
def create_fields fields
fields_list = []
fields.each do |field|
# puts "adding_field to array: #{field}"
field_def = { field: field, data: { type: 'Text', description: '' } }
fields_list.push field_def
end
fields_list
end
The fields_list
is being set to a jsonb field.
Lets say I pass in
create_fields ['Ford', 'BMW', 'Fiat']
Json result is an array:
{"field"=>"Ford", "data"=>{"type"=>"Text", "description"=>""}}
{"field"=>"BMW", "data"=>{"type"=>"Text", "description"=>""}}
{"field"=>"Fiat", "data"=>{"type"=>"Text", "description"=>""}}
How can I access the 'Ford' from the json array? Am i creating the array incorrectly? Is there a better way to create this array so I can access the field i want?
This assertion passes assert_equal(3, fields.count)
However i want to get 'Ford' and check it's properties, e.g. type = 'Text', type could equal 'Number' or whatever.
Upvotes: 0
Views: 3914
Reputation: 172
This is a structure that makes more sense to me for accessing values based on known keys:
def create_fields fields
fields_hash = {}
fields.each do |field|
fields_hash[field] = {type: 'Text', description: ''}
end
fields_hash
end
# The hash for fields_hash will look something like this:
{
Ford: {
type: "Text",
description: ""
},
BMW: {...},
Fiat: {...}
}
This will allow you to access the values like so: fields[:Ford][:type]
in ruby and fields.Ford.type
in JSON. Sounds like it would be easier to return an Object rather than an Array. You can access the values based on the keys more easily this way, and still have the option of looping through the object if you want.
Upvotes: 3
Reputation: 4440
So, you have result of your method:
result =
[
{"field"=>"Ford", "data"=>{"type"=>"Text", "description"=>""}},
{"field"=>"BMW", "data"=>{"type"=>"Text", "description"=>""}},
{"field"=>"Fiat", "data"=>{"type"=>"Text", "description"=>""}}
]
to get 'Ford' from it you can use simple method detect
result.detect { |obj| obj['field'] == 'Ford' }
#=> { "field"=>"Ford", "data"=>{"type"=>"Text", "description"=>""}
Also I recommend you to edit your method to make it more readable:
def create_fields(fields)
fields.map do |field|
{
field: field,
data: {
type: 'Text',
description: ''
}
}
end
end
Upvotes: 1
Reputation: 5633
Obviously, there are several ways of creating or accessing your data, but I'd always lean towards the developer picking a data structure best suited for your application.
In your case currently, in order to access the Ford
hash, you could use the Ruby Array#detect method as such:
ford = fields_list.detect{|field_hash| field_hash['field'] == 'Ford' }
ford['data'] # => {"type"=>"Text", "description"=>""}
ford['data']['type'] # => 'Text'
Upvotes: 1
Reputation: 341
The result of your create_fields method with the specified parameters is the following:
[
{:field=>"Ford", :data=>{:type=>"Text", :description=>""}},
{:field=>"BMW", :data=>{:type=>"Text", :description=>""}},
{:field=>"Fiat", :data=>{:type=>"Text", :description=>""}}
]
It means that if you want to access the line belonging to "Ford", you need to search for it like:
2.3.1 :019 > arr.select{|e| e[:field] == "Ford" }
=> [{:field=>"Ford", :data=>{:type=>"Text", :description=>""}}]
2.3.1 :020 > arr.select{|e| e[:field] == "Ford" }[0][:data][:type]
=> "Text"
This is not optimal, because you need to search an array O(n) instead of using the pros of a hash. If there are e.g.: 2 "Ford" lines, you'll get an array which contains 2 elements, harder to handle collisions in field value.
It would be better if you created the array like:
def create_fields fields
fields_list = []
fields.each do |field|
# puts "adding_field to array: #{field}"
field_def = [field, { type: 'Text', description: '' } ]
fields_list.push field_def
end
Hash[fields_list]
end
If you choose this version, you can access the members like:
2.3.1 :072 > arr = create_fields ['Ford', 'BMW', 'Fiat']
=> {"Ford"=>{:type=>"Text", :description=>""}, "BMW"=>{:type=>"Text", :description=>""}, "Fiat"=>{:type=>"Text", :description=>""}}
2.3.1 :073 > arr["Ford"]
=> {:type=>"Text", :description=>""}
2.3.1 :074 > arr["Ford"][:type]
=> "Text"
Both of the above examples are Ruby dictionaries / Hashes. If you want to create a JSON from this, you will need to convert it:
2.3.1 :077 > require 'json'
=> true
2.3.1 :078 > arr.to_json
=> "{\"Ford\":{\"type\":\"Text\",\"description\":\"\"},\"BMW\":{\"type\":\"Text\",\"description\":\"\"},\"Fiat\":{\"type\":\"Text\",\"description\":\"\"}}"
Upvotes: 5