How to edit accepts_nested_attributes_for? - ruby-on-rails

I have a Company model that has_many Address(es) and many Phone(s).
Address(es) belong_to Company as do Phone(s).
My problem is that I don't understand how to edit a Company's particular Adress and Phone.
In my edit action, I call up the specific record and assign it to an instance variable (i.e. #address = some scoped searched for the specific address I want), and then in my fields_for I references this child's attributes, ex:
<%= f.fields_for :addresses, #address do |address| %>
A) I'm not sure if this is the way to do it. The documentation on how to access a parent's specific child for editing is sparse.
B) While this works fine if the update succeeds, when it fails and I render :edit the view presents additional fields with the parent's current child (the one I specified in my edit action + another child -- seemingly the next record in line).
So basically, my form is extended with two children when the render :edit is called. Weird.
What's the deal with this? How do nested attributes work? Is there a better way to manage forms with multiple associated models?
Thanks.

It sounds like you are using the fields_for helper outside of its purpose here. From what you've described, you want to edit an address outside of its parents relationship. If that's the case you'll edit that address in its own form (and likely its own controller) using the form_for helper.
The fields_for would be used if you wanted to do any CRUD operations in the same form as the parent thereby leveraging the accepts_nested_attributes_for functionality.

Defiantly watch the screen casts that dmarucco posted to get a good and general understanding of nested forms, then check out the problem I had before here with nested forms (I too had a many to many relationship):
Rails 3.1+ Nested Forms Issue: Can't mass-assign protected attributes
I posted my solution at the bottom of that page.
I also used nested_form and simple_form gems for formatting my nested forms, so you may want to look into that
Hope this sets you in the right path!

These screencasts could you help much more than thousands words.
Railscast - Lesson 1
Railscast - Lesson 2

Related

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.

Reform to wrap a collection of records to be saved simultaneously

I have a collection of records that are related to a specific parent object. I have no need to update the parent, just want to update all the children.
I tried making a Reform::Form and simply adding the collection declaration. An example might be a developer has many projects. When the developer goes on holiday his projects are "on_hold", but some of them might still be active. So, I would like to list all the projects with a checkbox to check if they should be put on hold. I essentially want to have a simple_fields_for :projects.
Does it make sense to use Reform for this?
I have this code:
class ProjectsForm < Reform::Form
collection :projects do
property :name #perhaps I want to rename them in the same form (bear with me)
property :on_hold
end
end
This should work, but when initializing the form with a hash
#form = ProjectsForm.new({projects: #array_of_projects})
I get an error
undefined method `projects' for #<Hash:0x007fce8f2783b8>
As if the collection method is not working. I am obviously doing something stupid.
I'd really like to use Reform. I love the philosophy behind a lot of the trailblazing suit of gems. It will be great if someone can point me in the right direction here.
If it turns out this isn't a good usecase for Reform I'll find another :P
Update:
I think reform is slightly more coupled with the idea of a model than what I thought. I thought it was just a form object with properties to play nicely with form builder. I now find that your model is key. You need to initialize the Reform form with A model, or in the case of composition, a few models. However, if you pass in an array of hash reform believes this is the model and then tries to access the :projects property on the model. In my case a hash.
I have now added a
# my contrived example is getting lame
attr_accessor :projects
to the developer class and it is working. At least the generating the reform object is working.
I am still curious wether this is a good use-case for Reform.

Mixing forms in Rails

In my app users can register information about a tournament. If the user is a paying customer, she can fill in additional info, otherwise the fields for the additional info are unavailable (visible but disabled).
I laid this out as two objects: Tournament and TournamentExtras where the former has_one :tournament_extras and the latter belongs_to :tournament. Tournament also accepts_nested_attributes_for :tournament_extras.
I would like this to show up as a single form. The fields in the two objects are related, meaning you can add a start date (to Tournament) but only paying customers can add an end date (to TournamentExtras) but since the two fields are logically realted, they should show up after eachother in the form.
How do I do this?
I tried opening the form_for and fields_for loops withing eachother (before adding any fields) hoping that I could add any field whereever I like. That didn't work; apparently you can't reference the form object within the fields loop(?).
form_form and fields_for should work with each other.
Somewhat of a skeleton for this is:
form_for(#tournament) do |f|
f.fields_for(#tournament.tournament_extra) do |g|
end
end

Build rails form fields from associated models

Rails3,jQuery. What I'm trying to do: Create a new WorkoutPlan that HABTM Exercises. Then create a new Workout that belongs_to a WorkoutPlan. I want the Workout#edit page to build a form with fields_for new/edit WorkoutRoutines, one routine for each exercise in the WorkoutPlan.
That last part is where I'm struggling, creating one Routine for each Exercise in the WorkoutPlan. Everything else works, its just this form build that sucks. Not sure if I'm making this overly complicated, or if there was an easier way. Any ideas?
From what I understand, using nested attributes should solve the problem without many complications. From the link,
Nested attributes allow you to save
attributes on associated records
through the parent. By default nested
attribute updating is turned off, you
can enable it using the
accepts_nested_attributes_for class
method. When you enable nested
attributes an attribute writer is
defined on the model.
The attribute writer is named after
the association, which means that in
the following example, two new methods
are added to your model:
author_attributes=(attributes) and pages_attributes=(attributes).
anytime you need a complex form in rails its either going to be a pain, or can use formtastic. super easy awesome forms, plenty of ways to deal with habtm relations as well.

Friendship invite form with hobo

The hobo lifecycle tutorial shows how to implement a friendship logic in
the model and controller. However it does not really cover how to glue
the gui/views together. When I go to /friendships/invite - hobo
presents me with a form with a drop down menu. How do I add a form to
the user show-page with just one button (Invite) I guess that the the
user viewed should be in a hidden field?
I tried adding the form like this:
<extend tag="show-page" for="User">
<old-show-page merge>
<append-content-body:>
<invite-form for="Friendship" />
</append-content-body:>
</old-show-page>
</extend>
Hobo ignores the invite-form hmmm I must be missing something.
Best regards
Asbjørn Morell
try <invite-form:friendships.build/> assuming you have has_many :friendships on your user model. for is an attribute on the 'def' and 'extend' tags, it's not recognized by 'form'. To use a polymorphic tag, simply pass in an instance of the correct type in the context. This of course is easier if an instance already exists, but since you're using a creator action, just build one.
P.S. Questions like this get answered much quicker on the Hobo Users mailing list.

Resources