1

I have a JSON file the has a structure something like this:

[
  {
    "Name" : {
      "Attribute" : " Value",
      "Attribute2" : " Value2",
      "Attribute3" : " Value3",
    }
   , "Name2" : {
    ...
    }
]

I'm trying to seed this file into a database table. I don't need all attribute:value pairs, so I need to map the ones I need to the create command in the loop. This is what I've attempted in the seeds.rb file:

json = ActiveSupport::JSON.decode(File.read("db/exercises.json"))

json.each_with_index do |e, index|

    Model.create!(
        name: e[0]
        )

end

What I essentially need to do is something like this:

Model.create!(
    name: e[0],
    attribute1: e[0][attribute1],
    attribute3: e[0][attribute3]
    )

Any help ?

6
  • Can you show us a more realistic sample of your data file? It's not clear what you're trying to map to your model. For starters, you want JSON.parse, not decode, and you shouldn't be referencing e[0] - e is not an array. Commented Feb 10, 2016 at 3:31
  • I need to map the "Name" and the "Value" associated with the attributes to my database model. My model has columns for Name, Value, Value2, etc. Commented Feb 10, 2016 at 3:44
  • It looks like the braces in your example are mismatched. Is { ... repeat ... } supposed to be the second element in the top-level array, rather than a sibling of "Name" (which is invalid syntax)? Commented Feb 10, 2016 at 3:46
  • My mistake, i meant to convey that the same structure repeats, fixed now Commented Feb 10, 2016 at 3:47
  • So does the array only have a single object in it, and the object contains a key/value pair for each record you want to insert in your DB? Commented Feb 10, 2016 at 3:49

1 Answer 1

3

Most of your confusion is around how to access your objects. ActiveSupport::JSON.decode parses your data into an array containing a Hash with keys "Name", "Name2", etc. Hash#each yields pairs of |key, value| that you can use to populate your database. Your keys become Model#name, and then you can map the data's attributes to your model's.

data = ActiveSupport::JSON.decode(File.read("db/exercises.json"))
data = data[0] # Unwrap the Array

data.each do |name, attributes|
  Model.create!(
    name: name,
    column_one: attributes['one'],
    column_two: attributes['another one']
  )
end

If your file shares key names with your columns, Rails provides Hash#slice to easily pull out a subset.

> {a: 1, b: 2, c: 3}.slice(:a, :c)
#=> {a: 1, c: 3}
Sign up to request clarification or add additional context in comments.

4 Comments

What do I do if the attribute is composed of more than one word ?
Your model can't have multiple words in its columns, so you need to map those explicitly like name. Read up on Ruby Hashes, it sounds like you're missing that foundation.
That's right, but I only want to map some of the attributes. Would something like .splice(column_name: "attribute1", column_name_2: "attribute3") work ?
No, if you read the docs you'll see that slice accepts a list of key name you want out, not a hash. I've updated my example with the more explicit mapping you're after.

Your Answer

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