How to save Responses of dynamically created Forms by Users - ruby-on-rails

I'm relatively new to Ruby on Rails.
I have an app where the User can create Forms.
I've already declared that user has_many forms and forms belongs_to user.
In addition, Forms have a nested model Item which stands for the questions of the Form, allowing a User to make a Form to have multiple questions. Also, Item has_many Answers so one question can have multiple answers (like radio or checkbox type of question). Finally, an Answer has_many Results allowing to store multiple values later for each answer if it is submited by different people.
Users also have Children which I'd like them to apply the Forms that they create.
How can I achieve this?
Would you recommend to create an association between my Child model and Form model?
How would you do it?
So all I need is to have the forms created by one user available to be answered for each one of the user's children.
Update:
So I came up with the following idea:
Create a join table between form and children to map which forms were applied to which child.
Also, the result model should have an answer_id column of the answer which it responded to. And I guess it will need another column to point the id of the join table above to map which form-child belongs to.
¿Do you think this logic is right?
When displaying the form to be used, I plan to display form.title, loop into their items through each item and display its item.title and again loop into its answers through each answer and display its type and label as of the type of field and label for the form_fields of each of the results.
The problem now is how can I manage to do this?
I know how to create and save specific number of Objects but not Dynamic number of Objects.
Code:
form.rb
belongs_to :user
has_many :items, dependent: :destroy
accepts_nested_attributes_for :items, allow_destroy: true
item.rb
belongs_to :form
has_many :answers, dependent: :destroy
accepts_nested_attributes_for :answers, allow_destroy: true
answer.rb
belongs_to :item

Let me point out what may be the problems in your current schema:
Answer has_many Results allowing to store multiple values later for each answer if it is submited by different people
=> What happens if we want to query how many correct answers in Form for a specific User or how many correct answers in total for a Form?
Users also have Children which I'd like them to apply the Forms that they create
=> This is kind of confusing, between User and Form we have the relations: User can create many Forms and User can apply many Form via a model Children
I have researched on kind of this problem before, here is my suggested schema:
Explanation
User has many Form by creating action
Form has many Item
Item has many Question
Question has many Answer (An answer is correct/incorrect)
User applies 1/many Form, each time like that, an AnswerSheet was created between User and Form
AnswerSheet contains many SelectedAnswer so SelectedAnswer belongs to AnswerSheet and original Answer. Additionally, a SelectedAnswer was created by the action that user selects an Answer
This is clearer, we can explain the schema with the real meaning, hence, it is easier to understand & implement
One note I use AnswerSheet instead of your idea of Children, I think that makes sense, you can any term you want, but just make sure people understand it :)

According to your Scenario ,I would like to recommend you there is many to many relationship between children and form and also child has_many results.

Related

Rails - Creating and Validating Many-to-Many relationship with the same model?

This is probably a really simple question, but I've been searching the web for probably around an hour and I can't really find an answer to my problem. It should be clear by what follows that I am very new to Rails, so my terminology and explanation might be a bit confusing.
Let's say that I were making a social media app on Rails, where one of the models is User. I want to make a many-to-many relationship called "friends", which links two users together. Let's say in this situation I also wanted to make a many-to-many between two users called "enemies".
This is all completely hypothetical, but the idea is the same one that I want to use for something I'm working on.
Because a user can have many friends and enemies, but also be many friends and enemies, I would use:
class User < ActiveRecord::Base
has_and_belongs_to_many :users #this should be the friends association
has_and_belongs_to_many :users #this should be the enemies association
end
Now I'm guessing I can't just do that, because I would have to have two tables both named users_users. So, then I switch to:
class User < ActiveRecord::Base
has_and_belongs_to_many(:users, join_table: 'friends',
foreign_key: 'user_id', associate_foreign_key: 'friend_id')
end
With a similar statement for the enemies table. Now, my problem is that I want to have a form that the user can use when they sign up, where they can input their information (this is the User object details), and also list their friends and enemies.
Because the user won't have the database id key for their friends or enemies, they'll have to input the users' names. This is fine, though because the name is also a unique key, guaranteed by the validation.
However, if the user types in the name of a friend, I can't join the two if the friend happens to not exist. So, I use a custom validation class that looks something like this:
class FriendValidator < ActiveModel::Validator
def validate(object)
#lookup user and throw error if not found.
end
end
which will access the variable (object.friends) and (object.enemies)
With something similar for enemies. So therefore, above my has_and_belongs_to_many statements, I have lines that say:
attr_accessor :friends, :enemies #these are attrs because they don't exist within the model's db
validates_with FriendValidator
When I create the form with erb, I have the standard form_for block
<%= form_for(#user) do |f| %>
It seems to me that I can't just stick
<%= f.text_area :friends %>
because friends isn't actually something that will get passed to the User object, but rather a separate table. (Can I, though? Because the attr_accessor is declared in the user's model class?)
So now, we have my main problem. I have two many-to-many tables with a model to its own model class, and I don't know how to ensure that the validation class will take the two attributes, lookup and throw necessary errors, and then add a row to the join tables using the id of the user, rather than the string inputted. What form fields should I use to pass the input to the right place? Where do I change the controller methods so that the input gets sent to the join table rather than the user object?
This definitely seems like a pretty specific situation, so I can't really find an answer in the Rails documentation, which I've been learning from.
My initial impression of this problem has to do with your associations. To me, a user has_many enemies and has_many friends.
friends belong_to user
enemies belong_to user
Not sure if a many to many relationship makes sense in this case. Maybe that's why you are having such a hard time finding an answer online. Just my two cents.

Save data and repopulate form without creating a column for each field

I have a situation where I need to collect data from a user, save the data, and later be able to go back and view the data. In this case it is a survey. Normally I would create a model and put in some validations and it would be pretty straightforward.
But in this case the questions change so frequently that if I did that I might find myself writing new migrations and performing all kinds of maintenance constantly. And since all we really want is the data itself, it occurred to me that I should just make a model that has an id field and a form_data field and just stick whatever the params are into that form_data field. That way all I have to do is change the view and not mess with the model at all.
But later if I wanted to edit the data in the survey, how would I populate the form fields? The goal is to only change the view whenever my boss wants to add new questions.
P.S. I would prefer not to use Surveyor for this task since I'd like to be able to do some things that aren't easily don ein Surveyor from what I can tell.
So this is what it might look like
SurveySubmissions
id : integer
form_data: string
SurveySubmissions.find(1).form_data
"name":"Kevin"
"gender":"Male"
"favorite_color":"blue"
If you are using PostgreSQL you can take a look at Hstore. A nice starting point is this Railscast: http://railscasts.com/episodes/345-hstore (pro episode, so it requires payment).
It allows you to store all question/answer pairs in single database column.
You can also serialize your data into single database column as json/yml and use virtual attributes on your model to make it easy to populate form fields (Railscast episode about virtual attributes: http://railscasts.com/episodes/16-virtual-attributes-revised, there is also old episode for free)
Another solution (and my favorite) is to use MongoDB + Mongoid and its dynamic attributes.
It can be the best solution if you didn't start coding yet.
This might be helpful for you :
User Model
has_many :surveys
Survey Model
belongs_to :user
has_many :questions
Submissions Model
has_many :questions
belongs_to :user
belongs_to :survey
Question Model
has_many :answers
polymorphic => belongs_to "survey and submissions"
Answer Model
belongs_to :submission
belongs_to :question
and on top of this u can build relations and other stuff you require as per your requirements
I think the best choice is to save the form fields into the database and then use javascript to repopulate the form when editing. So I pull all the field values into a variable and then use JQuery.each to populate the fields.
surveySubmissionData = {"incident_id":"2013BaconSupreme",
"_confirmed":"No",
"_date_began":"2/26/2013"}
// Put some code here that loops through the surveySubmissionData
// and populates the form.
jQuery.each(surveySubmissionData, function(i, val) {
$("#" + i).val(val);
});

Limiting an attribute in Rails

I have a Tournament model that needs 0, 1, or 2 contacts. I created a Contact model and set has_many :contacts on the Tournament and belongs_to :tournament on the Contact. The Tournament accepts_nested_attributes_for :contacts.
However, when I build the form for Tournament I don't quite see how I should do it. I'm thinking about having two fields_for :contacts but it feels messy. I also considered having two specific attributes on the Tournament model (something along the line of primary_contact and secondary_contact) but I'm not sure about how to do that.
Is there a "correct" way to do this? Any suggestions?
I'm on Rails 3.1 BTW.
fields_for :contacts is the right way to go.
Take advantage of the fact that, if tournament.contacts has multiple items, then a single fields_for :contacts will show multiple fieldsets.
Then take advantage of the fact that tournament.contacts.build will create an unsaved Contact and add it to the contacts collection. If you do this in the controller before showing the form then your fields_for will display this empty contact and use it correctly with its nested attributes
I think you shouldn't limit the contacts for 2 fields, because I think you should keep the flexibility of adding more contacts for a tournament later
I have done a small example (by using check boxes) between Project to users, you might be able to get idea
https://github.com/sameera207/HABTMsample
I'd suggest maybe adding a non-persistent contact_list attribute and then you could enter as many contacts as you need separated by commas into one field:
has_many :contacts
attr_accessor :contact_list
def contact_list=value
value.split(',').each do |email|
self.contacts.build(:email => email).save
end
end
def contact_list
self.contacts.join(',')
end
If you need to enter more information for each contact (not just a name, email, or phone number), then you would need more fields.
The following railscast may help you:
http://railscasts.com/episodes/196-nested-model-form-part-1

Rails - Add many objects to another object type

Suppose that I've two controllers, "good" and "customer" and that I want add many goods to a single customer; in which way can I do this?
I mean, I need a customer's show view that list all goods associated to that project and a "add good to customer" used to add a new object to customer.
You would want to do that at the model level with an association and then allow for nested attributes.
It might look like this
model
class customer < ActiveRecord::Base
has_one :goods
accepts_nested_attributes_for :goods
end
Then in the views for customer you would want to have the nested form. This Railscast gives a good overview for that. Because of the association and the accepts you can automatically inherit them in the controller. Also there is a similar question here that amplifies the explanation.

How to access and submit related polymorphic models in the same form, in Rails?

Suppose I have 3 models, Car, Motorcycle and Truck, and for each I have to enter a bunch of stuff, such as a list of known previous owners, traffic tickets, license plates, etc. So I created a model for each (PreviousOwners, PreviousPlates, etc) and set up polymorphic associations for the related models.
The problem is, how can I enter all of that using just one form, kind of like this:
Car #123
Known previous owners:
Jason Jazz
Brian Bass [add another]
Known previous license plates:
12345
67890 [add another]
Current status:
Cleared
(this is a dropdown select menu, CurrentStatus is also a polymorphic association, but with predefined values.)
etc
This is proving to be a bitch, way beyond my level of expertise (newbie here). The resources are not nested and almost everything I find on multiple models is for nested resources, and nothing seems to apply to polymorphic associations.
(This is just an example, I know ideally I should have a Vehicle model with 'Car', etc, as categories, but it's just to illustrate the real need for polymorphic models in my case.)
Thanks.
Maybe the PresenterPattern is helpfull too:
http://blog.jayfields.com/2007/03/rails-presenter-pattern.html
The basic idea is to create a presenter which acts like a model and processes all the incoming data from your form and distributes it to the models. This way it's also easy to create multiple instances of lets say PreviousOwner and attach it to Car.
Check the link out!
You can use the new nested attributes in Rails 2.3, but there is a certain way you have to write it to make it work. The trick is that you need to create the actual polymorphic object, then build the class that has the belongs to polymorphic clause in it. This is an example I found at Ryans Scraps, posted by a user named: Superslau (I've cleaned it up a good bit for here):
This feature is really awesome. I have
implemented this with polymorphic
associations, and it works!
class Task < ActiveRecord::Base
has_many :assets, :dependent=>:destroy
accepts_nested_attributes_for :assets, :allow_destroy => true
belongs_to :workable, :polymorphic => true
end
class Upload < ActiveRecord::Base
has_one :task, :as => :workable, :dependent=>:destroy
accepts_nested_attributes_for :task, :allow_destroy => true
end
Upload is a kind of task. All tasks
can have one or more assets uploaded.
I took me a while to figure out that I
should use the Upload model as the
parent. So in one form, I can create
an upload, and it’s corresponding task
entry, along with a file upload.
in my controller:
def new
#upload = Upload.new
#upload.task = Task.new
#upload.task.assets.build
end
Don’t
worry if that doesn’t make any sense,
I just wanted to let people know that
accepts_nested_attributes_for works
just fine with polymorphic
associations. Thanks Eloy!
Very well, nested form builders doesn't have to be associated with nested resources AFAIK.Can you post your models code as well?
There is a RailsCast on Complex Forms that might help you with building a single form from multiple models.
If the car/motorcycle/truck models are identical, you should add a type column to your vehicle model. If they're not, you should use STI (single table inheritance).
But yeah, need to see your models first before I can give you code.
You can avoid this and make things a bit simpler by introducing a Vehicle model. The Vehicle model can have all your PreviousOwners, PreviousPlates, etc collections, and then your Truck, Car and Motorcycle models can has_one Vehicle.

Resources