Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

adding solution for deeply nested models

  • Loading branch information...
commit b2294600143509423bebfc366b5d373f991f78af 1 parent c0557d5
@ryanb ryanb authored
View
10 app/helpers/application_helper.rb
@@ -1,15 +1,17 @@
# Methods added to this helper will be available to all templates in the application.
module ApplicationHelper
- def add_task_link(name, f)
- fields = new_child_fields(f, :tasks)
- link_to_function(name, "insert_fields('tasks', '#{escape_javascript(fields)}')")
+ def add_child_link(name, f, method)
+ fields = new_child_fields(f, method)
+ js = "insert_fields(this, \"#{method}\", \"#{escape_javascript(fields)}\")"
+ "<a href=\"#\" onclick=\"#{h(js)}\">#{name}</a>"
+ #link_to_function(name, "insert_fields(\"#{method}\", \"#{escape_javascript(h(fields))}\");")
end
def new_child_fields(form_builder, method, options = {})
options[:object] ||= form_builder.object.class.reflect_on_association(method).klass.new
options[:partial] ||= method.to_s.singularize
options[:form_builder_local] ||= :f
- form_builder.fields_for(method, options[:object], :child_index => 'NEW_RECORD') do |f|
+ form_builder.fields_for(method, options[:object], :child_index => "new_#{method}") do |f|
render(:partial => options[:partial], :locals => { options[:form_builder_local] => f })
end
end
View
6 app/models/assignment.rb
@@ -0,0 +1,6 @@
+class Assignment < ActiveRecord::Base
+ belongs_to :task
+ has_many :steps
+ validates_presence_of :owner
+ accepts_nested_attributes_for :steps, :reject_if => lambda { |a| a.values.all?(&:blank?) }, :allow_destroy => true
+end
View
3  app/models/step.rb
@@ -0,0 +1,3 @@
+class Step < ActiveRecord::Base
+ belongs_to :assignment
+end
View
2  app/models/task.rb
@@ -1,4 +1,6 @@
class Task < ActiveRecord::Base
belongs_to :project
+ has_many :assignments
validates_presence_of :name
+ accepts_nested_attributes_for :assignments, :reject_if => lambda { |a| a.values.all?(&:blank?) }, :allow_destroy => true
end
View
12 app/views/projects/_assignment.html.erb
@@ -0,0 +1,12 @@
+<div class="field">
+ <%= f.label :owner %>
+ <%= f.text_field :owner %>
+ <%= f.check_box :_delete %>
+ <%= f.label :_delete, "(remove)" %>
+ <div class="children_fields">
+ <% f.fields_for :steps do |step_form| %>
+ <%= render :partial => 'step', :locals => { :f => step_form } %>
+ <% end %>
+ <p><%= add_child_link "New Step", f, :steps %></p>
+ </div>
+</div>
View
4 app/views/projects/_form.html.erb
@@ -6,11 +6,9 @@
</p>
<h3>Tasks</h3>
- <div id="tasks">
<% f.fields_for :tasks do |task_form| %>
<%= render :partial => 'task', :locals => { :f => task_form } %>
<% end %>
- </div>
- <p><%= add_task_link "New Task", f %></p>
+ <p><%= add_child_link "New Task", f, :tasks %></p>
<p><%= f.submit "Submit" %></p>
<% end %>
View
6 app/views/projects/_step.html.erb
@@ -0,0 +1,6 @@
+<div class="field">
+ <%= f.label :name, "Step" %>
+ <%= f.text_field :name %>
+ <%= f.check_box :_delete %>
+ <%= f.label :_delete, "(remove)" %>
+</div>
View
6 app/views/projects/_task.html.erb
@@ -3,4 +3,10 @@
<%= f.text_field :name %>
<%= f.check_box :_delete %>
<%= f.label :_delete, "(remove)" %>
+ <div class="children_fields">
+ <% f.fields_for :assignments do |assignment_form| %>
+ <%= render :partial => 'assignment', :locals => { :f => assignment_form } %>
+ <% end %>
+ <p><%= add_child_link "New Assignment", f, :assignments %></p>
+ </div>
</div>
View
2  app/views/projects/index.html.erb
@@ -1,5 +1,5 @@
<% title "Projects" %>
-
+<%= link_to_function "alert", "alert(\"#{escape_javascript(escape_javascript(escape_javascript("foo 'blah' \"test\" \\ \n bar!")))}\");" %>
<table>
<tr>
<th>Name</th>
View
18 app/views/projects/show.html.erb
@@ -9,7 +9,23 @@
<ul>
<% for task in @project.tasks %>
- <li><%=h task.name %></li>
+ <li>
+ <%=h task.name %>
+ <ul>
+ <% for assignment in task.assignments %>
+ <li>
+ <%=h assignment.owner %>
+ <ul>
+ <% for step in assignment.steps %>
+ <li>
+ <%=h step.name %>
+ </li>
+ <% end %>
+ </ul>
+ </li>
+ <% end %>
+ </ul>
+ </li>
<% end %>
</ul>
View
14 db/migrate/20090804011711_create_assignments.rb
@@ -0,0 +1,14 @@
+class CreateAssignments < ActiveRecord::Migration
+ def self.up
+ create_table :assignments do |t|
+ t.integer :task_id
+ t.string :owner
+
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :assignments
+ end
+end
View
14 db/migrate/20090804011903_create_steps.rb
@@ -0,0 +1,14 @@
+class CreateSteps < ActiveRecord::Migration
+ def self.up
+ create_table :steps do |t|
+ t.integer :assignment_id
+ t.string :name
+
+ t.timestamps
+ end
+ end
+
+ def self.down
+ drop_table :steps
+ end
+end
View
16 db/schema.rb
@@ -9,7 +9,14 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20080718205908) do
+ActiveRecord::Schema.define(:version => 20090804011903) do
+
+ create_table "assignments", :force => true do |t|
+ t.integer "task_id"
+ t.string "owner"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
create_table "projects", :force => true do |t|
t.string "name"
@@ -17,6 +24,13 @@
t.datetime "updated_at"
end
+ create_table "steps", :force => true do |t|
+ t.integer "assignment_id"
+ t.string "name"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
create_table "tasks", :force => true do |t|
t.integer "project_id"
t.string "name"
View
10 public/javascripts/application.js
@@ -1,8 +1,12 @@
// Place your application-specific JavaScript functions and classes here
// This file is automatically included by javascript_include_tag :defaults
-function insert_fields(element_id, content) {
+function insert_fields(link, method, content) {
var new_id = new Date().getTime();
- $(element_id).insert({
- bottom: content.replace(/NEW_RECORD/g, new_id)
+ var regexp = new RegExp("new_" + method, "g")
+ $(link).up().insert({
+ before: content.replace(regexp, new_id)
});
+ // $(element_id).insert({
+ // bottom: content.replace(/NEW_RECORD/g, new_id)
+ // });
}
View
4 public/stylesheets/application.css
@@ -87,3 +87,7 @@ body {
.field {
margin: 8px 0;
}
+
+.children_fields {
+ margin-left: 40px;
+}
View
9 test/fixtures/assignments.yml
@@ -0,0 +1,9 @@
+# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
+
+one:
+ task_id: 1
+ owner: MyString
+
+two:
+ task_id: 1
+ owner: MyString
View
9 test/fixtures/steps.yml
@@ -0,0 +1,9 @@
+# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
+
+one:
+ assignment_id: 1
+ name: MyString
+
+two:
+ assignment_id: 1
+ name: MyString
View
8 test/unit/assignment_test.rb
@@ -0,0 +1,8 @@
+require 'test_helper'
+
+class AssignmentTest < ActiveSupport::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
View
8 test/unit/step_test.rb
@@ -0,0 +1,8 @@
+require 'test_helper'
+
+class StepTest < ActiveSupport::TestCase
+ # Replace this with your real tests.
+ test "the truth" do
+ assert true
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.