Skip to content
This repository
Browse code

Convert to Rails 3 idioms.

  • Loading branch information...
commit 36a4b9b3231717281aa2eb4faa40b15db648545f 1 parent 0d06d81
Andy Stewart authored February 08, 2011

Showing 62 changed files with 9,989 additions and 282 deletions. Show diff stats Hide diff stats

  1. 63  Gemfile.lock
  2. 2  Rakefile
  3. 13  lib/paper_trail.rb
  4. 2  lib/paper_trail/controller.rb
  5. 5  lib/paper_trail/has_paper_trail.rb
  6. 41  paper_trail.gemspec
  7. 7  test/dummy/Rakefile
  8. 16  test/dummy/app/controllers/application_controller.rb
  9. 5  test/dummy/app/controllers/test_controller.rb
  10. 18  test/dummy/app/controllers/widgets_controller.rb
  11. 2  test/dummy/app/helpers/application_helper.rb
  12. 11  test/dummy/app/models/article.rb
  13. 5  test/dummy/app/models/authorship.rb
  14. 5  test/dummy/app/models/book.rb
  15. 3  test/dummy/app/models/fluxor.rb
  16. 2  test/dummy/app/models/foo_widget.rb
  17. 5  test/dummy/app/models/person.rb
  18. 12  test/dummy/app/models/song.rb
  19. 5  test/dummy/app/models/widget.rb
  20. 4  test/dummy/app/models/wotsit.rb
  21. 14  test/dummy/app/views/layouts/application.html.erb
  22. 4  test/dummy/config.ru
  23. 45  test/dummy/config/application.rb
  24. 10  test/dummy/config/boot.rb
  25. 22  test/dummy/config/database.yml
  26. 5  test/dummy/config/environment.rb
  27. 26  test/dummy/config/environments/development.rb
  28. 49  test/dummy/config/environments/production.rb
  29. 35  test/dummy/config/environments/test.rb
  30. 7  test/dummy/config/initializers/backtrace_silencers.rb
  31. 10  test/dummy/config/initializers/inflections.rb
  32. 5  test/dummy/config/initializers/mime_types.rb
  33. 7  test/dummy/config/initializers/secret_token.rb
  34. 8  test/dummy/config/initializers/session_store.rb
  35. 5  test/dummy/config/locales/en.yml
  36. 3  test/dummy/config/routes.rb
  37. BIN  test/dummy/db/development.sqlite3
  38. 84  test/dummy/db/migrate/20110208155312_set_up_test_tables.rb
  39. 82  test/dummy/db/schema.rb
  40. BIN  test/dummy/db/test.sqlite3
  41. 26  test/dummy/public/404.html
  42. 26  test/dummy/public/422.html
  43. 26  test/dummy/public/500.html
  44. 0  test/dummy/public/favicon.ico
  45. 2  test/dummy/public/javascripts/application.js
  46. 965  test/dummy/public/javascripts/controls.js
  47. 974  test/dummy/public/javascripts/dragdrop.js
  48. 1,123  test/dummy/public/javascripts/effects.js
  49. 6,001  test/dummy/public/javascripts/prototype.js
  50. 175  test/dummy/public/javascripts/rails.js
  51. 0  test/dummy/public/stylesheets/.gitkeep
  52. 6  test/dummy/script/rails
  53. 51  test/{paper_trail_controller_test.rb → functional/controller_test.rb}
  54. 8  test/{thread_safe_test.rb → functional/thread_safety_test.rb}
  55. 7  test/integration/navigation_test.rb
  56. 15  test/paper_trail_schema_test.rb
  57. 7  test/paper_trail_test.rb
  58. 71  test/schema.rb
  59. 3  test/schema_change.rb
  60. 5  test/support/integration_case.rb
  61. 60  test/test_helper.rb
  62. 73  test/{paper_trail_model_test.rb → unit/model_test.rb}
63  Gemfile.lock
@@ -2,13 +2,15 @@ PATH
2 2
   remote: .
3 3
   specs:
4 4
     paper_trail (2.0.0)
5  
-      actionpack (~> 3)
6  
-      activerecord (~> 3)
  5
+      rails (~> 3)
7 6
 
8 7
 GEM
9 8
   remote: http://rubygems.org/
10 9
   specs:
11 10
     abstract (1.0.0)
  11
+    actionmailer (3.0.3)
  12
+      actionpack (= 3.0.3)
  13
+      mail (~> 2.2.9)
12 14
     actionpack (3.0.3)
13 15
       activemodel (= 3.0.3)
14 16
       activesupport (= 3.0.3)
@@ -28,31 +30,78 @@ GEM
28 30
       activesupport (= 3.0.3)
29 31
       arel (~> 2.0.2)
30 32
       tzinfo (~> 0.3.23)
  33
+    activeresource (3.0.3)
  34
+      activemodel (= 3.0.3)
  35
+      activesupport (= 3.0.3)
31 36
     activesupport (3.0.3)
32 37
     arel (2.0.7)
33 38
     builder (2.1.2)
  39
+    capybara (0.4.1.1)
  40
+      celerity (>= 0.7.9)
  41
+      culerity (>= 0.2.4)
  42
+      mime-types (>= 1.16)
  43
+      nokogiri (>= 1.3.3)
  44
+      rack (>= 1.0.0)
  45
+      rack-test (>= 0.5.4)
  46
+      selenium-webdriver (>= 0.0.27)
  47
+      xpath (~> 0.1.3)
  48
+    celerity (0.8.7)
  49
+    childprocess (0.1.6)
  50
+      ffi (~> 0.6.3)
  51
+    culerity (0.2.15)
34 52
     erubis (2.6.6)
35 53
       abstract (>= 1.0.0)
  54
+    ffi (0.6.3)
  55
+      rake (>= 0.8.7)
36 56
     i18n (0.5.0)
  57
+    json_pure (1.5.1)
  58
+    mail (2.2.15)
  59
+      activesupport (>= 2.3.6)
  60
+      i18n (>= 0.4.0)
  61
+      mime-types (~> 1.16)
  62
+      treetop (~> 1.4.8)
  63
+    mime-types (1.16)
  64
+    nokogiri (1.4.4)
  65
+    polyglot (0.3.1)
37 66
     rack (1.2.1)
38 67
     rack-mount (0.6.13)
39 68
       rack (>= 1.0.0)
40 69
     rack-test (0.5.7)
41 70
       rack (>= 1.0)
  71
+    rails (3.0.3)
  72
+      actionmailer (= 3.0.3)
  73
+      actionpack (= 3.0.3)
  74
+      activerecord (= 3.0.3)
  75
+      activeresource (= 3.0.3)
  76
+      activesupport (= 3.0.3)
  77
+      bundler (~> 1.0)
  78
+      railties (= 3.0.3)
  79
+    railties (3.0.3)
  80
+      actionpack (= 3.0.3)
  81
+      activesupport (= 3.0.3)
  82
+      rake (>= 0.8.7)
  83
+      thor (~> 0.14.4)
42 84
     rake (0.8.7)
  85
+    rubyzip (0.9.4)
  86
+    selenium-webdriver (0.1.2)
  87
+      childprocess (~> 0.1.5)
  88
+      ffi (~> 0.6.3)
  89
+      json_pure
  90
+      rubyzip
43 91
     shoulda (2.10.3)
44 92
     sqlite3-ruby (1.3.1)
  93
+    thor (0.14.6)
  94
+    treetop (1.4.9)
  95
+      polyglot (>= 0.3.1)
45 96
     tzinfo (0.3.24)
  97
+    xpath (0.1.3)
  98
+      nokogiri (~> 1.3)
46 99
 
47 100
 PLATFORMS
48 101
   ruby
49 102
 
50 103
 DEPENDENCIES
51  
-  actionpack (~> 3)
52  
-  activerecord (~> 3)
53  
-  activesupport (~> 3)
54  
-  bundler (~> 1.0)
  104
+  capybara (>= 0.4.0)
55 105
   paper_trail!
56  
-  rake (= 0.8.7)
57 106
   shoulda (= 2.10.3)
58 107
   sqlite3-ruby (~> 1.2)
2  Rakefile
@@ -8,7 +8,7 @@ Rake::TestTask.new(:test) do |t|
8 8
   t.libs << 'lib'
9 9
   t.libs << 'test'
10 10
   t.pattern = 'test/**/*_test.rb'
11  
-  t.verbose = true
  11
+  t.verbose = false
12 12
 end
13 13
 
14 14
 desc 'Default: run unit tests.'
13  lib/paper_trail.rb
... ...
@@ -1,15 +1,11 @@
1 1
 require 'singleton'
2 2
 require 'yaml'
3 3
 
4  
-require 'action_controller'
5  
-require 'active_record'
6  
-
7 4
 require 'paper_trail/config'
8 5
 require 'paper_trail/controller'
9 6
 require 'paper_trail/has_paper_trail'
10 7
 require 'paper_trail/version'
11 8
 
12  
-
13 9
 # PaperTrail's module methods can be called in both models and controllers.
14 10
 module PaperTrail
15 11
 
@@ -66,3 +62,12 @@ def self.config
66 62
   end
67 63
 
68 64
 end
  65
+
  66
+
  67
+ActiveSupport.on_load(:active_record) do
  68
+  include PaperTrail::Model
  69
+end
  70
+
  71
+ActiveSupport.on_load(:action_controller) do
  72
+  include PaperTrail::Controller
  73
+end
2  lib/paper_trail/controller.rb
@@ -59,5 +59,3 @@ def set_paper_trail_controller_info
59 59
 
60 60
   end
61 61
 end
62  
-
63  
-ActionController::Base.send :include, PaperTrail::Controller
5  lib/paper_trail/has_paper_trail.rb
@@ -64,7 +64,7 @@ def live?
64 64
 
65 65
       # Returns who put the object into its current state.
66 66
       def originator
67  
-        versions.last.try :whodunnit
  67
+        Version.with_item_keys(self.class.name, id).last.try :whodunnit
68 68
       end
69 69
 
70 70
       # Returns the object (not a Version) as it was at the given timestamp.
@@ -112,6 +112,7 @@ def record_destroy
112 112
                                         :object    => object_to_string(item_before_change),
113 113
                                         :whodunnit => PaperTrail.whodunnit)
114 114
         end
  115
+        versions.send :load_target
115 116
       end
116 117
 
117 118
       def merge_metadata(data)
@@ -158,5 +159,3 @@ def switched_on?
158 159
 
159 160
   end
160 161
 end
161  
-
162  
-ActiveRecord::Base.send :include, PaperTrail::Model
41  paper_trail.gemspec
... ...
@@ -1,30 +1,23 @@
1  
-$LOAD_PATH.unshift 'lib'
  1
+$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2 2
 require 'paper_trail/version_number'
3 3
 
4 4
 Gem::Specification.new do |s|
5  
-  s.name             = 'paper_trail'
6  
-  s.version          = PaperTrail::VERSION
7  
-  s.summary          = "Track changes to your models' data.  Good for auditing or versioning."
8  
-  s.description      = s.summary
9  
-  s.homepage         = 'http://github.com/airblade/paper_trail'
10  
-  s.authors          = ['Andy Stewart']
11  
-  s.email            = 'boss@airbladesoftware.com'
12  
-  s.files            = %w[ README.md Rakefile paper_trail.gemspec ]
13  
-  s.files           += %w[ init.rb install.rb ]
14  
-  s.files           += Dir.glob("lib/**/*")
15  
-  s.files           += Dir.glob("generators/**/*")
16  
-  s.require_path     = 'lib'
17  
-  s.test_files       = Dir.glob("test/**/*")
  5
+  s.name          = 'paper_trail'
  6
+  s.version       = PaperTrail::VERSION
  7
+  s.summary       = "Track changes to your models' data.  Good for auditing or versioning."
  8
+  s.description   = s.summary
  9
+  s.homepage      = 'http://github.com/airblade/paper_trail'
  10
+  s.authors       = ['Andy Stewart']
  11
+  s.email         = 'boss@airbladesoftware.com'
18 12
 
19  
-  s.add_development_dependency 'bundler',       '~> 1.0'
20  
-  s.add_development_dependency 'rake',          '0.8.7'  # TODO: why do we need to list rake?
21  
-  s.add_development_dependency 'shoulda',       '2.10.3'
22  
-  s.add_development_dependency 'activesupport', '~> 3'
23  
-  s.add_development_dependency 'sqlite3-ruby',  '~> 1.2'
24  
-  # Repeated here to make bundler happy
25  
-  s.add_development_dependency 'activerecord',  '~> 3'
26  
-  s.add_development_dependency 'actionpack',    '~> 3'
  13
+  s.files         = `git ls-files`.split("\n")
  14
+  s.test_files    = `git ls-files -- {test,spec,features}/*`.split("\n")
  15
+  s.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
  16
+  s.require_paths = ['lib']
27 17
 
28  
-  s.add_dependency 'activerecord',  '~> 3'
29  
-  s.add_dependency 'actionpack',    '~> 3'
  18
+  s.add_dependency 'rails', '~> 3'
  19
+
  20
+  s.add_development_dependency 'shoulda',      '2.10.3'
  21
+  s.add_development_dependency 'sqlite3-ruby', '~> 1.2'
  22
+  s.add_development_dependency 'capybara',     '>= 0.4.0'
30 23
 end
7  test/dummy/Rakefile
... ...
@@ -0,0 +1,7 @@
  1
+# Add your own tasks in files placed in lib/tasks ending in .rake,
  2
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
  3
+
  4
+require File.expand_path('../config/application', __FILE__)
  5
+require 'rake'
  6
+
  7
+Dummy::Application.load_tasks
16  test/dummy/app/controllers/application_controller.rb
... ...
@@ -0,0 +1,16 @@
  1
+class ApplicationController < ActionController::Base
  2
+  protect_from_forgery
  3
+
  4
+  def rescue_action(e)
  5
+    raise e
  6
+  end
  7
+
  8
+  # Returns id of hypothetical current user
  9
+  def current_user
  10
+    153
  11
+  end
  12
+
  13
+  def info_for_paper_trail
  14
+    {:ip => request.remote_ip, :user_agent => request.user_agent}
  15
+  end
  16
+end
5  test/dummy/app/controllers/test_controller.rb
... ...
@@ -0,0 +1,5 @@
  1
+class TestController < ActionController::Base
  2
+  def current_user
  3
+    Thread.current.object_id
  4
+  end
  5
+end
18  test/dummy/app/controllers/widgets_controller.rb
... ...
@@ -0,0 +1,18 @@
  1
+class WidgetsController < ApplicationController
  2
+  def create
  3
+    @widget = Widget.create params[:widget]
  4
+    head :ok
  5
+  end
  6
+
  7
+  def update
  8
+    @widget = Widget.find params[:id]
  9
+    @widget.update_attributes params[:widget]
  10
+    head :ok
  11
+  end
  12
+
  13
+  def destroy
  14
+    @widget = Widget.find params[:id]
  15
+    @widget.destroy
  16
+    head :ok
  17
+  end
  18
+end
2  test/dummy/app/helpers/application_helper.rb
... ...
@@ -0,0 +1,2 @@
  1
+module ApplicationHelper
  2
+end
11  test/dummy/app/models/article.rb
... ...
@@ -0,0 +1,11 @@
  1
+class Article < ActiveRecord::Base
  2
+  has_paper_trail :ignore => [:title],
  3
+                  :meta   => {:answer => 42,
  4
+                              :action => :action_data_provider_method,
  5
+                              :question => Proc.new { "31 + 11 = #{31 + 11}" },
  6
+                              :article_id => Proc.new { |article| article.id } }
  7
+
  8
+  def action_data_provider_method
  9
+    self.object_id.to_s
  10
+  end
  11
+end
5  test/dummy/app/models/authorship.rb
... ...
@@ -0,0 +1,5 @@
  1
+class Authorship < ActiveRecord::Base
  2
+  belongs_to :book
  3
+  belongs_to :person
  4
+  has_paper_trail
  5
+end
5  test/dummy/app/models/book.rb
... ...
@@ -0,0 +1,5 @@
  1
+class Book < ActiveRecord::Base
  2
+  has_many :authorships, :dependent => :destroy
  3
+  has_many :authors, :through => :authorships, :source => :person
  4
+  has_paper_trail
  5
+end
3  test/dummy/app/models/fluxor.rb
... ...
@@ -0,0 +1,3 @@
  1
+class Fluxor < ActiveRecord::Base
  2
+  belongs_to :widget
  3
+end
2  test/dummy/app/models/foo_widget.rb
... ...
@@ -0,0 +1,2 @@
  1
+class FooWidget < Widget
  2
+end
5  test/dummy/app/models/person.rb
... ...
@@ -0,0 +1,5 @@
  1
+class Person < ActiveRecord::Base
  2
+  has_many :authorships, :dependent => :destroy
  3
+  has_many :books, :through => :authorships
  4
+  has_paper_trail
  5
+end
12  test/dummy/app/models/song.rb
... ...
@@ -0,0 +1,12 @@
  1
+# Example from 'Overwriting default accessors' in ActiveRecord::Base.
  2
+class Song < ActiveRecord::Base
  3
+  has_paper_trail
  4
+
  5
+  # Uses an integer of seconds to hold the length of the song
  6
+  def length=(minutes)
  7
+    write_attribute(:length, minutes.to_i * 60)
  8
+  end
  9
+  def length
  10
+    read_attribute(:length) / 60
  11
+  end
  12
+end
5  test/dummy/app/models/widget.rb
... ...
@@ -0,0 +1,5 @@
  1
+class Widget < ActiveRecord::Base
  2
+  has_paper_trail
  3
+  has_one :wotsit
  4
+  has_many :fluxors, :order => :name
  5
+end
4  test/dummy/app/models/wotsit.rb
... ...
@@ -0,0 +1,4 @@
  1
+class Wotsit < ActiveRecord::Base
  2
+  has_paper_trail
  3
+  belongs_to :widget
  4
+end
14  test/dummy/app/views/layouts/application.html.erb
... ...
@@ -0,0 +1,14 @@
  1
+<!DOCTYPE html>
  2
+<html>
  3
+<head>
  4
+  <title>Dummy</title>
  5
+  <%= stylesheet_link_tag :all %>
  6
+  <%= javascript_include_tag :defaults %>
  7
+  <%= csrf_meta_tag %>
  8
+</head>
  9
+<body>
  10
+
  11
+<%= yield %>
  12
+
  13
+</body>
  14
+</html>
4  test/dummy/config.ru
... ...
@@ -0,0 +1,4 @@
  1
+# This file is used by Rack-based servers to start the application.
  2
+
  3
+require ::File.expand_path('../config/environment',  __FILE__)
  4
+run Dummy::Application
45  test/dummy/config/application.rb
... ...
@@ -0,0 +1,45 @@
  1
+require File.expand_path('../boot', __FILE__)
  2
+
  3
+require "active_model/railtie"
  4
+require "active_record/railtie"
  5
+require "action_controller/railtie"
  6
+require "action_view/railtie"
  7
+require "action_mailer/railtie"
  8
+
  9
+Bundler.require
  10
+require 'paper_trail'
  11
+
  12
+module Dummy
  13
+  class Application < Rails::Application
  14
+    # Settings in config/environments/* take precedence over those specified here.
  15
+    # Application configuration should go into files in config/initializers
  16
+    # -- all .rb files in that directory are automatically loaded.
  17
+
  18
+    # Custom directories with classes and modules you want to be autoloadable.
  19
+    # config.autoload_paths += %W(#{config.root}/extras)
  20
+
  21
+    # Only load the plugins named here, in the order given (default is alphabetical).
  22
+    # :all can be used as a placeholder for all plugins not explicitly named.
  23
+    # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
  24
+
  25
+    # Activate observers that should always be running.
  26
+    # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
  27
+
  28
+    # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
  29
+    # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
  30
+    # config.time_zone = 'Central Time (US & Canada)'
  31
+
  32
+    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
  33
+    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
  34
+    # config.i18n.default_locale = :de
  35
+
  36
+    # JavaScript files you want as :defaults (application.js is always included).
  37
+    # config.action_view.javascript_expansions[:defaults] = %w(jquery rails)
  38
+
  39
+    # Configure the default encoding used in templates for Ruby 1.9.
  40
+    config.encoding = "utf-8"
  41
+
  42
+    # Configure sensitive parameters which will be filtered from the log file.
  43
+    config.filter_parameters += [:password]
  44
+  end
  45
+end
10  test/dummy/config/boot.rb
... ...
@@ -0,0 +1,10 @@
  1
+require 'rubygems'
  2
+gemfile = File.expand_path('../../../../Gemfile', __FILE__)
  3
+
  4
+if File.exist?(gemfile)
  5
+  ENV['BUNDLE_GEMFILE'] = gemfile
  6
+  require 'bundler'
  7
+  Bundler.setup
  8
+end
  9
+
  10
+$:.unshift File.expand_path('../../../../lib', __FILE__)
22  test/dummy/config/database.yml
... ...
@@ -0,0 +1,22 @@
  1
+# SQLite version 3.x
  2
+#   gem install sqlite3-ruby (not necessary on OS X Leopard)
  3
+development:
  4
+  adapter: sqlite3
  5
+  database: db/development.sqlite3
  6
+  pool: 5
  7
+  timeout: 5000
  8
+
  9
+# Warning: The database defined as "test" will be erased and
  10
+# re-generated from your development database when you run "rake".
  11
+# Do not set this db to the same as development or production.
  12
+test:
  13
+  adapter: sqlite3
  14
+  database: db/test.sqlite3
  15
+  pool: 5
  16
+  timeout: 5000
  17
+
  18
+production:
  19
+  adapter: sqlite3
  20
+  database: db/production.sqlite3
  21
+  pool: 5
  22
+  timeout: 5000
5  test/dummy/config/environment.rb
... ...
@@ -0,0 +1,5 @@
  1
+# Load the rails application
  2
+require File.expand_path('../application', __FILE__)
  3
+
  4
+# Initialize the rails application
  5
+Dummy::Application.initialize!
26  test/dummy/config/environments/development.rb
... ...
@@ -0,0 +1,26 @@
  1
+Dummy::Application.configure do
  2
+  # Settings specified here will take precedence over those in config/application.rb
  3
+
  4
+  # In the development environment your application's code is reloaded on
  5
+  # every request.  This slows down response time but is perfect for development
  6
+  # since you don't have to restart the webserver when you make code changes.
  7
+  config.cache_classes = false
  8
+
  9
+  # Log error messages when you accidentally call methods on nil.
  10
+  config.whiny_nils = true
  11
+
  12
+  # Show full error reports and disable caching
  13
+  config.consider_all_requests_local       = true
  14
+  config.action_view.debug_rjs             = true
  15
+  config.action_controller.perform_caching = false
  16
+
  17
+  # Don't care if the mailer can't send
  18
+  config.action_mailer.raise_delivery_errors = false
  19
+
  20
+  # Print deprecation notices to the Rails logger
  21
+  config.active_support.deprecation = :log
  22
+
  23
+  # Only use best-standards-support built into browsers
  24
+  config.action_dispatch.best_standards_support = :builtin
  25
+end
  26
+
49  test/dummy/config/environments/production.rb
... ...
@@ -0,0 +1,49 @@
  1
+Dummy::Application.configure do
  2
+  # Settings specified here will take precedence over those in config/application.rb
  3
+
  4
+  # The production environment is meant for finished, "live" apps.
  5
+  # Code is not reloaded between requests
  6
+  config.cache_classes = true
  7
+
  8
+  # Full error reports are disabled and caching is turned on
  9
+  config.consider_all_requests_local       = false
  10
+  config.action_controller.perform_caching = true
  11
+
  12
+  # Specifies the header that your server uses for sending files
  13
+  config.action_dispatch.x_sendfile_header = "X-Sendfile"
  14
+
  15
+  # For nginx:
  16
+  # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect'
  17
+
  18
+  # If you have no front-end server that supports something like X-Sendfile,
  19
+  # just comment this out and Rails will serve the files
  20
+
  21
+  # See everything in the log (default is :info)
  22
+  # config.log_level = :debug
  23
+
  24
+  # Use a different logger for distributed setups
  25
+  # config.logger = SyslogLogger.new
  26
+
  27
+  # Use a different cache store in production
  28
+  # config.cache_store = :mem_cache_store
  29
+
  30
+  # Disable Rails's static asset server
  31
+  # In production, Apache or nginx will already do this
  32
+  config.serve_static_assets = false
  33
+
  34
+  # Enable serving of images, stylesheets, and javascripts from an asset server
  35
+  # config.action_controller.asset_host = "http://assets.example.com"
  36
+
  37
+  # Disable delivery errors, bad email addresses will be ignored
  38
+  # config.action_mailer.raise_delivery_errors = false
  39
+
  40
+  # Enable threaded mode
  41
+  # config.threadsafe!
  42
+
  43
+  # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
  44
+  # the I18n.default_locale when a translation can not be found)
  45
+  config.i18n.fallbacks = true
  46
+
  47
+  # Send deprecation notices to registered listeners
  48
+  config.active_support.deprecation = :notify
  49
+end
35  test/dummy/config/environments/test.rb
... ...
@@ -0,0 +1,35 @@
  1
+Dummy::Application.configure do
  2
+  # Settings specified here will take precedence over those in config/application.rb
  3
+
  4
+  # The test environment is used exclusively to run your application's
  5
+  # test suite.  You never need to work with it otherwise.  Remember that
  6
+  # your test database is "scratch space" for the test suite and is wiped
  7
+  # and recreated between test runs.  Don't rely on the data there!
  8
+  config.cache_classes = true
  9
+
  10
+  # Log error messages when you accidentally call methods on nil.
  11
+  config.whiny_nils = true
  12
+
  13
+  # Show full error reports and disable caching
  14
+  config.consider_all_requests_local       = true
  15
+  config.action_controller.perform_caching = false
  16
+
  17
+  # Raise exceptions instead of rendering exception templates
  18
+  config.action_dispatch.show_exceptions = false
  19
+
  20
+  # Disable request forgery protection in test environment
  21
+  config.action_controller.allow_forgery_protection    = false
  22
+
  23
+  # Tell Action Mailer not to deliver emails to the real world.
  24
+  # The :test delivery method accumulates sent emails in the
  25
+  # ActionMailer::Base.deliveries array.
  26
+  config.action_mailer.delivery_method = :test
  27
+
  28
+  # Use SQL instead of Active Record's schema dumper when creating the test database.
  29
+  # This is necessary if your schema can't be completely dumped by the schema dumper,
  30
+  # like if you have constraints or database-specific column types
  31
+  # config.active_record.schema_format = :sql
  32
+
  33
+  # Print deprecation notices to the stderr
  34
+  config.active_support.deprecation = :stderr
  35
+end
7  test/dummy/config/initializers/backtrace_silencers.rb
... ...
@@ -0,0 +1,7 @@
  1
+# Be sure to restart your server when you modify this file.
  2
+
  3
+# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
  4
+# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
  5
+
  6
+# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
  7
+# Rails.backtrace_cleaner.remove_silencers!
10  test/dummy/config/initializers/inflections.rb
... ...
@@ -0,0 +1,10 @@
  1
+# Be sure to restart your server when you modify this file.
  2
+
  3
+# Add new inflection rules using the following format
  4
+# (all these examples are active by default):
  5
+# ActiveSupport::Inflector.inflections do |inflect|
  6
+#   inflect.plural /^(ox)$/i, '\1en'
  7
+#   inflect.singular /^(ox)en/i, '\1'
  8
+#   inflect.irregular 'person', 'people'
  9
+#   inflect.uncountable %w( fish sheep )
  10
+# end
5  test/dummy/config/initializers/mime_types.rb
... ...
@@ -0,0 +1,5 @@
  1
+# Be sure to restart your server when you modify this file.
  2
+
  3
+# Add new mime types for use in respond_to blocks:
  4
+# Mime::Type.register "text/richtext", :rtf
  5
+# Mime::Type.register_alias "text/html", :iphone
7  test/dummy/config/initializers/secret_token.rb
... ...
@@ -0,0 +1,7 @@
  1
+# Be sure to restart your server when you modify this file.
  2
+
  3
+# Your secret key for verifying the integrity of signed cookies.
  4
+# If you change this key, all old signed cookies will become invalid!
  5
+# Make sure the secret is at least 30 characters and all random,
  6
+# no regular words or you'll be exposed to dictionary attacks.
  7
+Dummy::Application.config.secret_token = '99c0312cf416079a8c7ccc63acb1e9f4f17741398ec8022a2f4fb509c57f55b72486573e9816a026f507efbcd452a9e954d45c93c95d5bacd87e664ad6805d3f'
8  test/dummy/config/initializers/session_store.rb
... ...
@@ -0,0 +1,8 @@
  1
+# Be sure to restart your server when you modify this file.
  2
+
  3
+Dummy::Application.config.session_store :cookie_store, :key => '_dummy_session'
  4
+
  5
+# Use the database for sessions instead of the cookie-based default,
  6
+# which shouldn't be used to store highly confidential information
  7
+# (create the session table with "rails generate session_migration")
  8
+# Dummy::Application.config.session_store :active_record_store
5  test/dummy/config/locales/en.yml
... ...
@@ -0,0 +1,5 @@
  1
+# Sample localization file for English. Add more files in this directory for other locales.
  2
+# See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
  3
+
  4
+en:
  5
+  hello: "Hello world"
3  test/dummy/config/routes.rb
... ...
@@ -0,0 +1,3 @@
  1
+Dummy::Application.routes.draw do
  2
+  resources :widgets
  3
+end
BIN  test/dummy/db/development.sqlite3
Binary file not shown
84  test/dummy/db/migrate/20110208155312_set_up_test_tables.rb
... ...
@@ -0,0 +1,84 @@
  1
+class SetUpTestTables < ActiveRecord::Migration
  2
+  def self.up
  3
+    create_table :widgets, :force => true do |t|
  4
+      t.string    :name
  5
+      t.text      :a_text
  6
+      t.integer   :an_integer
  7
+      t.float     :a_float
  8
+      t.decimal   :a_decimal
  9
+      t.datetime  :a_datetime
  10
+      t.time      :a_time
  11
+      t.date      :a_date
  12
+      t.boolean   :a_boolean
  13
+      t.datetime  :created_at, :updated_at
  14
+      t.string    :sacrificial_column
  15
+      t.string    :type
  16
+    end
  17
+
  18
+    create_table :versions, :force => true do |t|
  19
+      t.string   :item_type, :null => false
  20
+      t.integer  :item_id,   :null => false
  21
+      t.string   :event,     :null => false
  22
+      t.string   :whodunnit
  23
+      t.text     :object
  24
+      t.datetime :created_at
  25
+
  26
+      # Metadata columns.
  27
+      t.integer :answer
  28
+      t.string :action
  29
+      t.string  :question
  30
+      t.integer :article_id
  31
+
  32
+      # Controller info columns.
  33
+      t.string :ip
  34
+      t.string :user_agent
  35
+    end
  36
+    add_index :versions, [:item_type, :item_id]
  37
+
  38
+    create_table :wotsits, :force => true do |t|
  39
+      t.integer :widget_id
  40
+      t.string  :name
  41
+      t.datetime :created_at, :updated_at
  42
+    end
  43
+
  44
+    create_table :fluxors, :force => true do |t|
  45
+      t.integer :widget_id
  46
+      t.string  :name
  47
+    end
  48
+
  49
+    create_table :articles, :force => true do |t|
  50
+      t.string :title
  51
+      t.string :content
  52
+    end
  53
+
  54
+    create_table :books, :force => true do |t|
  55
+      t.string :title
  56
+    end
  57
+
  58
+    create_table :authorships, :force => true do |t|
  59
+      t.integer :book_id
  60
+      t.integer :person_id
  61
+    end
  62
+
  63
+    create_table :people, :force => true do |t|
  64
+      t.string :name
  65
+    end
  66
+
  67
+    create_table :songs, :force => true do |t|
  68
+      t.integer :length
  69
+    end
  70
+  end
  71
+
  72
+  def self.down
  73
+    drop_table :songs
  74
+    drop_table :people
  75
+    drop_table :authorships
  76
+    drop_table :books
  77
+    drop_table :articles
  78
+    drop_table :fluxors
  79
+    drop_table :wotsits
  80
+    remove_index :versions, :column => [:item_type, :item_id]
  81
+    drop_table :versions
  82
+    drop_table :widgets
  83
+  end
  84
+end
82  test/dummy/db/schema.rb
... ...
@@ -0,0 +1,82 @@
  1
+# This file is auto-generated from the current state of the database. Instead
  2
+# of editing this file, please use the migrations feature of Active Record to
  3
+# incrementally modify your database, and then regenerate this schema definition.
  4
+#
  5
+# Note that this schema.rb definition is the authoritative source for your
  6
+# database schema. If you need to create the application database on another
  7
+# system, you should be using db:schema:load, not running all the migrations
  8
+# from scratch. The latter is a flawed and unsustainable approach (the more migrations
  9
+# you'll amass, the slower it'll run and the greater likelihood for issues).
  10
+#
  11
+# It's strongly recommended to check this file into your version control system.
  12
+
  13
+ActiveRecord::Schema.define(:version => 20110208155312) do
  14
+
  15
+  create_table "articles", :force => true do |t|
  16
+    t.string "title"
  17
+    t.string "content"
  18
+  end
  19
+
  20
+  create_table "authorships", :force => true do |t|
  21
+    t.integer "book_id"
  22
+    t.integer "person_id"
  23
+  end
  24
+
  25
+  create_table "books", :force => true do |t|
  26
+    t.string "title"
  27
+  end
  28
+
  29
+  create_table "fluxors", :force => true do |t|
  30
+    t.integer "widget_id"
  31
+    t.string  "name"
  32
+  end
  33
+
  34
+  create_table "people", :force => true do |t|
  35
+    t.string "name"
  36
+  end
  37
+
  38
+  create_table "songs", :force => true do |t|
  39
+    t.integer "length"
  40
+  end
  41
+
  42
+  create_table "versions", :force => true do |t|
  43
+    t.string   "item_type",  :null => false
  44
+    t.integer  "item_id",    :null => false
  45
+    t.string   "event",      :null => false
  46
+    t.string   "whodunnit"
  47
+    t.text     "object"
  48
+    t.datetime "created_at"
  49
+    t.integer  "answer"
  50
+    t.string   "action"
  51
+    t.string   "question"
  52
+    t.integer  "article_id"
  53
+    t.string   "ip"
  54
+    t.string   "user_agent"
  55
+  end
  56
+
  57
+  add_index "versions", ["item_type", "item_id"], :name => "index_versions_on_item_type_and_item_id"
  58
+
  59
+  create_table "widgets", :force => true do |t|
  60
+    t.string   "name"
  61
+    t.text     "a_text"
  62
+    t.integer  "an_integer"
  63
+    t.float    "a_float"
  64
+    t.decimal  "a_decimal"
  65
+    t.datetime "a_datetime"
  66
+    t.time     "a_time"
  67
+    t.date     "a_date"
  68
+    t.boolean  "a_boolean"
  69
+    t.datetime "created_at"
  70
+    t.datetime "updated_at"
  71
+    t.string   "sacrificial_column"
  72
+    t.string   "type"
  73
+  end
  74
+
  75
+  create_table "wotsits", :force => true do |t|
  76
+    t.integer  "widget_id"
  77
+    t.string   "name"
  78
+    t.datetime "created_at"
  79
+    t.datetime "updated_at"
  80
+  end
  81
+
  82
+end
BIN  test/dummy/db/test.sqlite3
Binary file not shown
26  test/dummy/public/404.html
... ...
@@ -0,0 +1,26 @@
  1
+<!DOCTYPE html>
  2
+<html>
  3
+<head>
  4
+  <title>The page you were looking for doesn't exist (404)</title>
  5
+  <style type="text/css">
  6
+    body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
  7
+    div.dialog {
  8
+      width: 25em;
  9
+      padding: 0 4em;
  10
+      margin: 4em auto 0 auto;
  11
+      border: 1px solid #ccc;
  12
+      border-right-color: #999;
  13
+      border-bottom-color: #999;
  14
+    }
  15
+    h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
  16
+  </style>
  17
+</head>
  18
+
  19
+<body>
  20
+  <!-- This file lives in public/404.html -->
  21
+  <div class="dialog">
  22
+    <h1>The page you were looking for doesn't exist.</h1>
  23
+    <p>You may have mistyped the address or the page may have moved.</p>
  24
+  </div>
  25
+</body>
  26
+</html>
26  test/dummy/public/422.html
... ...
@@ -0,0 +1,26 @@
  1
+<!DOCTYPE html>
  2
+<html>
  3
+<head>
  4
+  <title>The change you wanted was rejected (422)</title>
  5
+  <style type="text/css">
  6
+    body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
  7
+    div.dialog {
  8
+      width: 25em;
  9
+      padding: 0 4em;
  10
+      margin: 4em auto 0 auto;
  11
+      border: 1px solid #ccc;
  12
+      border-right-color: #999;
  13
+      border-bottom-color: #999;
  14
+    }
  15
+    h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
  16
+  </style>
  17
+</head>
  18
+
  19
+<body>
  20
+  <!-- This file lives in public/422.html -->
  21
+  <div class="dialog">
  22
+    <h1>The change you wanted was rejected.</h1>
  23
+    <p>Maybe you tried to change something you didn't have access to.</p>
  24
+  </div>
  25
+</body>
  26
+</html>
26  test/dummy/public/500.html
... ...
@@ -0,0 +1,26 @@
  1
+<!DOCTYPE html>
  2
+<html>
  3
+<head>
  4
+  <title>We're sorry, but something went wrong (500)</title>
  5
+  <style type="text/css">
  6
+    body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
  7
+    div.dialog {
  8
+      width: 25em;
  9
+      padding: 0 4em;
  10
+      margin: 4em auto 0 auto;
  11
+      border: 1px solid #ccc;
  12
+      border-right-color: #999;
  13
+      border-bottom-color: #999;
  14
+    }
  15
+    h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
  16
+  </style>
  17
+</head>
  18
+
  19
+<body>
  20
+  <!-- This file lives in public/500.html -->
  21
+  <div class="dialog">
  22
+    <h1>We're sorry, but something went wrong.</h1>
  23
+    <p>We've been notified about this issue and we'll take a look at it shortly.</p>
  24
+  </div>
  25
+</body>
  26
+</html>
0  test/dummy/public/favicon.ico
No changes.
2  test/dummy/public/javascripts/application.js
... ...
@@ -0,0 +1,2 @@
  1
+// Place your application-specific JavaScript functions and classes here
  2
+// This file is automatically included by javascript_include_tag :defaults
965  test/dummy/public/javascripts/controls.js
... ...
@@ -0,0 +1,965 @@
  1
+// script.aculo.us controls.js v1.8.3, Thu Oct 08 11:23:33 +0200 2009
  2
+
  3
+// Copyright (c) 2005-2009 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
  4
+//           (c) 2005-2009 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
  5
+//           (c) 2005-2009 Jon Tirsen (http://www.tirsen.com)
  6
+// Contributors:
  7
+//  Richard Livsey
  8
+//  Rahul Bhargava
  9
+//  Rob Wills
  10
+//
  11
+// script.aculo.us is freely distributable under the terms of an MIT-style license.
  12
+// For details, see the script.aculo.us web site: http://script.aculo.us/
  13
+
  14
+// Autocompleter.Base handles all the autocompletion functionality
  15
+// that's independent of the data source for autocompletion. This
  16
+// includes drawing the autocompletion menu, observing keyboard
  17
+// and mouse events, and similar.
  18
+//
  19
+// Specific autocompleters need to provide, at the very least,
  20
+// a getUpdatedChoices function that will be invoked every time
  21
+// the text inside the monitored textbox changes. This method
  22
+// should get the text for which to provide autocompletion by
  23
+// invoking this.getToken(), NOT by directly accessing
  24
+// this.element.value. This is to allow incremental tokenized
  25
+// autocompletion. Specific auto-completion logic (AJAX, etc)
  26
+// belongs in getUpdatedChoices.
  27
+//
  28
+// Tokenized incremental autocompletion is enabled automatically
  29
+// when an autocompleter is instantiated with the 'tokens' option
  30
+// in the options parameter, e.g.:
  31
+// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
  32
+// will incrementally autocomplete with a comma as the token.
  33
+// Additionally, ',' in the above example can be replaced with
  34
+// a token array, e.g. { tokens: [',', '\n'] } which
  35
+// enables autocompletion on multiple tokens. This is most
  36
+// useful when one of the tokens is \n (a newline), as it
  37
+// allows smart autocompletion after linebreaks.
  38
+
  39
+if(typeof Effect == 'undefined')
  40
+  throw("controls.js requires including script.aculo.us' effects.js library");
  41
+
  42
+var Autocompleter = { };
  43
+Autocompleter.Base = Class.create({
  44
+  baseInitialize: function(element, update, options) {
  45
+    element          = $(element);
  46
+    this.element     = element;
  47
+    this.update      = $(update);
  48
+    this.hasFocus    = false;
  49
+    this.changed     = false;
  50
+    this.active      = false;
  51
+    this.index       = 0;
  52
+    this.entryCount  = 0;
  53
+    this.oldElementValue = this.element.value;
  54
+
  55
+    if(this.setOptions)
  56
+      this.setOptions(options);
  57
+    else
  58
+      this.options = options || { };
  59
+
  60
+    this.options.paramName    = this.options.paramName || this.element.name;
  61
+    this.options.tokens       = this.options.tokens || [];
  62
+    this.options.frequency    = this.options.frequency || 0.4;
  63
+    this.options.minChars     = this.options.minChars || 1;
  64
+    this.options.onShow       = this.options.onShow ||
  65
+      function(element, update){
  66
+        if(!update.style.position || update.style.position=='absolute') {
  67
+          update.style.position = 'absolute';
  68
+          Position.clone(element, update, {
  69
+            setHeight: false,
  70
+            offsetTop: element.offsetHeight
  71
+          });
  72
+        }
  73
+        Effect.Appear(update,{duration:0.15});
  74
+      };
  75
+    this.options.onHide = this.options.onHide ||
  76
+      function(element, update){ new Effect.Fade(update,{duration:0.15}) };
  77
+
  78
+    if(typeof(this.options.tokens) == 'string')
  79
+      this.options.tokens = new Array(this.options.tokens);
  80
+    // Force carriage returns as token delimiters anyway
  81
+    if (!this.options.tokens.include('\n'))
  82
+      this.options.tokens.push('\n');
  83
+
  84
+    this.observer = null;
  85
+
  86
+    this.element.setAttribute('autocomplete','off');
  87
+
  88
+    Element.hide(this.update);
  89
+
  90
+    Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
  91
+    Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
  92
+  },
  93
+
  94
+  show: function() {
  95
+    if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
  96
+    if(!this.iefix &&
  97
+      (Prototype.Browser.IE) &&
  98
+      (Element.getStyle(this.update, 'position')=='absolute')) {
  99
+      new Insertion.After(this.update,
  100
+       '<iframe id="' + this.update.id + '_iefix" '+
  101
+       'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
  102
+       'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
  103
+      this.iefix = $(this.update.id+'_iefix');
  104
+    }
  105
+    if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
  106
+  },
  107
+
  108
+  fixIEOverlapping: function() {
  109
+    Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
  110
+    this.iefix.style.zIndex = 1;
  111
+    this.update.style.zIndex = 2;
  112
+    Element.show(this.iefix);
  113
+  },
  114
+
  115
+  hide: function() {
  116
+    this.stopIndicator();
  117
+    if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
  118
+    if(this.iefix) Element.hide(this.iefix);
  119
+  },
  120
+
  121
+  startIndicator: function() {
  122
+    if(this.options.indicator) Element.show(this.options.indicator);
  123
+  },
  124
+
  125
+  stopIndicator: function() {
  126
+    if(this.options.indicator) Element.hide(this.options.indicator);
  127
+  },
  128
+
  129
+  onKeyPress: function(event) {
  130
+    if(this.active)
  131
+      switch(event.keyCode) {
  132
+       case Event.KEY_TAB:
  133
+       case Event.KEY_RETURN:
  134
+         this.selectEntry();
  135
+         Event.stop(event);
  136
+       case Event.KEY_ESC:
  137
+         this.hide();
  138
+         this.active = false;
  139
+         Event.stop(event);
  140
+         return;
  141
+       case Event.KEY_LEFT:
  142
+       case Event.KEY_RIGHT:
  143
+         return;
  144
+       case Event.KEY_UP:
  145
+         this.markPrevious();
  146
+         this.render();
  147
+         Event.stop(event);
  148
+         return;
  149
+       case Event.KEY_DOWN:
  150
+         this.markNext();
  151
+         this.render();
  152
+         Event.stop(event);
  153
+         return;
  154
+      }
  155
+     else
  156
+       if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
  157
+         (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
  158
+
  159
+    this.changed = true;
  160
+    this.hasFocus = true;
  161
+
  162
+    if(this.observer) clearTimeout(this.observer);
  163
+      this.observer =
  164
+        setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
  165
+  },
  166
+
  167
+  activate: function() {
  168
+    this.changed = false;
  169
+    this.hasFocus = true;
  170
+    this.getUpdatedChoices();
  171
+  },
  172
+
  173
+  onHover: function(event) {
  174
+    var element = Event.findElement(event, 'LI');
  175
+    if(this.index != element.autocompleteIndex)
  176
+    {
  177
+        this.index = element.autocompleteIndex;
  178
+        this.render();
  179
+    }
  180
+    Event.stop(event);
  181
+  },
  182
+
  183
+  onClick: function(event) {
  184
+    var element = Event.findElement(event, 'LI');
  185
+    this.index = element.autocompleteIndex;
  186
+    this.selectEntry();
  187
+    this.hide();
  188
+  },
  189
+
  190
+  onBlur: function(event) {
  191
+    // needed to make click events working
  192
+    setTimeout(this.hide.bind(this), 250);
  193
+    this.hasFocus = false;
  194
+    this.active = false;
  195
+  },
  196
+