Tom Clowers
Tom Clowers

Reputation: 141

Updating a Rails Association table

I'm working on a quiz app in Rails that keeps track of a number of Facts

app/models/fact.rb

class Fact < ActiveRecord::Base
    validates(:question, presence: true, uniqueness: { case_sensitive: false })
    validates(:answer, presence: true)
end

Every time a user takes a new quiz, they generate an Exam

app/models/exam.rb

class Exam < ActiveRecord::Base
    after_create :assign_facts
    belongs_to :user
    default_scope -> { order('created_at DESC') }
    validates :user_id, presence: true
    has_many :problems
    has_many :facts, through: :problems

    def assigned?(fact)
        problems.find_by(fact_id: fact.id)
    end

    def assign!(fact)
        problems.create!(fact_id: fact.id)
    end

    private

        def assign_facts
            facts = Fact.all.sample(10)
            facts.each do |fact|
                self.assign!(fact)
            end
        end

end

Since there are many Exams all using the same Facts, each Exam has_many Facts though an association table of Problems

app/models/problem.rb:

class Problem < ActiveRecord::Base
    belongs_to :exam
    belongs_to :fact
    validates :exam_id, presence: true
    validates :fact_id, presence: true
end

excerpt from db/scheme.rb:

  create_table "problems", force: true do |t|
    t.integer  "exam_id"
    t.integer  "fact_id"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.boolean  "correct",    default: false
  end

My problem is that I'm trying to figure out how to store the results of each user's exam (whether they answer a specific question either correctly, or incorrectly). I was planning on updating the association table each time the user answers a question and storing the result in the t.boolean "correct" collumn. This would be a fairly simple matter in PHP/MySQL (UPDATE problems SET correct = 1 WHERE exam = 'id' AND fact = 'id'), but I'm having difficulty figuring out how to do it the Rails way.

Is there some way I can simply, and easily update my associations table (problems) with Rails? OR Should I create a fourth table (maybe 'results' or something) to keep track of the user's correct/incorrect answers? --I know I don't have any controller code here, I'm just thinking out the broad strokes, and I want to keep things simple. Any help would be greatly appreciated.

Upvotes: 0

Views: 157

Answers (1)

sameers
sameers

Reputation: 5095

You are almost there... you have already added a Boolean column called correct in the schema for the problem model, so now you just need to access that as an attribute when updating an Exam. Som somewhere in your controller code, you would say:

ps=@exam_taken.problems
ps.each do |p|
   if answered_correctly(p)
        p.correct=true
        p.save
   end
end
# This assumes you have a method that checks correctness inside the binding where the
# above code is written

@exam_taken.save

If you are using Rails3, you would have to also declare the correct attribute as attr_accessible in your model.

And here's a free pro-tip: Default scope is evil :)

Upvotes: 1

Related Questions