parlement 0.10 → 0.11

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 (109) hide show
  1. data/CHANGES +11 -0
  2. data/MEMORY +9 -1
  3. data/README +5 -4
  4. data/app/controllers/account_controller.rb +10 -13
  5. data/app/controllers/application.rb +4 -5
  6. data/app/controllers/elt_controller.rb +9 -7
  7. data/app/controllers/person_controller.rb +1 -3
  8. data/app/controllers/subscriber_controller.rb +10 -10
  9. data/app/helpers/elt_helper.rb +2 -0
  10. data/app/models/elt.rb +28 -19
  11. data/app/models/mail.rb +26 -14
  12. data/app/models/mail_notify.rb +5 -4
  13. data/app/models/person.rb +11 -2
  14. data/app/views/account/_login.rhtml +3 -3
  15. data/app/views/account/_show.rhtml +12 -14
  16. data/app/views/elt/_choice.rhtml +3 -3
  17. data/app/views/elt/_elt.rhtml +4 -4
  18. data/app/views/elt/_list.rhtml +2 -2
  19. data/app/views/elt/_listByDate.rhtml +1 -1
  20. data/app/views/elt/_listByVote.rhtml +1 -1
  21. data/app/views/elt/new.rhtml +3 -3
  22. data/app/views/elt/show.rhtml +2 -2
  23. data/app/views/layouts/top.rhtml +6 -0
  24. data/app/views/mail_notify/publish.text.html.rhtml +1 -1
  25. data/app/views/person/_listElts.rhtml +5 -3
  26. data/app/views/person/show.rhtml +1 -2
  27. data/config/boot.rb +5 -4
  28. data/config/environment.rb +6 -4
  29. data/config/routes.rb +3 -2
  30. data/db/development_structure.sql +15 -4
  31. data/db/migrate/006_last_activity.rb +10 -0
  32. data/db/schema.rb +67 -49
  33. data/public/dispatch.fcgi +1 -0
  34. data/public/javascripts/controls.js +41 -23
  35. data/public/javascripts/dragdrop.js +317 -99
  36. data/public/javascripts/effects.js +301 -166
  37. data/public/javascripts/prototype.js +932 -402
  38. data/public/stylesheets/default.css +3 -2
  39. data/test/unit/elt_test.rb +13 -0
  40. data/test/unit/mail_test.rb +3 -1
  41. data/vendor/plugins/engines/CHANGELOG +203 -99
  42. data/vendor/plugins/engines/MIT-LICENSE +1 -1
  43. data/vendor/plugins/engines/README +32 -384
  44. data/vendor/plugins/engines/Rakefile +14 -0
  45. data/vendor/plugins/engines/UPGRADING +93 -0
  46. data/vendor/plugins/engines/about.yml +7 -0
  47. data/vendor/plugins/engines/generators/plugin_migration/USAGE +45 -0
  48. data/vendor/plugins/engines/generators/plugin_migration/plugin_migration_generator.rb +79 -0
  49. data/vendor/plugins/engines/generators/plugin_migration/templates/plugin_migration.erb +13 -0
  50. data/vendor/plugins/engines/init.rb +34 -47
  51. data/vendor/plugins/engines/install.rb +32 -0
  52. data/vendor/plugins/engines/lib/engines/{ruby_extensions.rb → deprecated_config_support.rb} +135 -113
  53. data/vendor/plugins/engines/lib/engines/plugin.rb +214 -0
  54. data/vendor/plugins/engines/lib/engines/plugin_list.rb +31 -0
  55. data/vendor/plugins/engines/lib/engines/plugin_migrator.rb +60 -0
  56. data/vendor/plugins/engines/lib/engines/rails_extensions/active_record.rb +19 -0
  57. data/vendor/plugins/engines/lib/engines/rails_extensions/dependencies.rb +143 -0
  58. data/vendor/plugins/engines/lib/engines/rails_extensions/migrations.rb +155 -0
  59. data/vendor/plugins/engines/lib/engines/rails_extensions/public_asset_helpers.rb +116 -0
  60. data/vendor/plugins/engines/lib/engines/rails_extensions/rails.rb +20 -0
  61. data/vendor/plugins/engines/lib/engines/rails_extensions/rails_initializer.rb +86 -0
  62. data/vendor/plugins/engines/lib/engines/rails_extensions/routing.rb +77 -0
  63. data/vendor/plugins/engines/lib/engines/rails_extensions/templates.rb +140 -0
  64. data/vendor/plugins/engines/lib/engines/rails_extensions.rb +6 -0
  65. data/vendor/plugins/engines/lib/engines/testing.rb +88 -0
  66. data/vendor/plugins/engines/lib/engines.rb +281 -425
  67. data/vendor/plugins/engines/tasks/engines.rake +108 -137
  68. metadata +218 -250
  69. data/db/ROOT/perso.txt +0 -214
  70. data/public/images/indicator.gif +0 -0
  71. data/public/images/orange_by_darren_Hester_350o.jpg +0 -0
  72. data/public/images/smile.png +0 -0
  73. data/vendor/plugins/engines/generators/engine/USAGE +0 -26
  74. data/vendor/plugins/engines/generators/engine/engine_generator.rb +0 -199
  75. data/vendor/plugins/engines/generators/engine/templates/README +0 -85
  76. data/vendor/plugins/engines/generators/engine/templates/init_engine.erb +0 -15
  77. data/vendor/plugins/engines/generators/engine/templates/install.erb +0 -4
  78. data/vendor/plugins/engines/generators/engine/templates/lib/engine.erb +0 -6
  79. data/vendor/plugins/engines/generators/engine/templates/licenses/GPL +0 -18
  80. data/vendor/plugins/engines/generators/engine/templates/licenses/LGPL +0 -19
  81. data/vendor/plugins/engines/generators/engine/templates/licenses/MIT +0 -22
  82. data/vendor/plugins/engines/generators/engine/templates/licenses/None +0 -1
  83. data/vendor/plugins/engines/generators/engine/templates/public/javascripts/engine.js +0 -0
  84. data/vendor/plugins/engines/generators/engine/templates/public/stylesheets/engine.css +0 -0
  85. data/vendor/plugins/engines/generators/engine/templates/tasks/engine.rake +0 -0
  86. data/vendor/plugins/engines/generators/engine/templates/test/test_helper.erb +0 -17
  87. data/vendor/plugins/engines/lib/bundles/require_resource.rb +0 -124
  88. data/vendor/plugins/engines/lib/bundles.rb +0 -77
  89. data/vendor/plugins/engines/lib/engines/action_mailer_extensions.rb +0 -140
  90. data/vendor/plugins/engines/lib/engines/action_view_extensions.rb +0 -141
  91. data/vendor/plugins/engines/lib/engines/active_record_extensions.rb +0 -21
  92. data/vendor/plugins/engines/lib/engines/dependencies_extensions.rb +0 -129
  93. data/vendor/plugins/engines/lib/engines/migration_extensions.rb +0 -53
  94. data/vendor/plugins/engines/lib/engines/routing_extensions.rb +0 -28
  95. data/vendor/plugins/engines/lib/engines/testing_extensions.rb +0 -327
  96. data/vendor/plugins/engines/tasks/deprecated_engines.rake +0 -7
  97. data/vendor/plugins/engines/test/action_view_extensions_test.rb +0 -9
  98. data/vendor/plugins/engines/test/ruby_extensions_test.rb +0 -115
  99. data/vendor/plugins/guid/README.TXT +0 -29
  100. data/vendor/plugins/guid/init.rb +0 -30
  101. data/vendor/plugins/guid/lib/usesguid.rb +0 -37
  102. data/vendor/plugins/guid/lib/uuid22.rb +0 -43
  103. data/vendor/plugins/guid/lib/uuidtools.rb +0 -572
  104. data/vendor/plugins/responds_to_parent/MIT-LICENSE +0 -20
  105. data/vendor/plugins/responds_to_parent/README +0 -42
  106. data/vendor/plugins/responds_to_parent/Rakefile +0 -22
  107. data/vendor/plugins/responds_to_parent/init.rb +0 -1
  108. data/vendor/plugins/responds_to_parent/lib/responds_to_parent.rb +0 -46
  109. data/vendor/plugins/responds_to_parent/test/responds_to_parent_test.rb +0 -115
@@ -0,0 +1,116 @@
1
+ # The engines plugin makes it trivial to share public assets using plugins.
2
+ # To do this, include an <tt>assets</tt> directory within your plugin, and put
3
+ # your javascripts, stylesheets and images in subdirectories of that folder:
4
+ #
5
+ # my_plugin
6
+ # |- init.rb
7
+ # |- lib/
8
+ # |- assets/
9
+ # |- javascripts/
10
+ # | |- my_functions.js
11
+ # |
12
+ # |- stylesheets/
13
+ # | |- my_styles.css
14
+ # |
15
+ # |- images/
16
+ # |- my_face.jpg
17
+ #
18
+ # Files within the <tt>asset</tt> structure are automatically mirrored into
19
+ # a publicly-accessible folder each time your application starts (see
20
+ # Plugin#mirror_public_assets).
21
+ #
22
+ #
23
+ # == Using plugin assets in views
24
+ #
25
+ # It's also simple to use Rails' helpers in your views to use plugin assets.
26
+ # The default helper methods have been enhanced by the engines plugin to accept
27
+ # a <tt>:plugin</tt> option, indicating the plugin containing the desired asset.
28
+ #
29
+ # For example, it's easy to use plugin assets in your layouts:
30
+ #
31
+ # <%= stylesheet_link_tag "my_styles", :plugin => "my_plugin", :media => "screen" %>
32
+ # <%= javascript_include_tag "my_functions", :plugin => "my_plugin" %>
33
+ #
34
+ # ... and similarly in views and partials, it's easy to use plugin images:
35
+ #
36
+ # <%= image_tag "my_face", :plugin => "my_plugin" %>
37
+ # <!-- or -->
38
+ # <%= image_path "my_face", :plugin => "my_plugin" %>
39
+ #
40
+ # Where the default helpers allow the specification of more than one file (i.e. the
41
+ # javascript and stylesheet helpers), you can do similarly for multiple assets from
42
+ # within a single plugin.
43
+ #
44
+ # ---
45
+ #
46
+ # This module enhances four of the methods from ActionView::Helpers::AssetTagHelper:
47
+ #
48
+ # * stylesheet_link_tag
49
+ # * javascript_include_tag
50
+ # * image_path
51
+ # * image_tag
52
+ #
53
+ # Each one of these methods now accepts the key/value pair <tt>:plugin => "plugin_name"</tt>,
54
+ # which can be used to specify the originating plugin for any assets.
55
+ #
56
+ module Engines::RailsExtensions::PublicAssetHelpers
57
+ def self.included(base) #:nodoc:
58
+ base.class_eval do
59
+ [:stylesheet_link_tag, :javascript_include_tag, :image_path, :image_tag].each do |m|
60
+ alias_method_chain m, :engine_additions
61
+ end
62
+ end
63
+ end
64
+
65
+ # Adds plugin functionality to Rails' default stylesheet_link_tag method.
66
+ def stylesheet_link_tag_with_engine_additions(*sources)
67
+ stylesheet_link_tag_without_engine_additions(*Engines::RailsExtensions::PublicAssetHelpers.pluginify_sources("stylesheets", *sources))
68
+ end
69
+
70
+ # Adds plugin functionality to Rails' default javascript_include_tag method.
71
+ def javascript_include_tag_with_engine_additions(*sources)
72
+ javascript_include_tag_without_engine_additions(*Engines::RailsExtensions::PublicAssetHelpers.pluginify_sources("javascripts", *sources))
73
+ end
74
+
75
+ #--
76
+ # Our modified image_path now takes a 'plugin' option, though it doesn't require it
77
+ #++
78
+
79
+ # Adds plugin functionality to Rails' default image_path method.
80
+ def image_path_with_engine_additions(source, options={})
81
+ options.stringify_keys!
82
+ source = Engines::RailsExtensions::PublicAssetHelpers.plugin_asset_path(options["plugin"], "images", source) if options["plugin"]
83
+ image_path_without_engine_additions(source)
84
+ end
85
+
86
+ # Adds plugin functionality to Rails' default image_tag method.
87
+ def image_tag_with_engine_additions(source, options={})
88
+ options.stringify_keys!
89
+ if options["plugin"]
90
+ source = Engines::RailsExtensions::PublicAssetHelpers.plugin_asset_path(options["plugin"], "images", source)
91
+ options.delete("plugin")
92
+ end
93
+ image_tag_without_engine_additions(source, options)
94
+ end
95
+
96
+ #--
97
+ # The following are methods on this module directly because of the weird-freaky way
98
+ # Rails creates the helper instance that views actually get
99
+ #++
100
+
101
+ # Convert sources to the paths for the given plugin, if any plugin option is given
102
+ def self.pluginify_sources(type, *sources)
103
+ options = sources.last.is_a?(Hash) ? sources.pop.stringify_keys : { }
104
+ sources.map! { |s| plugin_asset_path(options["plugin"], type, s) } if options["plugin"]
105
+ options.delete("plugin") # we don't want it appearing in the HTML
106
+ sources << options # re-add options
107
+ end
108
+
109
+ # Returns the publicly-addressable relative URI for the given asset, type and plugin
110
+ def self.plugin_asset_path(plugin_name, type, asset)
111
+ raise "No plugin called '#{plugin_name}' - please use the full name of a loaded plugin." if Rails.plugins[plugin_name].nil?
112
+ "/#{Rails.plugins[plugin_name].public_asset_directory}/#{type}/#{asset}"
113
+ end
114
+ end
115
+
116
+ ::ActionView::Helpers::AssetTagHelper.send(:include, Engines::RailsExtensions::PublicAssetHelpers)
@@ -0,0 +1,20 @@
1
+ # In order to give a richer infrastructure for dealing with plugins, the engines
2
+ # plugin adds two new attributes to the Rails module:
3
+ #
4
+ # [+plugins+] A PluginList instance which holds the currently loaded plugins
5
+ # [+configuration+] The current Rails::Configuration instance, so that we can
6
+ # query any parameters that might be set *after* Rails has
7
+ # loaded, as well as during plugin initialization
8
+ #
9
+ #--
10
+ # Here we just re-open the Rails module and add our custom accessors; it
11
+ # may be cleaner to seperate them into a module, but in this case that seems
12
+ # like overkill.
13
+ #++
14
+ module Rails
15
+ # The set of all loaded plugins
16
+ mattr_accessor :plugins
17
+
18
+ # The Rails::Initializer::Configuration object
19
+ mattr_accessor :configuration
20
+ end
@@ -0,0 +1,86 @@
1
+ # Enhances the Rails::Initializer class to be a bit smarter about
2
+ # plugins. See Engines::RailsExtensions::RailsInitializer for more
3
+ # details.
4
+
5
+ require "engines/rails_extensions/rails"
6
+ require 'engines/plugin_list'
7
+
8
+ # The engines plugin changes the way that Rails actually loads other plugins.
9
+ # It creates instances of the Plugin class to represent each plugin, stored
10
+ # in the <tt>Rails.plugins</tt> PluginList.
11
+ #
12
+ # ---
13
+ #
14
+ # Three methods from the original Rails::Initializer module are overridden
15
+ # by Engines::RailsExtensions::RailsInitializer:
16
+ #
17
+ # [+load_plugin+] which now creates Plugin instances and calls Plugin#load
18
+ # [+after_initialize+] which now performs Engines.after_initialize in addition
19
+ # to the given config block
20
+ # [<tt>plugin_enabled?</tt>] which now respects the result of
21
+ # Engines.load_all_plugins?
22
+ #
23
+ module Engines::RailsExtensions::RailsInitializer
24
+ def self.included(base) #:nodoc:
25
+ base.class_eval do
26
+ alias_method_chain :load_plugin, :engine_additions
27
+ alias_method_chain :after_initialize, :engine_additions
28
+ alias_method_chain :plugin_enabled?, :engine_additions
29
+ end
30
+ end
31
+
32
+ # Loads all plugins in configuration.plugin_paths, regardless of the contents
33
+ # of configuration.plugins
34
+ def load_all_plugins
35
+ # a nil value implies we don't care about plugins; load 'em all in a reliable order
36
+ find_plugins(configuration.plugin_paths).sort.each { |path| load_plugin path }
37
+ end
38
+
39
+ # Loads a plugin, performing the extra load path/public file magic of
40
+ # engines by calling Plugin#load.
41
+ def load_plugin_with_engine_additions(directory)
42
+ name = plugin_name(directory)
43
+ return false if loaded_plugins.include?(name)
44
+
45
+ logger.debug "loading plugin from #{directory} with engine additions"
46
+
47
+ # add the Plugin object
48
+ plugin = Plugin.new(plugin_name(directory), directory)
49
+ Rails.plugins << plugin
50
+
51
+ # do the other stuff that load_plugin used to do. This includes
52
+ # allowing the plugin's init.rb to set configuration options on
53
+ # it's instance, which can then be used in it's initialization
54
+ load_plugin_without_engine_additions(directory)
55
+
56
+ # perform additional loading tasks like mirroring public assets
57
+ # and adding app directories to the appropriate load paths
58
+ plugin.load
59
+
60
+ true
61
+ end
62
+
63
+ # Allow the engines plugin to do whatever it needs to do after Rails has
64
+ # loaded, and then call the actual after_initialize block. Currently, this
65
+ # is call Engines.after_initialize.
66
+ def after_initialize_with_engine_additions
67
+ Engines.after_initialize
68
+ after_initialize_without_engine_additions
69
+ end
70
+
71
+ protected
72
+
73
+ # Returns true if the plugin at the given path should be loaded; false
74
+ # otherwise. If Engines.load_all_plugins? is true, this method will return
75
+ # true regardless of the path given.
76
+ def plugin_enabled_with_engine_additions?(path)
77
+ Engines.load_all_plugins? || plugin_enabled_without_engine_additions?(path)
78
+ end
79
+
80
+ # Returns the name of the plugin at the given path.
81
+ def plugin_name(path)
82
+ File.basename(path)
83
+ end
84
+ end
85
+
86
+ ::Rails::Initializer.send(:include, Engines::RailsExtensions::RailsInitializer)
@@ -0,0 +1,77 @@
1
+ # Effective use of Rails' routes can help create a tidy and elegant set of URLs,
2
+ # and is a significant part of creating an external API for your web application.
3
+ #
4
+ # When developing plugins which contain controllers, it seems obvious that including
5
+ # the corresponding routes would be extremely useful. This is particularly true
6
+ # when exposing RESTful resources using the new REST-ian features of Rails 1.2.
7
+ #
8
+ # == Including routes in your plugin
9
+ #
10
+ # The engines plugin makes it possible to include a set of routes within your plugin
11
+ # very simply, as it turns out. In your plugin, you simply include a <tt>routes.rb</tt>
12
+ # file like the one below at the root of your plugin:
13
+ #
14
+ # connect "/login", :controller => "my_plugin/account", :action => "login"
15
+ #
16
+ # # add a named route
17
+ # logout "/logout", :controller => "my_plugin/account", :action => "logout"
18
+ #
19
+ # # some restful stuff
20
+ # resources :things do |t|
21
+ # t.resources :other_things
22
+ # end
23
+ #
24
+ # Everywhere in a normal <tt>RAILS_ROOT/config/routes.rb</tt> file
25
+ # where you might have <tt>map.connect</tt>, you just use <tt>connect</tt> in your
26
+ # plugin's <tt>routes.rb</tt>.
27
+ #
28
+ # === Hooking it up in your application
29
+ #
30
+ # While it would be possible to have each plugin's routes automagically included into
31
+ # the application's route set, to do so would actually be a stunningly bad idea. Route
32
+ # priority is the key issue here. You, the application developer, needs to be in complete
33
+ # control when it comes to specifying the priority of routes in your application, since
34
+ # the ordering of your routes directly affects how Rails will interpret incoming requests.
35
+ #
36
+ # To add plugin routes into your application's <tt>routes.rb</tt> file, you need to explicitly
37
+ # map them in using the Engines::RailsExtensions::Routing#from_plugin method:
38
+ #
39
+ # ApplicationController::Routing::Routes.draw do |map|
40
+ #
41
+ # map.connect "/app_stuff", :controller => "application_thing" # etc...
42
+ #
43
+ # # This line includes the routes from the given plugin at this point, giving you
44
+ # # control over the priority of your application routes
45
+ # map.from_plugin :your_plugin
46
+ #
47
+ # map.connect ":controller/:action/:id"
48
+ # end
49
+ #
50
+ # By including routes in plugins which have controllers, you can now share in a simple way
51
+ # a compact and elegant URL scheme which corresponds to those controllers.
52
+ #
53
+ # ---
54
+ #
55
+ # The Engines::RailsExtensions::Routing module defines extensions to Rails'
56
+ # routing (ActionController::Routing) mechanism such that routes can be loaded
57
+ # from a given plugin.
58
+ #
59
+ # The key method is Engines::RailsExtensions::Routing#from_plugin, which can be called
60
+ # within your application's <tt>config/routes.rb</tt> file to load plugin routes at that point.
61
+ #
62
+ module Engines::RailsExtensions::Routing
63
+ # Loads the set of routes from within a plugin and evaluates them at this
64
+ # point within an application's main <tt>routes.rb</tt> file.
65
+ #
66
+ # Plugin routes are loaded from <tt><plugin_root>/routes.rb</tt>.
67
+ def from_plugin(name)
68
+ # At the point in which routing is loaded, we cannot guarantee that all
69
+ # plugins are in Rails.plugins, so instead we need to use find_plugin_path
70
+ path = Engines.find_plugin_path(name)
71
+ routes_path = File.join(path, name.to_s, "routes.rb")
72
+ logger.debug "loading routes from #{routes_path}"
73
+ eval(IO.read(routes_path), binding, routes_path) if File.file?(routes_path)
74
+ end
75
+ end
76
+
77
+ ::ActionController::Routing::RouteSet::Mapper.send(:include, Engines::RailsExtensions::Routing)
@@ -0,0 +1,140 @@
1
+ # As well as providing code overloading for controllers and helpers
2
+ # (see Engines::RailsExtensions::Dependencies), the engines plugin also allows
3
+ # developers to selectively override views and partials within their application.
4
+ #
5
+ # == An example
6
+ #
7
+ # This is achieved in much the same way as controller overriding. Our plugin contains
8
+ # a view to be rendered at the URL <tt>/test/hello</tt>, in
9
+ # <tt>our_plugin/app/views/test/hello.rhtml</tt>:
10
+ #
11
+ # <div class="greeting">Hi, <%= @dude.name %>, what's up?</div>
12
+ #
13
+ # If in a particular application we're not happy with this message, we can override
14
+ # it by replacing the partial in our own application -
15
+ # <tt>RAILS_ROOT/app/views/test/hello.rhtml</tt>:
16
+ #
17
+ # <div class="greeting custom_class">Wassup <%= @dude.name %>.
18
+ # Waaaaassaaaaaaaaup</div>
19
+ #
20
+ # This view will then be rendered in favour of that in the plugin.
21
+ #
22
+ module Engines::RailsExtensions::Templates
23
+
24
+ # Override the finding of partials and views. This is achieved by wrapping
25
+ # the (private) method #full_template_path_with_engine_additions, that checks
26
+ # for the given template within plugins as well as the application.
27
+ module ActionView
28
+ def self.included(base) #:nodoc:
29
+ base.class_eval { alias_method_chain :full_template_path, :engine_additions }
30
+ end
31
+
32
+ private
33
+ def full_template_path_with_engine_additions(template_path, extension)
34
+ path_in_app_directory = full_template_path_from_application(template_path, extension)
35
+
36
+ # First check for this template in the application. If it exists, the user has
37
+ # overridden anything from the plugin, so use it (unless we're testing plugins;
38
+ # see full_template_path_from_application())
39
+ return path_in_app_directory if path_in_app_directory && File.exist?(path_in_app_directory)
40
+
41
+ # Otherwise, check in the plugins to see if the template can be found there.
42
+ # Load this in order so that more recently started plugins will take priority.
43
+ Rails.plugins.by_precedence do |plugin|
44
+ plugin_specific_path = File.join(plugin.root, 'app', 'views',
45
+ template_path.to_s + '.' + extension.to_s)
46
+ return plugin_specific_path if File.exist?(plugin_specific_path)
47
+ end
48
+
49
+ # If it cannot be found anywhere, return the default path.
50
+ return full_template_path_without_engine_additions(template_path, extension)
51
+ end
52
+
53
+ # Return a path to this template within our default app/views directory.
54
+ # In some circumstances, we may wish to prevent users from overloading views,
55
+ # such as when we are testing plugins with views. In this case, return "".
56
+ def full_template_path_from_application(template_path, extension)
57
+ if Engines.disable_application_view_loading
58
+ nil
59
+ else
60
+ full_template_path_without_engine_additions(template_path, extension)
61
+ end
62
+ end
63
+ end
64
+
65
+
66
+ # The Layout module overrides a single (private) method in ActionController::Layout::ClassMethods,
67
+ # called #layout_list. This method now returns an array of layouts, including those in plugins.
68
+ module Layout
69
+ def self.included(base) #:nodoc:
70
+ base.class_eval { alias_method_chain :layout_list, :engine_additions }
71
+ end
72
+
73
+ private
74
+ # Return the list of layouts, including any in the <tt>app/views/layouts</tt>
75
+ # directories of loaded plugins.
76
+ def layout_list_with_engine_additions
77
+ plugin_layouts = Rails.plugins.by_precedence.map do |p|
78
+ File.join(p.root, "app", "views", "layouts")
79
+ end
80
+ layout_list_without_engine_additions + Dir["{#{plugin_layouts.join(",")}}/**/*"]
81
+ end
82
+ end
83
+
84
+
85
+ # The way ActionMailer is coded in terms of finding templates is very restrictive, to the point
86
+ # where all templates for rendering must exist under the single base path. This is difficult to
87
+ # work around without re-coding significant parts of the action mailer code.
88
+ #
89
+ # ---
90
+ #
91
+ # The MailTemplates module overrides two (private) methods from ActionMailer to enable mail
92
+ # templates within plugins:
93
+ #
94
+ # [+template_path+] which now produces the contents of #template_paths
95
+ # [+render+] which now find the first matching template and creates an ActionVew::Base
96
+ # instance with the correct @base_path for that template
97
+ module MailTemplates
98
+ def self.included(base) #:nodoc:
99
+ base.class_eval do
100
+ alias_method_chain :template_path, :engine_additions
101
+ alias_method_chain :render, :engine_additions
102
+ end
103
+ end
104
+
105
+ private
106
+ # Returns all possible template paths for the current mailer, including those
107
+ # within the loaded plugins.
108
+ def template_paths
109
+ paths = Rails.plugins.by_precedence.map { |p| "#{p.root}/app/views/#{mailer_name}" }
110
+ paths.unshift(template_path_without_engine_additions) unless Engines.disable_application_view_loading
111
+ paths
112
+ end
113
+
114
+ # Return something that Dir[] can glob against. This method is called in
115
+ # ActionMailer::Base#create! and used as part of an argument to Dir. We can
116
+ # take advantage of this by using some of the features of Dir.glob to search
117
+ # multiple paths for matching files.
118
+ def template_path_with_engine_additions
119
+ "{#{template_paths.join(",")}}"
120
+ end
121
+
122
+ # We've broken this up so that we can dynamically alter the base_path that ActionView
123
+ # is rendering from so that templates can be located from plugins.
124
+ def render_with_engine_additions(opts)
125
+ template_path_for_method = Dir["#{template_path}/#{opts[:file]}*"].first
126
+ body = opts.delete(:body)
127
+ i = initialize_template_class(body)
128
+ i.base_path = File.dirname(template_path_for_method)
129
+ i.render(opts)
130
+ end
131
+ end
132
+ end
133
+
134
+
135
+ ::ActionView::Base.send(:include, Engines::RailsExtensions::Templates::ActionView)
136
+ ::ActionController::Layout::ClassMethods.send(:include, Engines::RailsExtensions::Templates::Layout)
137
+
138
+ if Object.const_defined?(:ActionMailer) # We don't need to do this if ActionMailer hasn't been loaded.
139
+ ::ActionMailer::Base.send(:include, Engines::RailsExtensions::Templates::MailTemplates)
140
+ end
@@ -0,0 +1,6 @@
1
+ # This module contains all the extensions that the engines plugin makes to
2
+ # Rails core. Explanations of how each extension works are included as RDoc
3
+ # documentation for each of the modules listed.
4
+ module Engines::RailsExtensions
5
+ # let's not rely *entirely* on Rails' magic modules. Not just yet.
6
+ end
@@ -0,0 +1,88 @@
1
+ # Contains the enhancements to assist in testing plugins. See Engines::Testing
2
+ # for more details.
3
+
4
+ require 'test/unit'
5
+ require 'test_help'
6
+
7
+ require 'tmpdir'
8
+ require 'fileutils'
9
+
10
+ # In most cases, Rails' own plugin testing mechanisms are sufficient. However, there
11
+ # are cases where plugins can be given a helping hand in the testing arena. This module
12
+ # contains some methods to assist when testing plugins that contain fixtures.
13
+ #
14
+ # == Fixtures and plugins
15
+ #
16
+ # Since Rails' own fixtures method is fairly strict about where files can be loaded from,
17
+ # the simplest approach when running plugin tests with fixtures is to simply copy all
18
+ # fixtures into a single temporary location and inform the standard Rails mechanism to
19
+ # use this directory, rather than RAILS_ROOT/test/fixtures.
20
+ #
21
+ # The Engines::Testing#setup_plugin_fixtures method does this, copying all plugin fixtures
22
+ # into the temporary location before and tests are performed. This behaviour is invoked
23
+ # the the rake tasks provided by the Engines plugin, in the "test:plugins" namespace. If
24
+ # necessary, you can invoke the task manually.
25
+ #
26
+ # If you wish to take advantage of this, add a call to the Engines::Testing.set_fixture_path
27
+ # method somewhere before your tests (in a test_helper file, or above the TestCase itself).
28
+ #
29
+ # = Testing plugins
30
+ #
31
+ # Normally testing a plugin will require that Rails is loaded, unless you are including
32
+ # a skeleton Rails environment or set of mocks within your plugin tests. If you require
33
+ # the Rails environment to be started, you must ensure that this actually happens; while
34
+ # it's not obvious, your tests do not automatically run with Rails loaded.
35
+ #
36
+ # The simplest way to setup plugin tests is to include a test helper with the following
37
+ # contents:
38
+ #
39
+ # # Load the normal Rails helper. This ensures the environment is loaded
40
+ # require File.expand_path(File.dirname(__FILE__) + '/../../../../test/test_helper')
41
+ # # Ensure that we are using the temporary fixture path
42
+ # Engines::Testing.set_fixture_path
43
+ #
44
+ # Then run tests using the provided tasks (<tt>test:plugins</tt>, or the tasks that the engines
45
+ # plugin provides - <tt>test:plugins:units</tt>, etc.).
46
+ #
47
+ # Alternatively, you can explicitly load the environment by adpating the contents of the
48
+ # default <tt>test_helper</tt>:
49
+ #
50
+ # ENV["RAILS_ENV"] = "test"
51
+ # # Note that we are requiring config/environment from the root of the enclosing application.
52
+ # require File.expand_path(File.dirname(__FILE__) + "/../../../../config/environment")
53
+ # require 'test_help'
54
+ #
55
+ module Engines::Testing
56
+ mattr_accessor :temporary_fixtures_directory
57
+ self.temporary_fixtures_directory = FileUtils.mkdir_p(File.join(Dir.tmpdir, "rails_fixtures"))
58
+
59
+ # Copies fixtures from plugins and the application into a temporary directory
60
+ # (Engines::Testing.temporary_fixtures_directory).
61
+ #
62
+ # If a set of plugins is not given, fixtures are copied from all plugins in order
63
+ # of precedence, meaning that plugins can 'overwrite' the fixtures of others if they are
64
+ # loaded later; the application's fixtures are copied last, allowing any custom fixtures
65
+ # to override those in the plugins. If no argument is given, plugins are loaded via
66
+ # PluginList#by_precedence.
67
+ #
68
+ # This method is called by the engines-supplied plugin testing rake tasks
69
+ def self.setup_plugin_fixtures(plugins=Rails.plugins.by_precedence)
70
+
71
+ # Copy all plugin fixtures, and then the application fixtures, into this directory
72
+ plugins.each do |plugin|
73
+ plugin_fixtures_directory = File.join(plugin.root, "test", "fixtures")
74
+ if File.directory?(plugin_fixtures_directory)
75
+ Engines.mirror_files_from(plugin_fixtures_directory, self.temporary_fixtures_directory)
76
+ end
77
+ end
78
+ Engines.mirror_files_from(File.join(RAILS_ROOT, "test", "fixtures"),
79
+ self.temporary_fixtures_directory)
80
+ end
81
+
82
+ # Sets the fixture path used by Test::Unit::TestCase to the temporary
83
+ # directory which contains all plugin fixtures.
84
+ def self.set_fixture_path
85
+ Test::Unit::TestCase.fixture_path = self.temporary_fixtures_directory
86
+ $LOAD_PATH.unshift self.temporary_fixtures_directory
87
+ end
88
+ end