rails how to do f.parent.text_field :name - ruby-on-rails

I need to put fields from journals and journal_entries into one row on a table, and have the ability to add and show many data entry rows in the same view. (ie a table of rows and using link_to_add_fields with accepts_nested_attributes to expand the rows in the table).
There has to be some kind of f.parent.text_field or f.object.parent.text_field?
I'm trying to do something like the following
<table>
#in a :pm namespace
<%= form_for [:pm, #lease] do |f| %>
<%= f.fields_for :journal_entries do |journal_entries| %>
<%= render "journal_entry_fields" , f: journal_entries %>
<% end %>
<%= link_to_add_fields "+ Add transactions", f, :journal_entries %>
<% end %>
</table>
_journal_entry_fields.html.erb
<fieldset>
<tr>
## HERE IS WHAT I'M LOOKING FOR <<<<<<<<<<<!!>>>>>>>>>>>>>
<td><%= f.parent.text_field :dated %></td>
<td><%= f.parent.text_field :account_name %></td>
<td><%= f.text_field :credit %></td>
<td><%= f.text_field :notes %></td>
</tr>
</fieldset>
My Models
class Lease < ActiveRecord::Base
has_many :journals, :order => [:dated, :id] #, :conditions => "journals.lease_id = id"
has_many :journal_entries, :through => :journals
accepts_nested_attributes_for :journal_entries , :allow_destroy => true
accepts_nested_attributes_for :journals , :allow_destroy => true
end
class Journal < ActiveRecord::Base
belongs_to :lease, :conditions => :lease_id != nil
has_many :journal_entries
accepts_nested_attributes_for :journal_entries , :allow_destroy => true
end
class JournalEntry < ActiveRecord::Base
belongs_to :journal
end
I'm using Rails 3.2.12 and ruby 1.9.3
I'm trying to see if this is a better solution than the problem faced on: rails link_to_add_fields not adding fields with has_many :through (with nested form inside)
I made a different thread because I think it's so drastically different.
Thanks,
Phil

As per my understanding about your use-case you want to create journals and its entries in a single form of Lease. So, you can us the fields_for for both of them as below:
<table>
#in a :pm namespace
<%= form_for [:pm, #lease] do |f| %>
<%= f.fields_for :journals do |journal| %>
<%= render "journal_entry_fields" , f: journal %>
<% end %>
<%= link_to_add_fields "+ Add transactions", f, :journals %>
<% end %>
</table>
_journal_entry_fields.html.erb
<fieldset>
<tr>
<td><%= f.text_field :dated %></td>
<td><%= f.text_field :account_name %></td>
<%= f.fields_for :journal_entries do |journal_entry| %>
<td><%= journal_entry.text_field :credit %></td>
<td><%= journal_entry.text_field :notes %></td>
<% end %>
</tr>
</fieldset>
Though you need to initialise the journal entries every time a new record is added dynamically. I can't help you with this right now as I'm not on my PC.

Try this: http://railscasts.com/episodes/196-nested-model-form-revised
The RailsCasts model relations are similar to your model relations, although you would need to alter the HTML.
RailsCasts Models: Survey > Question > Answer
Your Models: Lease > Journal > JournalEntry

Related

rails multi-level nested forms with cocoon and tables

I've successfully implemented one level of nested form with Cocoon and tables. However, I'm having a difficult time wrapping my mind on how to do another nested level. My issue is how to do this with a table. And maybe a table isn't the write way to go at all. Thank you for helping a newbie.
Here are my models:
class Profession < ApplicationRecord
has_many :procedure_categories, dependent: :destroy
accepts_nested_attributes_for :procedure_categories, allow_destroy: true
end
And:
class ProcedureCategory < ApplicationRecord
belongs_to :profession
has_many :procedures
accepts_nested_attributes_for :procedures, allow_destroy: true
end
And:
class Procedure < ApplicationRecord
belongs_to :procedure_category
end
Here is my top level form code:
<%= form_for(#profession) do |f| %>
<%= render 'shared/profession_error_messages' %>
<%= f.label :profession %>
<%= f.text_field :profession, class: 'form-control' %>
<%= f.label :description %>
<%= f.text_field :description, class: 'form-control' %>
<%= f.label :active, class: "checkbox inline" do %>
<%= f.check_box :active %>
<span>Active profession?</span>
<% end %>
<table class='table'>
<thead>
<tr>
<th>Category</th>
<th>Description</th>
<th>Display Order</th>
<th>Selection Type</th>
<th>Delete</th>
<th>Edit</th>
</tr>
</thead>
<tbody class="categories">
<%= f.fields_for :procedure_categories do |procedure_category| %>
<%= render 'procedure_category_fields', f: procedure_category %>
<% end %>
</tbody>
</table>
<%= link_to_add_association 'Add Category', f, :procedure_categories,
data: { association_insertion_node: '.categories', association_insertion_method: :append } %>
<br><br>
<%= f.submit "Save", class: "btn btn-primary" %>
<% end %>
And the next partial one level down:
<tr class="nested-fields">
<td><%= f.text_field :category, class: 'form-control' %></td>
<td><%= f.text_field :description, class: 'form-control' %></td>
<td><%= f.text_field :display_order, class: 'form-control' %></td>
<% cs = options_for_select(controls, f.object.selection_type) %>
<td><%= f.select :selection_type, cs, class: 'form-control' %></td>
<td><%= link_to_remove_association "Remove Category", f %></td>
<% if f.object != nil %>
<td><%= link_to "Category", edit_procedure_category_path(#profession,f.object) %><td></td>
<% end %>
</tr>
So, I'm struggling with how to implement the final level of nesting (procedures).
Thank you for listening.
Use has_many :through
Here are my models:
class Profession < ApplicationRecord
has_many :procedures, through: categories
has_many :categories, dependent: :destroy
accepts_nested_attributes_for :categories, allow_destroy: true
end
Rename this procedure_category model in category
class Category < ApplicationRecord
belongs_to :profession
has_many :procedures
accepts_nested_attributes_for :procedures, allow_destroy: true
end
And:
class Procedure < ApplicationRecord
belongs_to :category
end
If I miss something you can check the instruction from the rails guide
The controller professions#new action should create the following variables, so that they are available in the view:
def new
#profession = Profession.new
#categories = #profession.categories.build
#procedures = #categories.procedures.build
end
The view uses that variable so store the user inputs and make a post request at /profession/ with those inputs stored in the parameters hash
<%= form_for(#profession) do |f| %>
<%= f.fields_for :categories do |category| %>
<%= category.fields_for :procedures do |precedure| %>
<% end %>
<% end %>
<% end %>
The fields_for yields a form builder. The parameters' name will be what accepts_nested_attributes_for expects. For example, when creating a user with 2 addresses, the submitted parameters would look like:
This is how your parameters should look like:
{
'profession' => {
'name' => 'John Doe',
'categories_attributes' => {
'0' => {
'kind' => 'Home',
'street' => '221b Baker Street',
'procedures_attributes' => {
'0' => {},
'1' => {}
}
},
'1' => {
'kind' => 'Office',
'street' => '31 Spooner Street'
}
}
}
}
so make sure your form is pointing at post url /professions/ and that the routing will trigger the professions#create action
def create
binding.pry
end
for any problems set a binding pry and check in your console how your parameters are showing up.
Read more at
http://guides.rubyonrails.org/form_helpers.html#building-complex-forms

Why is fields_for not iterating over the passed ActiveRecord::Relation?

I'm trying to setup a section of the form where a user can select zero or more doctors, but is required to provide a token from each to demonstrate that they spoke to the doctor. Anyway, I have the relationship working on the models, and can set & get lists of doctors and patients. But fields_for doesn't seem to understand that. There's probably some magic somewhere that I've missed, and if anyone can point it out that'd be great.
in the controller:
def edit
#doctors = User.doctor
super
end
in the model:
class User < ActiveRecord::Base
devise :registerable
has_secure_token
enum role: [:doctor, :admin, :customer, :distributor]
enum salutation: [:mr, :mrs, :ms, :miss, :dr]
has_and_belongs_to_many :doctors, -> { doctor }, {class_name: "User", join_table: :doctors_patients, foreign_key: :patient_id, association_foreign_key: :doctor_id}
has_and_belongs_to_many :patients, {class_name: "User", join_table: :doctors_patients, foreign_key: :doctor_id, association_foreign_key: :patient_id}
end
in the view:
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put,class:"form-horizontal" }) do |f|
...
<%= f.fields_for :doctors, #doctors do |d| %>
<tr>
<td><%= d.check_box :id,{checked: resource.doctors.include? d.object.id} %></td>
<td><%= "#{d.object.salutation.titleize}. #{d.object.last_name}" %></td>
<td><%= "#{d.object.clinic}" %></td>
<td><%= d.text_field :token %></td>
<td><%= link_to 'More','#',class:"btn btn-primary",data:{toggle:"modal",target:"#doctor#{d.object.id}Modal"} %></td>
</tr>
<% end %>
<% end %>
I'm currently getting an error: undefined method 'id' for #<User::ActiveRecord_Relation:0x007faa9392c9b8> because the entire relation is being used in fields_for not one instance at a time.
I'm just trying to implement this:
Or a collection to be used:
<%= form_for #person do |person_form| %>
...
<%= person_form.fields_for :projects, #active_projects do |project_fields| %>
Name: <%= project_fields.text_field :name %>
<% end %>
...
<% end %>
from: http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for
Turns out you need accepts_nested_attributes_for :doctors in your model if you want to get the iteration from fields_for.
replace line <%= f.fields_for :doctors, #doctors do |d| %> with <%= f.fields_for :doctor do |d| %>.

Ruby on Rails: Display relationship between 2 models

I have an authors page that displays all the authors in the database.
<h1>Listing authors</h1>
<table>
<tr>
<th>Name</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #authors.each do |author| %>
<tr>
<td><%= author.name %></td>
<td><%= link_to 'Show', author %></td>
<td><%= link_to 'Edit', edit_author_path(author) %></td>
<td><%= link_to 'Destroy', author, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
<%= link_to 'New Author', new_author_path %>
And for each author, you click show, to bring up their own page.
<p>
<b>Name:</b>
<%= #author.name %>
</p>
<%= link_to 'Edit', edit_author_path(#author) %> |
<%= link_to 'Back', authors_path %>
Now I have the same set up for books, where the user can enter new books, show and edit books in the database.
I then set up a model called authorbooks that holds a relation ship between authors and books using has_many, and belongs_to in the models for author.rb, book.rb and authorbook.rb.
I am wanting the show page of the author to display every book that they are related to.
How would I go about this? I am new to rails and still learning so please remember when answering. Thanks in advance.
EDIT model code for each model:
author.rb
class Author < ActiveRecord::Base
attr_accessible :name
validates :name, :presence => true
has_many :authorbooks
has_many :books, :through => :authorbooks
end
book.rb
class Book < ActiveRecord::Base
attr_accessible :name
validates :name, :presence => true
has_many :authorbooks
has_many :authors, :through => :authorbooks
end
authorbook.rb
class Authorbook < ActiveRecord::Base
attr_accessible :author_id, :book_id
belongs_to :book
belongs_to :author
end
It would have been interesting to see the model code as well. I assume you have something like:
class Author
has_many :author_books
has_many :books, :through => :author_books # this line might be missing,
# read in the api documentation about it.
class AuthorBooks
belongs_to :author
belongs_to :book
Now you can do something like:
<h3>Related books</h3>
<ul>
<% #author.books.each do |book| %>
<li><%= book.name %> <%= link_to "Details", book_path(book) %></li>
<% end %>
</ul>
Without the :through line you could have done something like:
#author.author_books.each do |ab|
... ab.book.name ...
Note 1: you get N+1 load problems with the second example. See the eager loading chapter in A::R guide for more information about that.
Note 2: Checkout HAML; much nicer than ERB

How to add data from multiple models to same view (Rails 3.2)

Im trying to figure out how to have data from multiple models show up on the same calendar in my view. Right now it's showing birthdays, but i would love to add anniversaries & holidays as well (which are currently just lists in view).. *stripped unnecessary formatting for clarity
https://github.com/watu/table_builder
users/show.html.erb
<% if #user.friends.any? %>
<h3>Upcoming Birthdays</h3>
<div id="calendar">
<h2 id="month">
<%= link_to "<", :month => (#date.beginning_of_month-1).strftime("%Y-%m") %>
<%=h #date.strftime("%B %Y") %>
<%= link_to ">", :month => (#date.end_of_month+1).strftime("%Y-%m") %>
</h2>
<%= calendar_for #friends, :year => #date.year, :month => #date.month do |calendar| %>
<%= calendar.head('mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun') %>
<%= calendar.day(:day_method => :dob) do |date, friends| %>
<%= date.day %>
<ul>
<% friends.each do |friend| %>
<li> <%= link_to h(friend.name), friends %><%= "\'s birthday"%></li>
<% end %>
</ul>
<% end %>
<% end %>
</div>
<% end %>
<% if #user.holidays.any? %>
<h3>Upcoming Holidays</h3>
<% #user.holidays.each do |hld| %>
<td><%= hld.name %></td>
<td><%= hld.date %></td>
<% end %>
</tbody>
</table>
Models
class User < ActiveRecord::Base
has_many :friends
has_many :user_holidays
has_many :holidays, :through => :user_holidays
has_many :anniversaries
class Holiday < ActiveRecord::Base
attr_accessible :name, :date
has_many :user_holidays
has_many :users, :through => :user_holidays
end
class UserHoliday < ActiveRecord::Base
attr_accessible :holiday_id, :user_id
belongs_to :user
belongs_to :holiday
end
class Anniversary < ActiveRecord::Base
belongs_to :user
attr_accessible :anniversary_date, :spouse_name, :anniversaries, :interest_ids
has_many :person_interests, :as => :person
has_many :interests, :through => :person_interests
end
There's nothing about a view that keeps it from using data from other models. You just have to make sure that the controller action passes it to the view somehow. You're currently passing one #date object and one #user object; if you want other objects you should set those as well. I advise you to make those objects accessible via the #user object, which is to say that you should create instance methods for a User so that you can access them in a view
class User
def birthdays
...
end
def anniversaries
...
end
def holidays
...
end
end
And then in your view, you can simply call #user.birthdays etc, etc.

rails 3.1 has_many :through extra field in join model

i'm trying to solve has_many :through association with additional text_field in join model.None of the existing answers do the trick for me.
I have three models:
class Partner
has_many :prices
has_many :services, :through => :prices
accept_nested_attributes_for :prices
end
class Service
has_many :prices
has_many :partners, :through => :prices
end
class Price
belongs_to :service
belongs_to :partner
end
Prices table looks like this:
id
partner_id
service_id
price
I need to enter price for every selected service.
View looks like this:
<%= form_for(#partner, :url => save_services_path(#partner.id), :remote => true) do |f| %>
<table>
<% #services.in_groups_of(4, false) do |services| %>
<tr>
<% services.each do |service| %>
<td>
<%= check_box_tag "partner[service_ids][]", service.id, #partner.services.include?(service) %>
<%= service.name %>
<%= f.fields_for :prices do |p| %>
<%= p.text_field :price %>
<% end %>
</td>
<% end %>
</tr>
<% end %>
</table>
<% end %>
Checkbox works fine, but i'm unable to update price for service.
I believe the problem is in nested form syntax...i've tried many different combinations but non worked.
Thanks in advance!
UPDATE:
controller action:
def save_services
#partner = Partner.find(params[:id])
#partner.update_attributes(params[:partner]
end
log:
Started PUT "/partners/save_services/337" for
Processing by PartnersController#save_services as JS
Parameters: {"utf8"=>"รข", "authenticity_token"=>"xxx", "partner"=>{"service_ids"=>["20", "24"]}, "commit"=>"Save", "id"=>"337"}
Why do you have this?
:url => save_services_path(#partner.id)
in your form_for? you're creating form with #partner, but saving with services.. try
<%= form_for(#partner, :url => {:action => 'update'}, :remote => true) do |f| %>
or post your params from log

Resources