Skip to content

Commit

Permalink
adding Rails 3 app based on Railscasts episodes 196 and 197
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanb committed Feb 15, 2011
1 parent df979cc commit 14f98e9
Show file tree
Hide file tree
Showing 70 changed files with 10,200 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
@@ -0,0 +1,4 @@
.bundle
db/*.sqlite3
log/*.log
tmp/
1 change: 1 addition & 0 deletions .rvmrc
@@ -0,0 +1 @@
rvm 1.9.2@complex-form-examples --create
6 changes: 6 additions & 0 deletions Gemfile
@@ -0,0 +1,6 @@
source 'http://rubygems.org'

gem 'rails', '3.0.4'
gem 'sqlite3'
gem 'nifty-generators'
gem "mocha", :group => :test
77 changes: 77 additions & 0 deletions Gemfile.lock
@@ -0,0 +1,77 @@
GEM
remote: http://rubygems.org/
specs:
abstract (1.0.0)
actionmailer (3.0.4)
actionpack (= 3.0.4)
mail (~> 2.2.15)
actionpack (3.0.4)
activemodel (= 3.0.4)
activesupport (= 3.0.4)
builder (~> 2.1.2)
erubis (~> 2.6.6)
i18n (~> 0.4)
rack (~> 1.2.1)
rack-mount (~> 0.6.13)
rack-test (~> 0.5.7)
tzinfo (~> 0.3.23)
activemodel (3.0.4)
activesupport (= 3.0.4)
builder (~> 2.1.2)
i18n (~> 0.4)
activerecord (3.0.4)
activemodel (= 3.0.4)
activesupport (= 3.0.4)
arel (~> 2.0.2)
tzinfo (~> 0.3.23)
activeresource (3.0.4)
activemodel (= 3.0.4)
activesupport (= 3.0.4)
activesupport (3.0.4)
arel (2.0.8)
builder (2.1.2)
erubis (2.6.6)
abstract (>= 1.0.0)
i18n (0.5.0)
mail (2.2.15)
activesupport (>= 2.3.6)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
mime-types (1.16)
mocha (0.9.12)
nifty-generators (0.4.5)
polyglot (0.3.1)
rack (1.2.1)
rack-mount (0.6.13)
rack (>= 1.0.0)
rack-test (0.5.7)
rack (>= 1.0)
rails (3.0.4)
actionmailer (= 3.0.4)
actionpack (= 3.0.4)
activerecord (= 3.0.4)
activeresource (= 3.0.4)
activesupport (= 3.0.4)
bundler (~> 1.0)
railties (= 3.0.4)
railties (3.0.4)
actionpack (= 3.0.4)
activesupport (= 3.0.4)
rake (>= 0.8.7)
thor (~> 0.14.4)
rake (0.8.7)
sqlite3 (1.3.3)
thor (0.14.6)
treetop (1.4.9)
polyglot (>= 0.3.1)
tzinfo (0.3.24)

PLATFORMS
ruby

DEPENDENCIES
mocha
nifty-generators
rails (= 3.0.4)
sqlite3
5 changes: 5 additions & 0 deletions README.md
@@ -0,0 +1,5 @@
# Complex Form Examples

This repository currently contains one Rails 3 example of a complex nested model form which is based off of Railscasts episodes 196 & 197. Expect more variations to come.

If you want to see the Rails 2 examples, check out the "rails2" branch.
7 changes: 7 additions & 0 deletions Rakefile
@@ -0,0 +1,7 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

require File.expand_path('../config/application', __FILE__)
require 'rake'

Surveyor::Application.load_tasks
3 changes: 3 additions & 0 deletions app/controllers/application_controller.rb
@@ -0,0 +1,3 @@
class ApplicationController < ActionController::Base
protect_from_forgery
end
45 changes: 45 additions & 0 deletions app/controllers/surveys_controller.rb
@@ -0,0 +1,45 @@
class SurveysController < ApplicationController
def index
@surveys = Survey.all
end

def show
@survey = Survey.find(params[:id])
end

def new
@survey = Survey.new
3.times do
question = @survey.questions.build
4.times { question.answers.build }
end
end

def create
@survey = Survey.new(params[:survey])
if @survey.save
redirect_to @survey, :notice => "Successfully created survey."
else
render :action => 'new'
end
end

def edit
@survey = Survey.find(params[:id])
end

def update
@survey = Survey.find(params[:id])
if @survey.update_attributes(params[:survey])
redirect_to @survey, :notice => "Successfully updated survey."
else
render :action => 'edit'
end
end

def destroy
@survey = Survey.find(params[:id])
@survey.destroy
redirect_to surveys_url, :notice => "Successfully destroyed survey."
end
end
13 changes: 13 additions & 0 deletions app/helpers/application_helper.rb
@@ -0,0 +1,13 @@
module ApplicationHelper
def link_to_remove_fields(name, f)
f.hidden_field(:_destroy) + link_to_function(name, "remove_fields(this)")
end

def link_to_add_fields(name, f, association)
new_object = f.object.class.reflect_on_association(association).klass.new
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
render(association.to_s.singularize + "_fields", :f => builder)
end
link_to_function(name, "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")")
end
end
23 changes: 23 additions & 0 deletions app/helpers/error_messages_helper.rb
@@ -0,0 +1,23 @@
module ErrorMessagesHelper
# Render error messages for the given objects. The :message and :header_message options are allowed.
def error_messages_for(*objects)
options = objects.extract_options!
options[:header_message] ||= I18n.t(:"activerecord.errors.header", :default => "Invalid Fields")
options[:message] ||= I18n.t(:"activerecord.errors.message", :default => "Correct the following errors and try again.")
messages = objects.compact.map { |o| o.errors.full_messages }.flatten
unless messages.empty?
content_tag(:div, :class => "error_messages") do
list_items = messages.map { |msg| content_tag(:li, msg) }
content_tag(:h2, options[:header_message]) + content_tag(:p, options[:message]) + content_tag(:ul, list_items.join.html_safe)
end
end
end

module FormBuilderAdditions
def error_messages(options = {})
@template.error_messages_for(@object, options)
end
end
end

ActionView::Helpers::FormBuilder.send(:include, ErrorMessagesHelper::FormBuilderAdditions)
22 changes: 22 additions & 0 deletions app/helpers/layout_helper.rb
@@ -0,0 +1,22 @@
# These helper methods can be called in your template to set variables to be used in the layout
# This module should be included in all views globally,
# to do so you may need to add this line to your ApplicationController
# helper :layout
module LayoutHelper
def title(page_title, show_title = true)
content_for(:title) { h(page_title.to_s) }
@show_title = show_title
end

def show_title?
@show_title
end

def stylesheet(*args)
content_for(:head) { stylesheet_link_tag(*args) }
end

def javascript(*args)
content_for(:head) { javascript_include_tag(*args) }
end
end
2 changes: 2 additions & 0 deletions app/helpers/surveys_helper.rb
@@ -0,0 +1,2 @@
module SurveysHelper
end
3 changes: 3 additions & 0 deletions app/models/answer.rb
@@ -0,0 +1,3 @@
class Answer < ActiveRecord::Base
belongs_to :question
end
5 changes: 5 additions & 0 deletions app/models/question.rb
@@ -0,0 +1,5 @@
class Question < ActiveRecord::Base
belongs_to :survey
has_many :answers, :dependent => :destroy
accepts_nested_attributes_for :answers, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end
4 changes: 4 additions & 0 deletions app/models/survey.rb
@@ -0,0 +1,4 @@
class Survey < ActiveRecord::Base
has_many :questions, :dependent => :destroy
accepts_nested_attributes_for :questions, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end
19 changes: 19 additions & 0 deletions app/views/layouts/application.html.erb
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<title><%= content_for?(:title) ? yield(:title) : "Untitled" %></title>
<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag :defaults %>
<%= csrf_meta_tag %>
<%= yield(:head) %>
</head>
<body>
<div id="container">
<% flash.each do |name, msg| %>
<%= content_tag :div, msg, :id => "flash_#{name}" %>
<% end %>
<%= content_tag :h1, yield(:title) if show_title? %>
<%= yield %>
</div>
</body>
</html>
9 changes: 9 additions & 0 deletions app/views/surveys/_answer_fields.html.erb
@@ -0,0 +1,9 @@
<div class="fields">
<p>
<%= f.label :content, "Answer" %>
<%= f.text_field :content %>
<%# f.check_box :_destroy %>
<%# f.label :_destroy, "Remove" %>
<%= link_to_remove_fields "remove", f %>
</p>
</div>
12 changes: 12 additions & 0 deletions app/views/surveys/_form.html.erb
@@ -0,0 +1,12 @@
<%= form_for @survey do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<%= f.fields_for :questions do |builder| %>
<%= render "question_fields", :f => builder %>
<% end %>
<p><%= link_to_add_fields "Add Question", f, :questions %></p>
<p><%= f.submit "Submit" %></p>
<% end %>
13 changes: 13 additions & 0 deletions app/views/surveys/_question_fields.html.erb
@@ -0,0 +1,13 @@
<div class="fields">
<p>
<%= f.label :content, "Question" %><br />
<%= f.text_area :content, :rows => 3 %><br />
<%# f.check_box :_destroy %>
<%# f.label :_destroy, "Remove Question" %>
<%= link_to_remove_fields "remove", f %>
</p>
<%= f.fields_for :answers do |builder| %>
<%= render 'answer_fields', :f => builder %>
<% end %>
<p><%= link_to_add_fields "Add Answer", f, :answers %></p>
</div>
8 changes: 8 additions & 0 deletions app/views/surveys/edit.html.erb
@@ -0,0 +1,8 @@
<% title "Edit Survey" %>
<%= render 'form' %>

<p>
<%= link_to "Show", @survey %> |
<%= link_to "View All", surveys_path %>
</p>
17 changes: 17 additions & 0 deletions app/views/surveys/index.html.erb
@@ -0,0 +1,17 @@
<% title "Surveys" %>

<table>
<tr>
<th>Name</th>
</tr>
<% for survey in @surveys %>
<tr>
<td><%= survey.name %></td>
<td><%= link_to "Show", survey %></td>
<td><%= link_to "Edit", edit_survey_path(survey) %></td>
<td><%= link_to "Destroy", survey, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>

<p><%= link_to "New Survey", new_survey_path %></p>
5 changes: 5 additions & 0 deletions app/views/surveys/new.html.erb
@@ -0,0 +1,5 @@
<% title "New Survey" %>
<%= render 'form' %>

<p><%= link_to "Back to List", surveys_path %></p>
25 changes: 25 additions & 0 deletions app/views/surveys/show.html.erb
@@ -0,0 +1,25 @@
<% title "Survey" %>

<p>
<strong>Name:</strong>
<%= @survey.name %>
</p>

<ol>
<% for question in @survey.questions %>
<li>
<%= question.content %>
<ul>
<% for answer in question.answers %>
<li><%= answer.content %></li>
<% end %>
</ul>
</li>
<% end %>
</ol>

<p>
<%= link_to "Edit", edit_survey_path(@survey) %> |
<%= link_to "Destroy", @survey, :confirm => 'Are you sure?', :method => :delete %> |
<%= link_to "View All", surveys_path %>
</p>
4 changes: 4 additions & 0 deletions config.ru
@@ -0,0 +1,4 @@
# This file is used by Rack-based servers to start the application.

require ::File.expand_path('../config/environment', __FILE__)
run Surveyor::Application

0 comments on commit 14f98e9

Please sign in to comment.