amrita2 1.9.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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