Rails 3 - Nested Forms, using Builder - ruby-on-rails

I have the following:
My Controller:
def new
.
.
#teammembers.each do |teammember|
request = #request_thread.requests.build(:recipient_id => teammember.user_id, :full_name => 'Billy Bob T')
end
My View:
<%= f.fields_for :requests do |builder| %>
<div class="field">
<%= builder.label :full_name %>
<%= builder.check_box :recipient_id, :checked => false %>
</div>
<% end %>
The nested form for request only holds the user_id, not the user.name... Problem is in the nested form, I need to show the user.name next to the check_box. So I tried adding a virtual attribute in the model (attr_accessor :full_name), so I could use full_name but I can't see to access that in the nested form (inside builder).
Any tips or suggestions from the pros?
Thanks

What about:
User.find(:recipient_id).name
EDIT: I hope i understood your question ..

Related

Rails 4 : Checkbox array is not updating my attribute

My starting place was this discussion: Syntax for form_for when building an array from checkboxes
I have a call to my model passing back an array of valid options. This array then makes a series of check_box_tag
<%= form_for #game, :url => wizard_path do |f| %>
<div>
<% #game.select_races.each do |a| %>
<%= f.label a %>
<%= check_box_tag 'game[races][]', a , true %>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
This successfully creates an array called 'races' containing the desired output. The problem is that it doesn't actually update the races attribute. So my races attribute is still nil.
I'm sure this is a painful Rails beginner question. Any help is appreciated.
UPDATE
My allowed params were:
def game_params
params.require(:game).permit(:shattered_empire, :shards_of_the_throne, :number_of_players, :rules, :strategy_cards, :players, :races)
end
Which needed to be updated to:
def game_params
params.require(:game).permit(:shattered_empire, :shards_of_the_throne, :number_of_players, :rules, :strategy_cards, :players, {:races => []})
end

Ruby on Rails 3: How to pass a parameter to a select box in a form?

I have a Client model that can have many Projects.
These are my view files:
edit.html.erb
<%= form_for(#project) do |f| %>
<%= render 'fields', :f => f %>
<%= f.submit Create %>
<% end %>
_fields.html.erb
<div>
<%= f.label :name %><br/>
<%= f.text_field :name %>
</div>
<div>
<%= f.label :client_id %><br/>
<%= f.select(:client_id, current_user.client_names) %>
</div>
This is easy and works great.
But is there a way to create a Project from within a Client view as well?
For example on the client edit page it would be nice to have a link New Project for this Client that leads to the above New Project form, but with the respective client preselected in the select box.
Can this be done somehow?
I can't seem to find a way to pass the Client ID to the New Project form.
Thanks for any help!
This is certainly possible, but requires passing the client id to the new_projects_path. This can be done by nesting the routes to projects inside of clients, or just appending the client id. The difference would be URLs that look like the following:
/clients/1/projects/new
- or -
/projects/new?client_id=1
In your projects controller, you should be able to instantiate the #project variable with a preselected client:
#project = Project.new :client_id => params[:client_id]
Yes, you can do this. You're going to use accepts_nested_attributes_for :project in your Client model. Nesting this will allow you to do something like
<%= f.fields_for :project do |p| %>
<fieldset>
<%= p.text_area :content %>
</fieldset>
<% end %>
Check out the railscasts episode #196 on Nested Model Form.

Ruby on Rails: Multiple Input Fields in The Same Form - Change ID/Value

Have a page where there are multiple input fields of the same thing, Posts. Right now, when a user enters in a question for, let's say 3 fields, the only one that saves to the database is the last one. Whereas, it should save all three and give them each it's own post_id. Also; if the user doesn't enter anything in for the other fields, it should not save in the database either.
new_step_4_html.erb
<%= form_for(#post) do |f| %>
<%= f.text_field :content %>
<%= f.text_field :content %>
<%= f.text_field :content %>
<% end %>
projects_controller.rb
def new_step_4
#post = Post.new
end
Right now, all it does is submit one :content field, obviously because they all share the same id/value. Unfortunately, the Railscasts #197 applies for nested forms, so the javascript and helper stuff he does all applies for nested. I would think this is something simple. Person from IRC mentioned I could do some sort of '3.times' code into the view file or something?
First of all you will probably have to edit the model of you post.
post.rb
has_many :contents, :dependent => :destroy
accepts_nested_attributes_for :contents
You will need another model to store the content fields.
so first generate a model
rails g model content post_id:integer body:text
the model
content.rb
belongs_to :post
Now, in stead of doing <%= f.text_field :content %> a few times, let rails create them, because now you basically let them overwrite each other.
3.times do
content = #post.content.build
end
the form view will be something like this:
<%= form_for #post do |f| %>
<%= f.fields_for :contents do |builder| %>
<%= builder.label :body, "Question" %><br />
<%= builder.text_area :body, :rows => 3 %><br />
<%= end %>
<p><%= f.submit "Submit" %></p>
<% end %>
I did not test this code, but the idea should be correct. Let me know if you need more info.

How to use the select_tag helper in a nested form?

UPDATE: SOLUTION AT BOTTOM
I'm hoping someone else has spent some time ironing out this same issue... I'm building an address book within an rails application, and I have an Person model and an Email model. Person has_many Emails, and Person accepts_nested_attributes_for :emails.
This all works perfectly -- I have a nested form with which I can add and remove emails and their attributes in my form (using a method similar to Railscasts 196-7 (here)). Submitting the form creates the Person, as well as the Emails, with all the correct associations.
The problem is, as it stands, I'm unable to find a way to use a select tag on the nested email model for the user to select a KIND (e.g. work, home, other) for that email. So, editing the Person model as I have it now, there is no easy way to select the attribute that is stored in the rails model.
Here's what I have now:
<%= form_for(#source) do |f| %>
<% f.fields_for :emails do |builder| %>
. . .
<%= builder.text_field :address, :size => 15 %>
<%= render :partial => 'email_select_1' %>0<%= render :partial => 'email_select_2' %>0<%= render :partial => 'email_select_3' %>
Note: the above is a hacky way of allowing me to set the ID later in javascript using the same code fragments. The partials spit out a hard-coded select and options, in this case '0' but in javascript I can change it to a unique:
<select id="person_emails_attributes_0_kind" name="person[emails_attributes][0][kind]"><option value="work">work</option><option value="home">home</option><option value="other">other</option></select>
and then the rest looks like this (abbrev):
. . .
<% end %>
. . .
<!-- more form stuff, actions, etc... -->
. . .
<% end %>
Is there a way to use the select_tag helper for this, and replace my hacky-hard-coded select? If not, any suggestions for writing my own helper method?
Thanks in advance!
UPDATE: Thanks to Geoff for the solution. For posterity, the big thing is to use select, not select_tag. Then you can just do something like this:
<%= builder.select :kind, [['work', 'work'], ['home', 'home'], ['other', 'other']]%>
you should just need to pass the formbuilder variable to the partial. you would do so by coding your partial like this:
<%= form_for(#source) do |f| %>
<% f.fields_for :emails do |builder| %>
. . .
<%= builder.text_field :address, :size => 15 %>
<%= render :partial => 'email_select_1', :locals => {:builder => builder} %>
<% end %>
<% end %>
And then your partial you would use:
<%= builder.select :kind %>
just as if it was within the fields_for block.
Hope this helps!

Multiple forms for the same model in a single page

On the front page of my rap lyrics explanation site, there's a place where users can try explaining a challenging line:
alt text http://dl.dropbox.com/u/2792776/screenshots/2010-02-06_1620.png
Here's the partial I use to generate this:
<div class="stand_alone annotation" data-id="<%= annotation.id %>">
<%= song_link(annotation.song, :class => :title) %>
<span class="needs_exegesis"><%= annotation.referent.strip.gsub(/\n/, "\n <br />") %></span>
<% form_for Feedback.new(:annotation_id => annotation.id, :created_by_id => current_user.try(:id), :email_address => current_user.try(:email)), :url => feedback_index_path, :live_validations => true do |f| %>
<%= f.hidden_field :annotation_id %>
<%= f.hidden_field :created_by_id %>
<p style="margin-top: 1em">
<%= f.text_area :body, :rows => 4, :style => 'width:96%', :example_text => "Enter your explanation" %>
</p>
<p>
<% if current_user %>
<%= f.hidden_field :email_address %>
<% else %>
<%= f.text_field :email_address, :example_text => "Your email address" %>
<% end %>
<%= f.submit "Submit", :class => :button, :style => 'margin-left: .1em;' %>
</p>
<% end %>
</div>
However, putting more than one of these on a single page is problematic because Rails automatically gives each form an ID of new_feedback, and each field an ID like feedback_body (leading to name collisions)
Obviously I could add something like :id => '' to the form and all its fields, but this seems a tad repetitive. What's the best way to do this?
If you don't want to change your input names or your model structure, you can use the id option to make your form ID unique and the namespace option to make your input IDs unique:
<%= form_for Feedback.new(...),
id: "annotation_#{annotation.id}_feedback"
namespace: "annotation_#{annotation.id}" do |f| %>
That way our form ID is unique, i.e. annotation_2_feedback and this will also add a prefix, e.g. annotation_2_, to every input created through f.
Did you consider nested_attributes for rails models? Instead of having multiple new feedback forms where each is tied to an annotation, you could have multiple edit annotation forms where each annotation includes fields for a new feedback. The id's of the generated forms would include the annotations id such as edit_annotation_16.
The annotation model would have a relationship to its feedbacks and will also accept nested attributes for them.
class Annotation < ActiveRecord::Base
has_many :feedbacks
accepts_nested_attributes_for :feedbacks
end
class Feedback < ActiveRecord::Base
belongs_to :annotation
end
You could then add as many forms as you want, one for each annotation. For example, this is what I tried:
<% form_for #a do |form| %>
Lyrics: <br />
<%= form.text_field :lyrics %><br />
<% form.fields_for :feedbacks do |feedback| %>
Feedback: <br/>
<%= feedback.text_field :response %><br />
<% end %>
<%= form.submit "Submit" %>
<% end %>
<% form_for #b do |form| %>
Lyrics: <br />
<%= form.text_field :lyrics %><br />
<% form.fields_for :feedbacks do |feedback| %>
Feedback: <br/>
<%= feedback.text_field :response %><br />
<% end %>
<%= form.submit "Submit" %>
<% end %>
And the quick and dirty controller for the above edit view:
class AnnotationsController < ApplicationController
def edit
#a = Annotation.find(1)
#a.feedbacks.build
#b = Annotation.find(2)
#b.feedbacks.build
end
def update
#annotation = Annotation.find(params[:id])
#annotation.update_attributes(params[:annotation])
#annotation.save!
render :index
end
end
I had this same issue on a site I'm currently working on and went with the solution you mention at the bottom. It's not repetitive if you generate the ID programmatically and put the whole form in a partial. For example, on my site, I have multiple "entries" per page, each of which has two voting forms, one to vote up and one to vote down. The record ID for each entry is appended to the DOM ID of its vote forms to make it unique, like so (just shows the vote up button, the vote down button is similar):
<% form_for [entry, Vote.new], :html => { :id => 'new_up_vote_' + entry.id.to_s } do |f| -%>
<%= f.hidden_field :up_vote, :value => 1, :id => 'vote_up_vote_' + entry.id.to_s %>
<%= image_submit_tag('/images/icon_vote_up.png', :id => 'vote_up_vote_submit' + entry.id.to_s, :class => 'vote-button vote-up-button') %>
<% end -%>
I also had the same issue but wanted a more extensible solution than adding the ID to each field. Since we're already using the form_for ... |f| notation the trick is to change the name of the model and you get a new HTML ID prefix.
Using a variant of this method: http://www.dzone.com/snippets/create-classes-runtime (I removed the &block stuff)
I create a new model that is an exact copy of the model I want a second form for on the same page. Then use that new model to render the new form.
If the first form is using
#address = Address.new
then
create_class('AddressNew', Address)
#address_new = AddressNew.new
Your ID prefix will be 'address_new_' instead of 'address_' for the second form of the same model. When you read the form params you can create an Address model to put the values into.
For those stumbling here, looking for the solution for Rails 3.2 app, look at this question instead:
Rails: Using form_for multiple times (DOM ids)

Resources