Rails build fields_for once inside fields_for - ruby-on-rails

in my
<%= nested_form_for #object do |f| %>
I've a nested_form like:
<%=f.fields_for :nested, :url => { :action => "new" } do |build| %>
<%= render 'nested_fields', :f => build %>
<% end %>
and inside that nested_field, I've another fields_for :nested2
My Problem is: I want nested2 appearing 1 time, when nested is called.
I tried inside the new action of the nested controller the
#nested = Nested.new
#nested.nested2.build
but this does only work for the "real" new action.
Is there any solution for that problem?
I'm using the "nested_form" gem.

fields_for lets you specify a particular object to render the fields for, so if you want your nested_fields partial to contain nested fields for a single, newly build nested2 model, you can do it in the fields_for call itself, like this:
# '_nested_fields.html.erb'
...
<%= f.fields_for :nested2, f.object.build_nested2 do |build| %>
<%= ... %>
<% end %>
This is assuming that Nested has_one :nested2, if it's a has_many association the fields_for arguments would be slightly different:
<%= f.fields_for :nested2s, f.object.nested2s.build do |build| %>
f.object allows you to access the form builder's object, and you can then use it's association methods (based on the association type) to build the new object at that point.

Related

rails, form_for in a secon route, but on the same model

In a rails 4 application, I have a book resource, that is a Book model with its controller, views and route. It's what gets created by:
rails g scaffold book title
Now I want to have another set of views (and another controller) that allows to manage the same model, maybe dedicated to a different user.
I want both the creating function and the editing function to be available on this different route and view, .
Let's call it book2.
The views in the /book2 url should operate on the Book2sController.
form_for support
But the form_for guesses the submit route (and puts it in the action attribute) from the model class, that, being it always Book, lets rails guess that the submit url is /books/1 for edit or /books/ for new and not /book2s/1 for edit and /book2s/ for new as it should be.
So i found this solution, but i find it to be a bit cumbersome.
Is there anything better out there?
<%= form_for #book, :url => #book.new_record? ? url_for(book2s_path) : url_for(book2_path(#book)) do |f| %>
<%= f.text_field :title %>
<% end %>
You could set the url in your controller.
def new
# ...
#form_url = book2s_path
# ...
end
def edit
# ...
#form_url = book2_path(#book)
# ...
end
Then your view becomes:
<%= form_for #book, :url => #form_url do |f| %>
<%= f.text_field :title %>
<% end %>
I have also seen:
<%= form_for #book, :url => {:controller => 'book2s', :action => #action} do |f| %>
<%= f.text_field :title %>
<% end %>
and you just set #action in the controller (probably create or update).
Note that you don't need to include the url_for like you have.

Rails4 : Referencing associated model in fields_for partial

I broke out my form fields for a associated model into a partial. I want to reference the associated model in the partial but I'm not sure how to do that. #position and #position_fields are both nil. I see render ..., object: #something but I am not sure how to reference the current position model to pass it in.
apps/views/events/_form.html.erb
<%= f.fields_for :positions do |builder| %>
<%= render 'position_fields', f: builder %>
<% end %>
apps/views/events/_position_fields.html.erb
Fields for <%= #position.name %>
<%= f.text_field :name %>
How do I reference the associated model in the fields_for partial?
In your apps/views/events/_position_fields.html.erb, you can do the following:
Fields for <%= f.object.name %>
<%= f.text_field :name %>
This is because the builder has a reference to each of the position object and that you are passing builder as a local to the position_fields partial with the name f.
Reading through this doc will be useful: http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for.

Nested attribute not saving in a form with polymorphic associations

I'm trying to make an app where a user can save goals, milestones for those goals, tasks for the milestones, and tasks for the goal itself. I'm using polymorphic associations, but making a form to input all of them has proven difficult. The problem is that the milestones aren't saving at all, and the milestone tasks are being listed in the database as having type "Goal" instead of type "Milestone" The models and database are set up like the top answer for this question.
I'm hoping someone could take a look at my form_for implementation and see if it's correct, or if the problem is somewhere else. Let me know if you need to see some other code.
<%= nested_form_for #goal do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<%= render 'shared/goal_fields', :f => f %>
<%= f.fields_for :milestones do |ff| %>
<%= render 'shared/milestone_fields', :f => ff %>
<% end %>
<%= f.fields_for :tasks do |ff| %>
<%= render 'shared/task_fields', :f => ff %>
<% end %>
<%= f.link_to_add "Add Milestone", :milestones %>
<%= f.link_to_add "Add Task", :tasks %>
<%= f.submit %>
<% end %>
The Rails form builder method fields_for allows you to nest attributes for multiple records. This part of your code looks correct (assuming that your partials are working). You can make your fields_for line more explicit by building the relationship off of the goal object as follows:
<%= f.fields_for :milestones, #goal.milestones.build do |ff| %>
<%= render 'shared/milestone_fields', :f => ff %>
<% end %>
Ensure that your models have the following code in order to process the parameters that will be passed to each of these models:
# app/models/goal.rb
has_many :milestones
has_many :tasks
accepts_nested_attributes_for :milestones
accepts_nested_attributes_for :tasks
# app/models/milestone.rb
has_many :tasks
accepts_nested_attributes_for :tasks # For tasks on milestones
Also ensure that if you are using attr_accessible to lock down your model attributes from mass-assignment, that these entries have corresponding entries (milestones_attributes, tasks_attributes, etc)
When you submit the form, look at the rails development log, and ensure that you see the parameters come through in a format similar to:
{:goal => {:milestones_attributes => {:tasks_attributes => {}, :tasks_attributes => {} }}
If all this data is going through, but the record is still not being saved, check for "ROLLBACK" entries in the log that might indicate that a record is not valid, and could not be inserted.
More info on nested_attributes can be found here:
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
Info on the form helpers utilizing these nested attributes can be found here:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for

Rails partial view set value of form field

Okay so I am quite new to Rails and am trying to do the following without success:
I have an Object (from my Active Record) containing a project, which contains n sub-projects, which contain n tasks. Now for each of these I want a partial view.
So I render from the project view the sub-project with the following code:
<%= render(:partial => 'subproject', :collection => #project.sub_projects) %>
Within my sub-project partial view called _subproject.rhtml (adding the code to a good ol Rails 1.2.3 project), so I can access the data like this:
<%= subproject.name %>
That will print out the name alright but when I try to generate a textfield this won't work:
<%= text_field 'subproject', 'name' %>
But this will:
<%= text_field 'subproject', 'name', :value => subproject.name %>
What am I doing wrong?
Edit: Changed title due to my problem is not passing the value but displaying it within a form field.
Edit2: As requested my controller code:
#project = Project.find(params[:id])
You can write this:
<%= render(:partial => 'subproject', :collection => #project.sub_projects) %>
as
<%= render :partial => #project.sub_projects %>
This will render every sub project with the sub_projects/_sub_project.html.erb partial. A little shortcut.
This:
<%= text_field 'subproject', 'name' %>
Says create a text_field called: subproject[name], but doesn't give it a value. You need to pass the value you want to set (the code that works).
The more idiomatic way of doing this now is with form_for:
<% form_for #subproject do |f| %>
<%= f.text_field :name %>
<% end %>
Or if you're using formtastic (https://github.com/justinfrench/formtastic), which is fantastic, you'd write:
<% semantic_form_for #subproject do |f| %>
<%= f.input :name %>
<% end %>
I hope this helps!

virtual model and form_for (or formtastic)

Sometimes we need form without model creation - for example search field or email, where should be send some instructions. What is the best way to create this forms? Can i create virtual model or something like this? I'd like to use formtastic, but not form_tag.
Firstly, Formtastic doesn't need a model in all cases, although it certainly works best and requires less code with a model.
Just like Rails' own built-in form_for, you can pass in a symbol instead of an object as the first argument, and Formtastic will build the form and post the params based on the symbol. Eg:
<% semantic_form_for(:session) do |f| %>
...
<% end %>
This will make the form values available to your controller as params[:session].
Secondly, a model doesn't mean an ActiveRecord model. What I mean is, Formtastic will work with any instance of a class that quacks like an ActiveRecord model.
A classic example of this that many people are using Authlogic for authentication with Formtastic. Part of Authlogic is the idea of a UserSession model, which works fine:
Controller:
def index
#user_session = UserSession.new
end
Form:
<% semantic_form_for(#user_session) do |f| %>
<%= f.input :login %>
<%= f.input :password %>
<% end %>
This will make your form data available in your controller as params[:user_session].
It's really not that hard to create a model instance to wrap up the concerns of your model. Just keep implementing the methods Formtastic is expecting until you get it working!
default_language.rb
class DefaultLanguage
attr_accessor :language_id
end
foo_controller.rb
def index
#default_language = params[:default_language] || Language.find_by_name("English")
end
index.erb
<% semantic_form_for #default_language do |form| %>
<% form.inputs :id => 'default_language' do %>
<%= form.input :id,
:as => :select,
:collection => #languages,
:required => false,
:label => "Primary Language:",
:include_blank => false %>
<% end %>
<% end %>
I used AJAX to post the form when the value changed.
Or you simply create a form with form_for and leave the model reference blank.
for example
<% form_for "", :url=>some_url do |f| %>
<%= f.text_field "some_attribute" %>
<%= submit_tag "submit" %>
You can fetch the values by simply saying params[:some_attribute] in your controller.

Resources