parlement 0.10 → 0.11

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