2

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}]]]}
7
  • can you post the exact content of @request? (you can see it by doing raiser @request BEFORE the line where the error occurs Commented Jun 4, 2014 at 16:27
  • Your e exists in block but not after them. Or it's some global thing?. Commented Jun 4, 2014 at 16:36
  • Added the first iteration of @request as it's massive Commented Jun 4, 2014 at 16:39
  • 1
    Yeah, appears formatting has been mucked up when I pasted. I'll see if I can sort it now Commented Jun 4, 2014 at 16:40
  • 1
    Got it, was confused by format. Commented Jun 4, 2014 at 16:41

1 Answer 1

1

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
Sign up to request clarification or add additional context in comments.

6 Comments

Got ActiveRecord::AssociationTypeMismatch: Question(#2297301000) expected, got ActiveSupport::HashWithIndifferentAccess(#2162666120)
You have to set accepts_nested_attributes_for :questions (and :sections & :answers) OR you can create the Exercise, Questions, Sections and Answers "independently" (tell me if you need an example for the last one, its pretty easy though) @Xopa
Yeah, I've got the joins setup and working when I create the exercise through a form. It's just this import function that doesn't want to work
Your request's repsonse shows that Answer is nested in Question which is nested in Section. Is it also your DB configuration? (i.e. Excercise has_many :sections && Section has_many :questions && Question has_many :answers? @Xopa
I updated my answer to nest the attributes, following the nested relations @Xopa
|

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.