Handling multiple forms interacting with the same model in Rails - ruby-on-rails

I have an app that is dealing with "patients". Each patient is going to have three forms that they deal with initially. Each form has related questions, but they also have differences, so they can't be the same form. Each answer, even if it is for the same question, has to be recorded and archived. Also, there needs to be some sense of versioning to each form that is filled out. For instance if patient "Steve" fills out "Form 1" on "October 5th", and a question is taken away from the form the next day, I need to still be able to pull up the questions that Steve filled out on Form 1. Right now I have four models that I think solve this problem which are:
patients: first_name, last_name
forms: name, version
form_response: patient_id, form_id
questions: content, form_id
answers: response, question_id, form_response_id
Would this be the best way to map out this data set? Also, should this all be handled through the patient model? If not, what type of model structure should be used to handle this? I'm just really confused on how to best handle this situation as far as what should go where and not end up with a mess of code to maintain. Thank you in advance for your help.

You have the right ides. Starting from the top:
form
has_many questions
questions
belong_to form
has_many answers
answers
belong_to question
belong_to response
Then you tie it together with the response:
response
belongs_to patient
belongs_to form

I would suggest looking into form objects to make this a lot easier. You might want to checkout:
Form-backing objects for fun and profit
Rails Form Objects
Form Objects

Related

how to continue after the nested model forms railscasts?

I followed the railscasts nested model form part 1, making some changes to have it work in rails 4. Basically, I created 3 models: Quiz, Question, and Answer, and they all belong_to the model intuitively above them. A form in the new action is used to create the quiz itself.
However, I'm at a bit of loss on how to proceed now. After creating the quiz, the show view looks like this:
done by iterating through #quiz.questions and #quiz.questions.answers and just displaying them on the page with their respective content attributes.
That's great for displaying just the questions and answers, but it doesn't accept user input at all. How do I make it so the user can use radio buttons to select an answer, and have it submit SOMEWHERE to save the results for grading and future reference for the user?
I've actually tried to create a form simply within the show action and have it save to another model but I got stuck extremely quickly. I'm finding it really difficult to both display the results AND accept user input for the displayed results. I also can't figure out a good way to save this data. Making another 3 models with the equivalent of Questions having something like a user_answer attribute seems difficult to implement and messy. I'm a beginner of the grandest caliber so any help would be great!
Nachime, your data model is good so far from what I can tell. Now you will want to link the answers to the users via many-to-many relationship. Note: this assumes that users will only take each quiz once.
Your next data model version will have a users_answers table containing user_id and answer_id. You can access the relative models using the has_many :through association so that each user has_many :answers, through: :users_answers.
The quiz will essentially just link the logged in user to the array of answers selected.

Rails dynamic & modifiable form schemas

I have a problem with forms. I'm developing an application that allows applicants to submit applications, and I want to make sure that users (people who receive those applications) could add/delete questions in their applications. How would I implement that?
My thought is to have a Application model and a ApplicationQuestion model that belongs_to Application. But I'm pretty lost beyond that.
UPDATE:
Another issue is confusing me. In my systems I could get Admins to add/delete ApplicationQuestions dynamically, and I have no problem implementing that. However, I want the Users to see the current set of ApplicationQuestions and answer them without being able to add/delete/edit questions. I'm now using a proxy model ApplicationQuestionAnswer which belongs_to Application and ApplciationQuestion. However I'm still having trouble with the views.
I'm actually more concerned about the views. How should I render the
forms to form-fillers?
Start with an Application form containing a stable amount of Questions (refer to Rails nested forms to implement it). The basic implementation could look like that:
<%= form_for #application do |f| %>
<%= f.fields_for :application_questions do |aq_form| %>
<%= aq_form.text_field :question %>
<%= aq_form.text_field :question %>
Dynamic adding and removing questions could be achieved by adding (and removing) HTML blocks produced by Rails helpers shown above:
<%= aq_form.text_field :question %>
You could dig into it's implementation by yourself (and write some javascript to orchestrate HTML blocks addition/removement) or use some gem with that functionality. One of those popular solutions is cocoon. It provides you with pretty links (link_to_add_association and link_to_remove_association), which being clicked perform the desired dynamic actions. You may be intrested in trying a cocoon demo application to get an idea of how to embed it into your project.
Yes you can keep the models as you are thinking. There will be a User model which would have two roles basically. One would be the teacher (just taking an example) who asks the questions and one would be student who will answer those questions. Now the teacher would be able to create application having different questions so two more models Application and ApplicationQuestion. The relations can be:
Application belongs_to User
ApplicationQuestion belongs to Application
Now the student will answer the questions which can be stored in answer table which would be another model ApplicationQuestionAnswer which would also belong to User and ApplicationQuestion. Now the questions can be of different type (numeric, string, date etc) so take care of that, they all can be stored in a single column by handling it at the code end and for this also have a question_type attribute in the ApplicationQuestion model.
Now the teacher can edit the application and delete the questions if they want or add new. Be sure to add dependent destroy so the answer would also be deleted when the question is deleted. Also suppose if the question can have choices then be sure to add one more model ApplicationQuestionChoice which would belong to ApplicationQuestion and its id will be saved as the answer of the student.
Update:
The ApplicationQuestionAnswer model will save each question's answer instead what you can do is that have two models. One would be ApplicationAnswer and another ApplicationQuestionAnswer. And the associations would be:
ApplicationAnswer belongs_to User
ApplicationAnswer belongs_to Application
ApplicationQuestionAnswer belongs_to ApplicationAnswer
Now in the view the form would be for creating/updating ApplicationAnswer and having nested forms for its associated ApplicationQuestionAnswer which you will display to the students. And this will save all the answers.
Also the same nested forms can be used with the teacher to add or remove questions. You can also use any gem for nested form too:
cocoon
nested_form
Hope this helps.

Rails: Finding models with missing has_one records

If model User has_one Profile, is there a simple way to find all users who have no profile without a custom query (eg NOT User.where('profile_id IS NULL')) or processing it in the app?
Since the association between User and Profile is already known to Rails I don't want to restate it. I want to keep this DRY. The actual connection between the models is more complex than this simple example (uses keys and class name) and may change in the future.
As #tadman & #antonk already said, you probably want to use scope:
scope :without_profile, where(profile_id: nil)
EDIT:
To answer #David Mauricio's question: you could use it by calling User.without_profile, to return the AR association of all users with a nil :profile_id.
#DriverDan : then I'm really unsure what you're asking for. Ask another question with more details, and we can try to answer it!

Rails beginner help with making a custom order form

So what I basically would like to do is make an order form. In this order form, users will submit information about their company members, and there will also be a part at the end of the order form where the user can select option services that are added by my client from a backend. I am new to rails so I would just like someone to help me make sure that I am going to do this using the best possible practice. Here is what I think I need to do:
Make an Order model
Make a Member model
Make a Field model
In my order model make
has_many :members
has_many :fields
In my member model make belongs_to :order and in my field model make belongs_to :order. Then what I need to do in my orders controller is #fields = Field.all and extract it in a #fields.each block.
P.S. there is one other thing I have to do and that is to make the order form displays 3 types of headers: Corporation, LLC, and Non-profit. What I thought would be smart is if in the url I made it like type=1 and type=2 and type=3 and in my model use an if statement like:
def order_type(type)
if type === "1"
"corporation"
elsif type === "2"
"llc"
else
"nonprofit"
end
end
I think using an if statement is kinda sloppy so for that so if someone could please explain to me the best practice that would be great. Please don't try and answer with a railscasts episode because I have checked out a lot of them already. What I would like is an explanation if possible
Thanks guys it means a lot
Are your fields really so complicated that they require their own model? If your "fields" are a one column list just include them as a column in the model they are applied too.
The problem with using the URL method that you suggested is as follows. Say a user creates a model object and assigns it as a "LLC.". Then your URL would have type=1 somewhere in it as you suggested. Now a user bookmarks this URL and afterwards someone realized it was a typo and instead of LLC the heading should be something else. Now you have a unRESTful situation where you are creating dead links on the Internet or you have urls that are encoded. URL encoding should be used for querying data not dceciding what the data should be.
I would not mess with the urls for the heading question. Instead just add a heading field to the main model that will be displayed and have that field either be LLC etc. Then in the view just have a variable that loads in the value for the object being displayed.

Rails app, and need to add tags to a model

I have this quiz rails app linked to an IRC bot who asks questions (yes, on IRC), where I have this Question model which contains, well, questions, answers, hints, and a few more things.
I started with Quiz model (like, say, the special Halloween or Christmas quiz) with a quiz_id in the questions table, then, I told myself, that it would be nice to be able to categorize the questions, so I added a Category model (like, say, Movies or Books), with a category_id in the questions.
Now, my users would like to be able to add a question to one or more quiz, and to assign one or more categories to questions…
So, I've been thinking about removing the Quiz and Category models and replace them with tags, so that, there will be a halloween tag, a movie tag, and a question can have "halloween movie christmas" for tags.
In my searchs, I've seen quite a few ways to include tags like acts_as_taggable, acts_as_taggable_on_steroids or whatever else someone has imagined :-)
Now, I'm wondering what I should do, and so, I'm asking, what you have done, how you've done it, why you did it this way.
acts_as_taggable_on_steroids is older, but it still works, and is still being maintained. Be sure you're visiting the primary repository for it:
http://svn.viney.net.nz/things/rails/plugins/acts_as_taggable_on_steroids/
You can use acts_as_taggable_on_steroids with named_scopes, here's an article that shows how:
Speed Up and named_scope acts_as_taggable_on_steroids Finds
The actual addition to your model is pretty trivial (this is directly from the article above):
named_scope :tagged_with, lambda { |tags| YourModel.find_options_for_find_tagged_with(tags) }
I think Category can easily be replaced by tags, because they are both used to add metadata to a question.
However, I have my doubts about the Quiz model. If you only use the Quiz model to group your questions, it could be possible to replace it with tags. But I think the Quiz model will include more functionality than just grouping alone. For example, score keeping, picking the next question, etc. So I would keep the Quic model intact.
To implement tagging, acts_as_taggable_on_steroids does work, but is a bit old. It would be nice to have a tagging plugin that uses named_scope in the background, as it would make the plugin far more flexible.

Resources