Saving and retrieving state in web forms - ruby-on-rails

I'm creating a 'work book' ruby on rails application. Basically a user will read a paragraph or two and then answer some questions based on what they've read.
I'm unsure how to model this. The paper work books have many pages and each page has many paragraphs.
Should I model it exactly as it is in physical form or should I simplify the model?
My biggest question is how do I save state so that a user can update their workbook and or make corrections after they've submitted part of their assignment?

I think these relations could work for you:
class WorkBook
has_many :pages
class Page
belongs_to :work_book
has_many :paragraphs
class Paragraph
belongs_to :page
has_many :questions
class Question
belongs_to :paragraph
has_many :answers
class Answer
belongs_to :question
belongs_to :user
class User
has_many :answers
has_many :answered_questions, class_name: 'Question', through: :answers
If you want a better control on your answers (like value_string, value_float, value_boolean, etc.) I recommend you to add an extra model "AnswerValue".
You might feel like there is too much models in this case, but trust me, it makes your app flexible and allows you to add more "granular" features on each model / relation.
An extenstion with these relations: You could add a model "AnswerCorrection" which would act like an Answer but would be a way to save another value after the user update it's workbook.
Hope this helps!

I'd go for something like this:
class PaperWork < ActiveRecord::Base
has_many :pages
has_many :paragraphs, through: :pages
end
class Page < ActiveRecord::Base
belongs_to :paper_work
has_many :paragraphs
end
class Paragraph
belongs_to :page
belongs_to :paper_work, through: :page
end
Then you can model assignments somewhat around this idea:
class Asignment < ActiveRecord::Base
belongs_to :user
belongs_to :paragraph
# attributes: description, status(pending, completed, etc.)
end

Related

ActiveRecord: has_many choices limited to has_many of another model

I would like to achieve something as follows where PersonSubject has many topics, but the choices of these topics are limited to the the selection of topics through another model (ie: through the associated subject):
class Topic < ApplicationRecord
belongs_to :subject
end
class Subject < ApplicationRecord
has_many :topics
end
class PersonSubject < ApplicationRecord
belongs_to :person
belongs_to :subject
has_many :topics # where the choices are limited to the subject.skills
end
I would then like if any person_subject.subject.topics are deleted (or association removed), it would automatically update the person_subject.topics to no longer "point" to the Topic(s) that were deleted.
Is this possible?
You can use a lambda to put arbitrary filters on an association. See What is the equivalent of the has_many 'conditions' option in Rails 4?
has_many :topics, -> { where(skill: subject.skills) }
I don't know that this is exact code will work without seeing your schema (what is the data type of subject.skills, and how do you join this with topic?). But hopefully this gets you on the right track
edit
in response to your comment, I think
has_many :topics, through: :skills
would work

Designing Database for Long Forms in Rails & ActiveRecord

I want to store complex form/questionnaire data but I'm having a hard time designing the database:
A User can create a new Exam. When creating an Exam, the user needs to choose from a template with 30 pre-set questions (and I want to store the answer to each of these questions in the database).
Purpose of the template is so that practitioners might want to run different exams (e.g. knee exam, arm exam, spine exam etc). So they create a new exam, choose a specific template. And each template has many questions
What's the best way to design this database? I started creating Exam, Template, and Question models, but then I got lost building the relationships.
Here's how I ended up designing the database. I added a 4th "answers" model. This way, I can associate answers to questions, and questions to templates, and templates to exams.
Hope this helps someone
class User < ActiveRecord::Base
has_many :patients
has_many :assessments
end
class Patient < ActiveRecord::Base
belongs_to :user
has_many :assessments
end
class Assessment < ActiveRecord::Base
belongs_to :user
belongs_to :template
belongs_to :patient
has_many :questions, :through=> :template
has_many :answers, :through=> :questions
end
class Template < ActiveRecord::Base
belongs_to :user
has_many :questions
end
class Question < ActiveRecord::Base
belongs_to :template
has_one :answer
end
class Answer < ActiveRecord::Base
belongs_to :question
end

Rails - track user's "actions" with relationship models

I'm building a math exercise app. I want to store questions that are separated into exercises and each exercise belongs to a different section. Also there are multiple sections for each grade (12 grades in total).
How do i track a user's answer (action)? For instance, when a user browses the app, decides to answer question 7 from exercise 'G1' in section 'G' of Grade 'Pre-K' and provides a correct answer i want to track that and in the future provide him with statistics about his performance.
Currently there isn't a connection between my User model to the questions and i wanted to hear from others as to what would be the most efficient way to tackle this (maybe the models right now are completely wrong)
This is the model diagram for now with has_many, belongs_to relationship (i'll add 'the_question':string and 'answer':string later on to the question model):
I think all that is missing is a Answer model, that is connected to the User.
Optionally, you can define the relations on the "parents" of Question too.
class Grade < ActiveRecord::Base
has_many :users, :through => :sections # optional. i.e. 'users that have answers in this grade'
end
class Section < ActiveRecord::Base
has_many :users, :through => :exercises # optional
end
class Exercise < ActiveRecord::Base
has_many :users, :through => :questions # optional
end
class Question < ActiveRecord::Base
has_many :answers
has_many :users, :through => :answers # optional
end
class Answer < ActiveRecord::Base
belongs_to :question
belongs_to :user
end
class User < ActiveRecord::Base
has_many :answers
end
Update: re-reading your description, I think CorrectAnswer would be better suitable than Answer.

Nested associates the rails way

I'm fairly new to Rails and I'm trying to gain a better understanding of how to be leverage the Rails framework for my associations.
While it's not specific for my app, the structure is similar -- for my example, I'll use the standard blog associates.
Example Models:
class Author < ActiveRecord::Base
has_many :posts, :through => :posts
end
class Post < ActiveRecord::Base
belongs_to :author
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :post
end
My challenge is that I want to select all comments that belong to a specific author. I understand how to reference post and author elements that are associated with a specific post:
comment_author = Comment.first
puts comment_author.post.author.name
But as I stated I'm trying to select all comments that belong to a specific author. I could accomplish this by doing a find_by_sql, but I want to ensure db independence and I want to do this the "Rails way."
Thanks!
You can use the has_many :through assocication:
class Author < ActiveRecord::Base
has_many :posts
has_many :comments, :through => :posts
end
#Femaref provided the exact answer to your question and you should accept it. Mine is merely a complement.
If an author can leave comments on posts, here is what you might want to do:
class Author
has_many :posts
has_many :comments
has_many :responses, through: :posts, source: :comments
end
class Post
belongs_to :author
has_many :comments
end
class Comment
belongs_to :author
belongs_to :post
end
To get all the comments left by sophia: sophia.comments
To get all the comments left on sophia's posts: sophia.responses
See the options for has_many (especially through and source)

Like/Dislike style Voting Database in Rails

I’m creating a voting feature for our website in the style of YouTube “Likes” and “Dislikes” and Digg using Ruby on Rails 3. I have having trouble coming up with the right scheme.
I have three models, Users, Topics, and Votes. Each User will make one vote “Like” or “Dislike” for one Topic. Like these sites, Users can Vote on a Topic, but they can also create new Topics. I’d like to be able to not only view all of a User’s Votes, but also both the Topics they have created and the Topics they have voted on. I am trying to build this on our own and decide how best to setup the database to handle this process.
My first idea was to use :has_many and belongs_to exclusively like so…
class User < ActiveRecord::Base
has_many :votes
has_many :topics
class Topic < ActiveRecord::Base
has_many :votes
belongs_to :users
class Vote < ActiveRecord::Base
belongs_to :topics
belongs_to :users
boolean choice #tracks whether the User chooses Like or Dislike
But it became evident that this might not be the best way to do this. I began to think the best method would be to use a :has_many :through association like...
class User < ActiveRecord::Base
has_many :votes, :through => :topics
But I’m not sure. Any ideas on how best to set something like this up?
I think your initial setup is good but it can be further improved upon to better support what you want to accomplish. Perhaps like this:
class User < ActiveRecord::Base
has_many :votes
has_many :topics
#Lists all topics the user has voted on
has_many :voted_topics, :through => :votes, :source => :topic
#Lists all votes for the users topics
has_many :topic_votes, :through => :topics, :source => :votes
end
class Topic < ActiveRecord::Base
has_many :votes
belongs_to :user
end
class Vote < ActiveRecord::Base
belongs_to :topic
belongs_to :user
end

Resources