Xopa
Xopa

Reputation: 131

Trying to import JSON string in to database using Rails

Exercise.rb - Model

def self.import!
  @request = Net::HTTP.get(URI.parse('https://example.com/output'))
  @exercises = JSON.parse(@request)

  @exercises.each do |e|
    existing = Exercise.exists?(e)
    unless existing === false
      tmp = existing.first
    end

    e[:sections_attributes] = e.delete("sections")
    e[:questions_attributes] = e.delete("questions")
    e[:answers_attributes] = e.delete("answers")

    record = Exercise.create(e)
    puts "Record #{record["id"]} updated / created"
  end
end

I'm getting the following error when I run the import:

(0.9ms) COMMIT TypeError: no implicit conversion of String into Integer

My gut feeling is because every item in there is a String. How do I go about converting the items or get the insert to ignore column types?

Excerpt of @request

> `[2] pry(Exercise)> e
=> {"publish_date"=>"2013-12-11",
  "grade_id"=>2,
  "exercise_type"=>3,
  "week"=>1,
  "content"=>"<hr />\r\n\r\nQuestions:\r\n\r\n",
  "grammar_list"=>"",
  "title_append"=>nil,
  "sections"=>
   [{"name"=>"Vocab",
     "order"=>0,
     "questions"=>
      [{"question"=>"rgrthth",
        "type"=>3,
        "order"=>0,
        "answers"=>[{"answer"=>"aa", "correct"=>true, "order"=>0}]},
         {"question"=>"uh67jy7k",
          "type"=>3,
          "order"=>0,
          "answers"=>[{"answer"=>"bb", "correct"=>true, "order"=>0}]},
          {"question"=>"rgtdyjuyik",
           "type"=>3,
           "order"=>0,
           "answers"=>[{"answer"=>"cc", "correct"=>true, "order"=>0}]}]}]}`

Output from updated code

2.1.0 :040 > Exercise.import!
   (0.2ms)  SELECT COUNT(*) FROM `exercises` WHERE `exercises`.`week` = 1 AND `exercises`.`exercise_type` = 3 AND `exercises`.`grade_id` = 2

From: /Users/pc-a/Sites/mailbox/app/models/exercise.rb @ line 99 Exercise.import!:

     92: def self.import!
     93:   @request = Net::HTTP.get(URI.parse('example.com/output'))
     94:   @exercises = JSON.parse(@request)
     95:
     96:   @exercises.map(&:with_indifferent_access).each do |e|
     97:     next if Exercise.exists?(e[:week], e[:exercise_type], e[:grade_id])
     98:
 =>  99:     binding.pry
    100:
    101:
    102:     e[:sections_attributes] = e.delete(:sections)
    103:     e[:sections_attributes].map! do |section_attributes|
    104:       section_attributes[:questions_attributes] = section_attributes.delete(:questions)
    105:       section_attributes[:questions_attributes].map! do |question_attributes|
    106:         question_attributes[:answers_attributes] = question_attributes.delete(:answers)
    107:       end
    108:     end
    109:
    110:     binding.pry
    111:
    112:     exercise = Exercise.new(e)
    113:     if exercise.save
    114:       puts "Exercise #{exercise.id} created!"
    115:     else
    116:       puts "Could not create Exercise: #{exercise.errors.full_messages.join('; ')}"
    117:     end
    118:   end
    119: end

[1] pry(Exercise)> e
=> {"publish_date"=>"2013-12-11",
 "grade_id"=>2,
 "exercise_type"=>3,
 "week"=>1,
 "content"=>"<hr />\r\n\r\nQuestions:\r\n\r\n",
 "grammar_list"=>"",
 "title_append"=>nil,
 "sections"=>
  [{"name"=>"Vocab",
    "order"=>0,
    "questions"=>
     [{"question"=>"rgrthth",
       "type"=>3,
       "order"=>0,
       "answers"=>[{"answer"=>"aa", "correct"=>true, "order"=>0}]},
      {"question"=>"uh67jy7k",
       "type"=>3,
       "order"=>0,
       "answers"=>[{"answer"=>"bb", "correct"=>true, "order"=>0}]},
      {"question"=>"rgtdyjuyik",
       "type"=>3,
       "order"=>0,
       "answers"=>[{"answer"=>"cc", "correct"=>true, "order"=>0}]}]}]}
[2] pry(Exercise)> exit

From: /Users/pc-a/Sites/mailbox/app/models/exercise.rb @ line 110 Exercise.import!:

     92: def self.import!
     93:   @request = Net::HTTP.get(URI.parse('example.com/output'))
     94:   @exercises = JSON.parse(@request)
     95:
     96:   @exercises.map(&:with_indifferent_access).each do |e|
     97:     next if Exercise.exists?(e[:week], e[:exercise_type], e[:grade_id])
     98:
     99:     binding.pry
    100:
    101:
    102:     e[:sections_attributes] = e.delete(:sections)
    103:     e[:sections_attributes].map! do |section_attributes|
    104:       section_attributes[:questions_attributes] = section_attributes.delete(:questions)
    105:       section_attributes[:questions_attributes].map! do |question_attributes|
    106:         question_attributes[:answers_attributes] = question_attributes.delete(:answers)
    107:       end
    108:     end
    109:
 => 110:     binding.pry
    111:
    112:     exercise = Exercise.new(e)
    113:     if exercise.save
    114:       puts "Exercise #{exercise.id} created!"
    115:     else
    116:       puts "Could not create Exercise: #{exercise.errors.full_messages.join('; ')}"
    117:     end
    118:   end
    119: end

[1] pry(Exercise)> e
=> {"publish_date"=>"2013-12-11",
 "grade_id"=>2,
 "exercise_type"=>3,
 "week"=>1,
 "content"=>"<hr />\r\n\r\nQuestions:\r\n\r\n",
 "grammar_list"=>"",
 "title_append"=>nil,
 "sections_attributes"=>
  [[[{"answer"=>"aa", "correct"=>true, "order"=>0}],
    [{"answer"=>"bb", "correct"=>true, "order"=>0}],
    [{"answer"=>"cc", "correct"=>true, "order"=>0}]]]}

Upvotes: 2

Views: 136

Answers (1)

MrYoshiji
MrYoshiji

Reputation: 54882

Try the following:

def self.import!
    @request = Net::HTTP.get(URI.parse('https://example.com/output'))
    @exercises = JSON.parse(@request)

    @exercises.map(&:with_indifferent_access).each do |e|
      next if Exercise.exists?(name: e[:name]) # or whatever the attribute(s) you use to determine the uniqueness of an Exercise

      e[:sections_attributes] = e.delete(:sections)
      e[:sections_attributes].map! do |section_attributes|
        section_attributes[:questions_attributes] = section_attributes.delete(:questions)
        section_attributes[:questions_attributes].map! do |question_attributes|
          question_attributes[:answers_attributes] = question_attributes.delete(:answers)
        end
      end

      exercise = Exercise.new(e)
      if exercise.save
        puts "Exercise #{exercise.id} created!"
      else
        puts "Could not create Exercise: #{exercise.errors.full_messages.join('; ')}"
      end
    end
  end
end

Upvotes: 1

Related Questions