amrita2 1.9.6 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. data/README +112 -0
  2. data/init.rb +6 -0
  3. data/lib/amrita2/gettext.rb +116 -0
  4. data/lib/amrita2/macro.rb +153 -0
  5. data/lib/amrita2/rails_bridge.rb +172 -26
  6. data/lib/amrita2/template.rb +2634 -234
  7. data/lib/amrita2/testsupport.rb +171 -0
  8. data/lib/amrita2/version.rb +3 -3
  9. data/lib/amrita2.rb +1 -0
  10. data/sample/depot/app/controllers/admin_controller.rb +59 -0
  11. data/sample/depot/app/controllers/application.rb +20 -0
  12. data/sample/depot/app/controllers/info_controller.rb +19 -0
  13. data/sample/depot/app/controllers/login_controller.rb +85 -0
  14. data/sample/depot/app/controllers/store_controller.rb +68 -0
  15. data/sample/depot/app/helpers/admin_helper.rb +7 -0
  16. data/sample/depot/app/helpers/application_helper.rb +10 -0
  17. data/sample/depot/app/helpers/ar_form.rb +169 -0
  18. data/sample/depot/app/helpers/form_tag.rb +24 -0
  19. data/sample/depot/app/helpers/info_helper.rb +7 -0
  20. data/sample/depot/app/helpers/standard_form.rb +73 -0
  21. data/sample/depot/app/helpers/store_helper.rb +14 -0
  22. data/sample/depot/app/models/cart.rb +36 -0
  23. data/sample/depot/app/models/cart_item.rb +26 -0
  24. data/sample/depot/app/models/line_item.rb +34 -0
  25. data/sample/depot/app/models/order.rb +57 -0
  26. data/sample/depot/app/models/product.rb +41 -0
  27. data/sample/depot/app/models/user.rb +83 -0
  28. data/sample/depot/config/boot.rb +49 -0
  29. data/sample/depot/config/environment.rb +83 -0
  30. data/sample/depot/config/environments/development.rb +24 -0
  31. data/sample/depot/config/environments/production.rb +24 -0
  32. data/sample/depot/config/environments/test.rb +24 -0
  33. data/sample/depot/config/routes.rb +10 -0
  34. data/sample/depot/db/migrate/001_create_products.rb +18 -0
  35. data/sample/depot/db/migrate/002_add_price.rb +14 -0
  36. data/sample/depot/db/migrate/003_add_test_data.rb +68 -0
  37. data/sample/depot/db/migrate/004_add_sessions.rb +20 -0
  38. data/sample/depot/db/migrate/005_create_orders.rb +21 -0
  39. data/sample/depot/db/migrate/006_create_line_items.rb +27 -0
  40. data/sample/depot/db/migrate/007_create_users.rb +18 -0
  41. data/sample/depot/db/schema.rb +45 -0
  42. data/sample/depot/public/dispatch.rb +15 -0
  43. data/sample/depot/test/functional/admin_controller_test.rb +54 -0
  44. data/sample/depot/test/functional/info_controller_test.rb +23 -0
  45. data/sample/depot/test/functional/login_controller_test.rb +74 -0
  46. data/sample/depot/test/functional/store_controller_test.rb +57 -0
  47. data/sample/depot/test/integration/dsl_user_stories_test.rb +126 -0
  48. data/sample/depot/test/integration/user_stories_test.rb +70 -0
  49. data/sample/depot/test/performance/order_speed_test.rb +58 -0
  50. data/sample/depot/test/test_helper.rb +16 -0
  51. data/sample/depot/test/unit/cart_test.rb +39 -0
  52. data/sample/depot/test/unit/cart_test1.rb +31 -0
  53. data/sample/depot/test/unit/line_item_test.rb +15 -0
  54. data/sample/depot/test/unit/order_test.rb +15 -0
  55. data/sample/depot/test/unit/product_test.rb +98 -0
  56. data/sample/depot/vendor/plugins/amrita2/init.rb +6 -0
  57. data/sample/hello/hello.rb +22 -0
  58. data/sample/login_engine/app/controllers/application.rb +16 -0
  59. data/sample/login_engine/app/controllers/user_controller.rb +265 -0
  60. data/sample/login_engine/app/helpers/application_helper.rb +3 -0
  61. data/sample/login_engine/app/helpers/form_tag.rb +16 -0
  62. data/sample/login_engine/app/helpers/two_columns.rb +24 -0
  63. data/sample/login_engine/app/helpers/two_columns_form.rb +47 -0
  64. data/sample/login_engine/app/helpers/user_helper.rb +88 -0
  65. data/sample/login_engine/app/models/user.rb +7 -0
  66. data/sample/login_engine/app/models/user_notify.rb +75 -0
  67. data/sample/login_engine/config/boot.rb +45 -0
  68. data/sample/login_engine/config/environment.rb +140 -0
  69. data/sample/login_engine/config/environments/development.rb +21 -0
  70. data/sample/login_engine/config/environments/production.rb +18 -0
  71. data/sample/login_engine/config/environments/test.rb +19 -0
  72. data/sample/login_engine/config/routes.rb +23 -0
  73. data/sample/login_engine/db/migrate/001_create_users.rb +25 -0
  74. data/sample/login_engine/db/schema.rb +25 -0
  75. data/sample/login_engine/lib/config.rb +113 -0
  76. data/sample/login_engine/lib/hpricot_test_extension.rb +80 -0
  77. data/sample/login_engine/lib/login_engine/authenticated_system.rb +113 -0
  78. data/sample/login_engine/lib/login_engine/authenticated_user.rb +155 -0
  79. data/sample/login_engine/lib/login_engine.rb +62 -0
  80. data/sample/login_engine/public/dispatch.rb +10 -0
  81. data/sample/login_engine/test/functional/amrita2_test.rb +267 -0
  82. data/sample/login_engine/test/functional/user_controller_test.rb +544 -0
  83. data/sample/login_engine/test/mocks/mail.rb +14 -0
  84. data/sample/login_engine/test/mocks/time.rb +19 -0
  85. data/sample/login_engine/test/test_helper.rb +31 -0
  86. data/sample/login_engine/test/unit/user_test.rb +116 -0
  87. data/sample/login_engine/vendor/plugins/amrita2/init.rb +6 -0
  88. data/specs/attribute.rb +201 -0
  89. data/specs/datatypes.rb +231 -0
  90. data/specs/dictionary.rb +68 -0
  91. data/specs/erb_cdata.rb +187 -0
  92. data/specs/filters.rb +513 -0
  93. data/specs/gettext/erb_gettext.rb +42 -0
  94. data/specs/gettext/gettext_util.rb +65 -0
  95. data/specs/gettext/static_text.rb +103 -0
  96. data/specs/impl/code_generator.rb +87 -0
  97. data/specs/impl/dynamic_element.rb +92 -0
  98. data/specs/impl/hash_delegator.rb +57 -0
  99. data/specs/impl/parse_opt.rb +34 -0
  100. data/specs/impl/preprocess.rb +823 -0
  101. data/specs/impl/testsupport.rb +89 -0
  102. data/specs/inlineruby.rb +429 -0
  103. data/specs/intro.rb +654 -0
  104. data/specs/loop.rb +203 -0
  105. data/specs/macro.rb +532 -0
  106. data/specs/sample.rb +34 -0
  107. data/specs/sanitize.rb +110 -0
  108. data/specs/template.rb +189 -0
  109. data/specs/trace.rb +97 -0
  110. metadata +138 -19
  111. data/lib/amrita2/core.rb +0 -1897
  112. data/lib/amrita2/rd.rb +0 -314
@@ -0,0 +1,75 @@
1
+ class UserNotify < ActionMailer::Base
2
+ def signup(user, password, url=nil)
3
+ setup_email(user)
4
+
5
+ # Email header info
6
+ @subject += "Welcome to #{LoginEngine.config(:app_name)}!"
7
+
8
+ # Email body substitutions
9
+ @body["name"] = "#{user.firstname} #{user.lastname}"
10
+ @body["login"] = user.login
11
+ @body["password"] = password
12
+ @body["url"] = url || LoginEngine.config(:app_url).to_s
13
+ @body["app_name"] = LoginEngine.config(:app_name).to_s
14
+ end
15
+
16
+ def forgot_password(user, url=nil)
17
+ setup_email(user)
18
+
19
+ # Email header info
20
+ @subject += "Forgotten password notification"
21
+
22
+ # Email body substitutions
23
+ @body["name"] = "#{user.firstname} #{user.lastname}"
24
+ @body["login"] = user.login
25
+ @body["url"] = url || LoginEngine.config(:app_url).to_s
26
+ @body["app_name"] = LoginEngine.config(:app_name).to_s
27
+ end
28
+
29
+ def change_password(user, password, url=nil)
30
+ setup_email(user)
31
+
32
+ # Email header info
33
+ @subject += "Changed password notification"
34
+
35
+ # Email body substitutions
36
+ @body["name"] = "#{user.firstname} #{user.lastname}"
37
+ @body["login"] = user.login
38
+ @body["password"] = password
39
+ @body["url"] = url || LoginEngine.config(:app_url).to_s
40
+ @body["app_name"] = LoginEngine.config(:app_name).to_s
41
+ end
42
+
43
+ def pending_delete(user, url=nil)
44
+ setup_email(user)
45
+
46
+ # Email header info
47
+ @subject += "Delete user notification"
48
+
49
+ # Email body substitutions
50
+ @body["name"] = "#{user.firstname} #{user.lastname}"
51
+ @body["url"] = url || LoginEngine.config(:app_url).to_s
52
+ @body["app_name"] = LoginEngine.config(:app_name).to_s
53
+ @body["days"] = LoginEngine.config(:delayed_delete_days).to_s
54
+ end
55
+
56
+ def delete(user, url=nil)
57
+ setup_email(user)
58
+
59
+ # Email header info
60
+ @subject += "Delete user notification"
61
+
62
+ # Email body substitutions
63
+ @body["name"] = "#{user.firstname} #{user.lastname}"
64
+ @body["url"] = url || LoginEngine.config(:app_url).to_s
65
+ @body["app_name"] = LoginEngine.config(:app_name).to_s
66
+ end
67
+
68
+ def setup_email(user)
69
+ @recipients = "#{user.email}"
70
+ @from = LoginEngine.config(:email_from).to_s
71
+ @subject = "[#{LoginEngine.config(:app_name)}] "
72
+ @sent_on = Time.now
73
+ @headers['Content-Type'] = "text/plain; charset=#{LoginEngine.config(:mail_charset)}; format=flowed"
74
+ end
75
+ end
@@ -0,0 +1,45 @@
1
+ # Don't change this file. Configuration is done in config/environment.rb and config/environments/*.rb
2
+
3
+ unless defined?(RAILS_ROOT)
4
+ root_path = File.join(File.dirname(__FILE__), '..')
5
+
6
+ unless RUBY_PLATFORM =~ /(:?mswin|mingw)/
7
+ require 'pathname'
8
+ root_path = Pathname.new(root_path).cleanpath(true).to_s
9
+ end
10
+
11
+ RAILS_ROOT = root_path
12
+ end
13
+
14
+ unless defined?(Rails::Initializer)
15
+ if File.directory?("#{RAILS_ROOT}/vendor/rails")
16
+ require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
17
+ else
18
+ require 'rubygems'
19
+
20
+ environment_without_comments = IO.readlines(File.dirname(__FILE__) + '/environment.rb').reject { |l| l =~ /^#/ }.join
21
+ environment_without_comments =~ /[^#]RAILS_GEM_VERSION = '([\d.]+)'/
22
+ rails_gem_version = $1
23
+
24
+ if version = defined?(RAILS_GEM_VERSION) ? RAILS_GEM_VERSION : rails_gem_version
25
+ # Asking for 1.1.6 will give you 1.1.6.5206, if available -- makes it easier to use beta gems
26
+ rails_gem = Gem.cache.search('rails', "~>#{version}.0").sort_by { |g| g.version.version }.last
27
+
28
+ if rails_gem
29
+ gem "rails", "=#{rails_gem.version.version}"
30
+ require rails_gem.full_gem_path + '/lib/initializer'
31
+ else
32
+ STDERR.puts %(Cannot find gem for Rails ~>#{version}.0:
33
+ Install the missing gem with 'gem install -v=#{version} rails', or
34
+ change environment.rb to define RAILS_GEM_VERSION with your desired version.
35
+ )
36
+ exit 1
37
+ end
38
+ else
39
+ gem "rails"
40
+ require 'initializer'
41
+ end
42
+ end
43
+
44
+ Rails::Initializer.run(:set_load_path)
45
+ end
@@ -0,0 +1,140 @@
1
+
2
+ $KCODE = 'u' # UTF-8�ξ�硣's' = SJIS, 'e' = EUC-JP�ʤ�
3
+ require 'jcode' # String���饹�Υ᥽�åɤʤɤ�$KCODE�˻��ꤷ��
4
+ # ʸ�������ɤ�Ŭ�ڤ�ư���褦���֤������ޤ���
5
+
6
+
7
+ # Be sure to restart your web server when you modify this file.
8
+
9
+ # Uncomment below to force Rails into production mode when
10
+ # you don't control web/app server and can't set it the proper way
11
+ # ENV['RAILS_ENV'] ||= 'production'
12
+
13
+ # Specifies gem version of Rails to use when vendor/rails is not present
14
+ #RAILS_GEM_VERSION = '1.1.6' unless defined? RAILS_GEM_VERSION
15
+
16
+ # Bootstrap the Rails environment, frameworks, and default configuration
17
+ require File.join(File.dirname(__FILE__), 'boot')
18
+
19
+ Rails::Initializer.run do |config|
20
+ # Settings in config/environments/* take precedence over those specified here
21
+
22
+ # Skip frameworks you're not going to use (only works if using vendor/rails)
23
+ # config.frameworks -= [ :action_web_service, :action_mailer ]
24
+
25
+ # Only load the plugins named here, by default all plugins in vendor/plugins are loaded
26
+ # config.plugins = %W( exception_notification ssl_requirement )
27
+
28
+ # Add additional load paths for your own custom dirs
29
+ # config.load_paths += %W( #{RAILS_ROOT}/extras )
30
+
31
+ # Force all environments to use the same logger level
32
+ # (by default production uses :info, the others :debug)
33
+ # config.log_level = :debug
34
+
35
+ # Use the database for sessions instead of the file system
36
+ # (create the session table with 'rake db:sessions:create')
37
+ # config.action_controller.session_store = :active_record_store
38
+
39
+ # Use SQL instead of Active Record's schema dumper when creating the test database.
40
+ # This is necessary if your schema can't be completely dumped by the schema dumper,
41
+ # like if you have constraints or database-specific column types
42
+ # config.active_record.schema_format = :sql
43
+
44
+ # Activate observers that should always be running
45
+ # config.active_record.observers = :cacher, :garbage_collector
46
+
47
+ # Make Active Record use UTC-base instead of local time
48
+ # config.active_record.default_timezone = :utc
49
+
50
+ # See Rails::Configuration for more options
51
+ end
52
+
53
+ # Add new inflection rules using the following format
54
+ # (all these examples are active by default):
55
+ # Inflector.inflections do |inflect|
56
+ # inflect.plural /^(ox)$/i, '\1en'
57
+ # inflect.singular /^(ox)en/i, '\1'
58
+ # inflect.irregular 'person', 'people'
59
+ # inflect.uncountable %w( fish sheep )
60
+ # end
61
+
62
+ # Add new mime types for use in respond_to blocks:
63
+ # Mime::Type.register "text/richtext", :rtf
64
+ # Mime::Type.register "application/x-mobile", :mobile
65
+
66
+ # Include your application configuration below
67
+
68
+ require 'config'
69
+
70
+ module LoginEngine
71
+ include AuthenticatedSystem # re-include the helper module
72
+
73
+ #--
74
+ # Define the configuration values. config sets the value of the
75
+ # constant ONLY if it has not already been set, i.e. by the user in
76
+ # environment.rb
77
+ #++
78
+
79
+ # Source address for user emails
80
+ config :email_from, 'webmaster@your.company'
81
+
82
+ # Destination email for system errors
83
+ config :admin_email, 'webmaster@your.company'
84
+
85
+ # Sent in emails to users
86
+ config :app_url, 'http://localhost:3000/'
87
+
88
+ # Sent in emails to users
89
+ config :app_name, 'TestApp'
90
+
91
+ # Email charset
92
+ config :mail_charset, 'utf-8'
93
+
94
+ # Security token lifetime in hours
95
+ config :security_token_life_hours, 24
96
+
97
+ # Two column form input
98
+ config :two_column_input, true
99
+
100
+ # Add all changeable user fields to this array.
101
+ # They will then be able to be edited from the edit action. You
102
+ # should NOT include the email field in this array.
103
+ config :changeable_fields, [ 'firstname', 'lastname' ]
104
+
105
+ # Set to true to allow delayed deletes (i.e., delete of record
106
+ # doesn't happen immediately after user selects delete account,
107
+ # but rather after some expiration of time to allow this action
108
+ # to be reverted).
109
+ config :delayed_delete, false
110
+
111
+ # Default is one week
112
+ config :delayed_delete_days, 7
113
+
114
+ # the table to store user information in
115
+ if ActiveRecord::Base.pluralize_table_names
116
+ config :user_table, "users"
117
+ else
118
+ config :user_table, "user"
119
+ end
120
+
121
+ # controls whether or not email is used
122
+ config :use_email_notification, true
123
+
124
+ # Controls whether accounts must be confirmed after signing up
125
+ # ONLY if this and use_email_notification are both true
126
+ config :confirm_account, true
127
+
128
+
129
+ config :salt, "your-salt-here"
130
+ end
131
+
132
+
133
+ require 'gettext'
134
+ require 'gettext/rails'
135
+ require 'amrita2/gettext'
136
+ require 'amrita2/macro'
137
+
138
+ # set text domain for get_text
139
+ Amrita2View::Base.text_domain = "login_engine"
140
+
@@ -0,0 +1,21 @@
1
+ # Settings specified here will take precedence over those in config/environment.rb
2
+
3
+ # In the development environment your application's code is reloaded on
4
+ # every request. This slows down response time but is perfect for development
5
+ # since you don't have to restart the webserver when you make code changes.
6
+ config.cache_classes = false
7
+
8
+ # Log error messages when you accidentally call methods on nil.
9
+ config.whiny_nils = true
10
+
11
+ # Enable the breakpoint server that script/breakpointer connects to
12
+ config.breakpoint_server = true
13
+
14
+ # Show full error reports and disable caching
15
+ config.action_controller.consider_all_requests_local = true
16
+ config.action_controller.perform_caching = false
17
+ config.action_view.cache_template_extensions = false
18
+ config.action_view.debug_rjs = true
19
+
20
+ # Don't care if the mailer can't send
21
+ config.action_mailer.raise_delivery_errors = false
@@ -0,0 +1,18 @@
1
+ # Settings specified here will take precedence over those in config/environment.rb
2
+
3
+ # The production environment is meant for finished, "live" apps.
4
+ # Code is not reloaded between requests
5
+ config.cache_classes = true
6
+
7
+ # Use a different logger for distributed setups
8
+ # config.logger = SyslogLogger.new
9
+
10
+ # Full error reports are disabled and caching is turned on
11
+ config.action_controller.consider_all_requests_local = false
12
+ config.action_controller.perform_caching = true
13
+
14
+ # Enable serving of images, stylesheets, and javascripts from an asset server
15
+ # config.action_controller.asset_host = "http://assets.example.com"
16
+
17
+ # Disable delivery errors, bad email addresses will be ignored
18
+ # config.action_mailer.raise_delivery_errors = false
@@ -0,0 +1,19 @@
1
+ # Settings specified here will take precedence over those in config/environment.rb
2
+
3
+ # The test environment is used exclusively to run your application's
4
+ # test suite. You never need to work with it otherwise. Remember that
5
+ # your test database is "scratch space" for the test suite and is wiped
6
+ # and recreated between test runs. Don't rely on the data there!
7
+ config.cache_classes = true
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.action_controller.consider_all_requests_local = true
14
+ config.action_controller.perform_caching = false
15
+
16
+ # Tell ActionMailer not to deliver emails to the real world.
17
+ # The :test delivery method accumulates sent emails in the
18
+ # ActionMailer::Base.deliveries array.
19
+ config.action_mailer.delivery_method = :test
@@ -0,0 +1,23 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ # The priority is based upon order of creation: first created -> highest priority.
3
+
4
+ # Sample of regular route:
5
+ # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
6
+ # Keep in mind you can assign values other than :controller and :action
7
+
8
+ # Sample of named route:
9
+ # map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase'
10
+ # This route can be invoked with purchase_url(:id => product.id)
11
+
12
+ # You can have the root of your site routed by hooking up ''
13
+ # -- just remember to delete public/index.html.
14
+ # map.connect '', :controller => "welcome"
15
+
16
+ # Allow downloading Web Service WSDL as a file with an extension
17
+ # instead of a file named 'wsdl'
18
+ map.connect ':controller/service.wsdl', :action => 'wsdl'
19
+
20
+ # Install the default route as the lowest priority.
21
+ map.connect ':controller/:action/:id.:format'
22
+ map.connect ':controller/:action/:id'
23
+ end
@@ -0,0 +1,25 @@
1
+ class CreateUsers < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :users do |t|
4
+ t.column "login", :string, :limit => 80, :default => "", :null => false
5
+ t.column "salted_password", :string, :limit => 40, :default => "", :null => false
6
+ t.column "email", :string, :limit => 60, :default => "", :null => false
7
+ t.column "firstname", :string, :limit => 40
8
+ t.column "lastname", :string, :limit => 40
9
+ t.column "salt", :string, :limit => 40, :default => "", :null => false
10
+ t.column "verified", :integer, :default => 0
11
+ t.column "role", :string, :limit => 40
12
+ t.column "security_token", :string, :limit => 40
13
+ t.column "token_expiry", :datetime
14
+ t.column "created_at", :datetime
15
+ t.column "updated_at", :datetime
16
+ t.column "logged_in_at", :datetime
17
+ t.column "deleted", :integer, :default => 0
18
+ t.column "delete_after", :datetime
19
+ end
20
+ end
21
+
22
+ def self.down
23
+ drop_table :users
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ # This file is autogenerated. Instead of editing this file, please use the
2
+ # migrations feature of ActiveRecord to incrementally modify your database, and
3
+ # then regenerate this schema definition.
4
+
5
+ ActiveRecord::Schema.define(:version => 1) do
6
+
7
+ create_table "users", :force => true do |t|
8
+ t.column "login", :string, :limit => 80, :default => "", :null => false
9
+ t.column "salted_password", :string, :limit => 40, :default => "", :null => false
10
+ t.column "email", :string, :limit => 60, :default => "", :null => false
11
+ t.column "firstname", :string, :limit => 40
12
+ t.column "lastname", :string, :limit => 40
13
+ t.column "salt", :string, :limit => 40, :default => "", :null => false
14
+ t.column "verified", :integer, :default => 0
15
+ t.column "role", :string, :limit => 40
16
+ t.column "security_token", :string, :limit => 40
17
+ t.column "token_expiry", :datetime
18
+ t.column "created_at", :datetime
19
+ t.column "updated_at", :datetime
20
+ t.column "logged_in_at", :datetime
21
+ t.column "deleted", :integer, :default => 0
22
+ t.column "delete_after", :datetime
23
+ end
24
+
25
+ end
@@ -0,0 +1,113 @@
1
+ #--
2
+ # Add these methods to the top-level module so that they are available in all
3
+ # modules, etc
4
+ #++
5
+ class ::Module
6
+ # Defines a constant within a module/class ONLY if that constant does
7
+ # not already exist.
8
+ #
9
+ # This can be used to implement defaults in plugins/engines/libraries, e.g.
10
+ # if a plugin module exists:
11
+ # module MyPlugin
12
+ # default_constant :MyDefault, "the_default_value"
13
+ # end
14
+ #
15
+ # then developers can override this default by defining that constant at
16
+ # some point *before* the module/plugin gets loaded (such as environment.rb)
17
+ def default_constant(name, value)
18
+ if !(name.is_a?(String) or name.is_a?(Symbol))
19
+ raise "Cannot use a #{name.class.name} ['#{name}'] object as a constant name"
20
+ end
21
+ if !self.const_defined?(name)
22
+ self.class_eval("#{name} = #{value.inspect}")
23
+ end
24
+ end
25
+
26
+ # A mechanism for defining configuration of Modules. With this
27
+ # mechanism, default values for configuration can be provided within shareable
28
+ # code, and the end user can customise the configuration without having to
29
+ # provide all values.
30
+ #
31
+ # Example:
32
+ #
33
+ # module MyModule
34
+ # config :param_one, "some value"
35
+ # config :param_two, 12345
36
+ # end
37
+ #
38
+ # Those values can now be accessed by the following method
39
+ #
40
+ # MyModule.config :param_one
41
+ # => "some value"
42
+ # MyModule.config :param_two
43
+ # => 12345
44
+ #
45
+ # ... or, if you have overrriden the method 'config'
46
+ #
47
+ # MyModule::CONFIG[:param_one]
48
+ # => "some value"
49
+ # MyModule::CONFIG[:param_two]
50
+ # => 12345
51
+ #
52
+ # Once a value is stored in the configuration, it will not be altered
53
+ # by subsequent assignments, unless a special flag is given:
54
+ #
55
+ # (later on in your code, most likely in another file)
56
+ # module MyModule
57
+ # config :param_one, "another value"
58
+ # config :param_two, 98765, :force
59
+ # end
60
+ #
61
+ # The configuration is now:
62
+ #
63
+ # MyModule.config :param_one
64
+ # => "some value" # not changed
65
+ # MyModule.config :param_two
66
+ # => 98765
67
+ #
68
+ # Configuration values can also be given as a Hash:
69
+ #
70
+ # MyModule.config :param1 => 'value1', :param2 => 'value2'
71
+ #
72
+ # Setting of these values can also be forced:
73
+ #
74
+ # MyModule.config :param1 => 'value3', :param2 => 'value4', :force => true
75
+ #
76
+ # A value of anything other than false or nil given for the :force key will
77
+ # result in the new values *always* being set.
78
+ def config(*args)
79
+
80
+ raise "config expects at least one argument" if args.empty?
81
+
82
+ # extract the arguments
83
+ if args[0].is_a?(Hash)
84
+ override = args[0][:force]
85
+ args[0].delete(:force)
86
+ args[0].each { |key, value| _handle_config(key, value, override)}
87
+ else
88
+ _handle_config(*args)
89
+ end
90
+ end
91
+
92
+ private
93
+ # Actually set the config values
94
+ def _handle_config(name, value=nil, override=false)
95
+ if !self.const_defined?("CONFIG")
96
+ self.class_eval("CONFIG = {}")
97
+ end
98
+
99
+ if value != nil
100
+ if override or self::CONFIG[name] == nil
101
+ self::CONFIG[name] = value
102
+ end
103
+ else
104
+ # if we pass an array of config keys to config(),
105
+ # get the array of values back
106
+ if name.is_a? Array
107
+ name.map { |c| self::CONFIG[c] }
108
+ else
109
+ self::CONFIG[name]
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,80 @@
1
+ require 'hpricot'
2
+
3
+ module HpricotTestExtension
4
+ # returns the inner content of
5
+ # the first tag found by the css query
6
+ def tag(css_query)
7
+ process_output
8
+ @output.content_for(css_query)
9
+ end
10
+
11
+ # returns an array of tag contents
12
+ # for all of the tags found by the
13
+ # css query
14
+ def tags(css_query)
15
+ process_output
16
+ @output.content_for_all(css_query)
17
+ end
18
+
19
+ # returns a raw Hpricot::Elem object
20
+ # for the first result found by the query
21
+ def element(css_query)
22
+ process_output
23
+ @output[css_query].first
24
+ end
25
+
26
+ # returns an array of Hpricot::Elem objects
27
+ # for the results found by the query
28
+ def elements(css_query)
29
+ process_output
30
+ @output[css_query]
31
+ end
32
+
33
+ # small utility class for working with
34
+ # the Hpricot parser class
35
+ class DocumentOutput
36
+ def initialize(response_body)
37
+ @parser = Hpricot.parse(response_body)
38
+ end
39
+
40
+ def content_for(css_query)
41
+ @parser.search(css_query).first.inner_text
42
+ end
43
+
44
+ def content_for_all(css_query)
45
+ @parser.search(css_query).collect(&:inner_text)
46
+ end
47
+
48
+ def [](css_query)
49
+ @parser.search(css_query)
50
+ end
51
+ end
52
+
53
+ protected
54
+ # creates a new DocumentOutput object from the response
55
+ # body if hasn't already been created. This is
56
+ # called automatically by the element and tag methods
57
+ def process_output
58
+ @output = HpricotTestExtension::DocumentOutput.new(@response.body) if @output.nil?
59
+ end
60
+ end
61
+
62
+ # monkey patches
63
+ class Hpricot::Elem
64
+ def should_contain(value)
65
+ self.inner_text.include?(value)
66
+ end
67
+
68
+ # courtesy of 'thomas' from the comments
69
+ # of _whys blog - get in touch if you want a better credit!
70
+ def inner_text
71
+ self.children.collect do |child|
72
+ child.is_a?(Hpricot::Text) ? child.content : child.inner_text
73
+ end.join.strip
74
+ end
75
+ end
76
+
77
+ # inject into test::unit
78
+ class Test::Unit::TestCase
79
+ include HpricotTestExtension
80
+ end