public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
Added app/[models|controllers|helpers] to the load path for plugins that has an 
app directory (go engines ;)) [DHH]
dhh (author)
Wed Nov 26 05:41:20 -0800 2008
commit  63d8f56774dcb1ea601928c3eb6c119d359fae10
tree    599aa9a3307d3f3516d051532c768724b967114b
parent  133c349b0af1c46d26f83c19e6b583062db931e4
...
1
2
 
 
3
4
5
...
1
2
3
4
5
6
7
0
@@ -1,5 +1,7 @@
0
 *2.3.0 [Edge]*
0
 
0
+* Added app/[models|controllers|helpers] to the load path for plugins that has an app directory (go engines ;)) [DHH]
0
+
0
 * Add config.preload_frameworks to load all frameworks at startup. Default to false so Rails autoloads itself as it's used. Turn this on for Passenger and JRuby. Also turned on by config.threadsafe!  [Jeremy Kemper]
0
 
0
 * Add a rake task to generate dispatchers : rake rails:generate_dispatchers [Pratik]
...
28
29
30
31
 
32
33
34
35
36
37
 
 
 
 
 
38
39
40
...
68
69
70
71
 
 
 
 
 
 
 
 
 
 
72
73
74
...
86
87
88
 
 
 
 
 
89
90
91
...
94
95
96
 
97
98
99
...
28
29
30
 
31
32
33
34
35
36
 
37
38
39
40
41
42
43
44
...
72
73
74
 
75
76
77
78
79
80
81
82
83
84
85
86
87
...
99
100
101
102
103
104
105
106
107
108
109
...
112
113
114
115
116
117
118
0
@@ -28,13 +28,17 @@ module Rails
0
     end
0
     
0
     def valid?
0
-      File.directory?(directory) && (has_lib_directory? || has_init_file?)
0
+      File.directory?(directory) && (has_app_directory? || has_lib_directory? || has_init_file?)
0
     end
0
   
0
     # Returns a list of paths this plugin wishes to make available in <tt>$LOAD_PATH</tt>.
0
     def load_paths
0
       report_nonexistant_or_empty_plugin! unless valid?
0
-      has_lib_directory? ? [lib_path] : []
0
+      
0
+      returning [] do |load_paths|
0
+        load_paths << lib_path  if has_lib_directory?
0
+        load_paths << app_paths if has_app_directory?
0
+      end.flatten
0
     end
0
 
0
     # Evaluates a plugin's init.rb file.
0
@@ -68,7 +72,16 @@ module Rails
0
 
0
       def report_nonexistant_or_empty_plugin!
0
         raise LoadError, "Can not find the plugin named: #{name}"
0
-      end      
0
+      end
0
+
0
+      
0
+      def app_paths
0
+        [ 
0
+          File.join(directory, 'app', 'models'), 
0
+          File.join(directory, 'app', 'controllers'),
0
+          File.join(directory, 'app', 'helpers')
0
+        ]
0
+      end
0
     
0
       def lib_path
0
         File.join(directory, 'lib')
0
@@ -86,6 +99,11 @@ module Rails
0
         File.file?(gem_init_path) ? gem_init_path : classic_init_path
0
       end
0
 
0
+
0
+      def has_app_directory?
0
+        File.directory?(File.join(directory, 'app'))
0
+      end
0
+
0
       def has_lib_directory?
0
         File.directory?(lib_path)
0
       end
0
@@ -94,6 +112,7 @@ module Rails
0
         File.file?(init_path)
0
       end
0
 
0
+
0
       def evaluate_init_rb(initializer)
0
         if has_init_file?
0
           silence_warnings do
...
33
34
35
 
36
37
38
...
45
46
47
48
 
 
 
49
50
51
52
53
 
54
55
56
...
59
60
61
62
 
63
64
 
65
66
67
...
33
34
35
36
37
38
39
...
46
47
48
 
49
50
51
52
53
54
55
56
57
58
59
60
...
63
64
65
 
66
67
 
68
69
70
71
0
@@ -33,6 +33,7 @@ module Rails
0
           plugin.load(initializer)
0
           register_plugin_as_loaded(plugin)
0
         end
0
+
0
         ensure_all_registered_plugins_are_loaded!
0
       end
0
       
0
@@ -45,12 +46,15 @@ module Rails
0
         plugins.each do |plugin|
0
           plugin.load_paths.each do |path|
0
             $LOAD_PATH.insert(application_lib_index + 1, path)
0
-            ActiveSupport::Dependencies.load_paths      << path
0
+
0
+            ActiveSupport::Dependencies.load_paths << path
0
+
0
             unless Rails.configuration.reload_plugins?
0
               ActiveSupport::Dependencies.load_once_paths << path
0
             end
0
           end
0
         end
0
+
0
         $LOAD_PATH.uniq!
0
       end      
0
       
0
@@ -59,9 +63,9 @@ module Rails
0
         # The locate_plugins method uses each class in config.plugin_locators to
0
         # find the set of all plugins available to this Rails application.
0
         def locate_plugins
0
-          configuration.plugin_locators.map { |locator|
0
+          configuration.plugin_locators.map do |locator|
0
             locator.new(initializer).plugins
0
-          }.flatten
0
+          end.flatten
0
           # TODO: sorting based on config.plugins
0
         end
0
 
...
209
210
211
212
 
213
214
215
...
217
218
219
220
 
221
222
223
...
225
226
227
228
 
229
230
231
...
299
300
301
302
 
303
304
305
...
209
210
211
 
212
213
214
215
...
217
218
219
 
220
221
222
223
...
225
226
227
 
228
229
230
231
...
299
300
301
 
302
303
304
305
0
@@ -209,7 +209,7 @@ uses_mocha "Initializer plugin loading tests" do
0
     def test_all_plugins_are_loaded_when_registered_plugin_list_is_untouched
0
       failure_tip = "It's likely someone has added a new plugin fixture without updating this list"
0
       load_plugins!
0
-      assert_plugins [:a, :acts_as_chunky_bacon, :gemlike, :plugin_with_no_lib_dir, :stubby], @initializer.loaded_plugins, failure_tip
0
+      assert_plugins [:a, :acts_as_chunky_bacon, :engine, :gemlike, :plugin_with_no_lib_dir, :stubby], @initializer.loaded_plugins, failure_tip
0
     end
0
 
0
     def test_all_plugins_loaded_when_all_is_used
0
@@ -217,7 +217,7 @@ uses_mocha "Initializer plugin loading tests" do
0
       only_load_the_following_plugins! plugin_names
0
       load_plugins!
0
       failure_tip = "It's likely someone has added a new plugin fixture without updating this list"
0
-      assert_plugins [:stubby, :acts_as_chunky_bacon, :a, :gemlike, :plugin_with_no_lib_dir], @initializer.loaded_plugins, failure_tip
0
+      assert_plugins [:stubby, :acts_as_chunky_bacon, :a, :engine, :gemlike, :plugin_with_no_lib_dir], @initializer.loaded_plugins, failure_tip
0
     end
0
 
0
     def test_all_plugins_loaded_after_all
0
@@ -225,7 +225,7 @@ uses_mocha "Initializer plugin loading tests" do
0
       only_load_the_following_plugins! plugin_names
0
       load_plugins!
0
       failure_tip = "It's likely someone has added a new plugin fixture without updating this list"
0
-      assert_plugins [:stubby, :a, :gemlike, :plugin_with_no_lib_dir, :acts_as_chunky_bacon], @initializer.loaded_plugins, failure_tip
0
+      assert_plugins [:stubby, :a, :engine, :gemlike, :plugin_with_no_lib_dir, :acts_as_chunky_bacon], @initializer.loaded_plugins, failure_tip
0
     end
0
 
0
     def test_plugin_names_may_be_strings
0
@@ -299,7 +299,7 @@ uses_mocha 'i18n settings' do
0
        File.expand_path("./test/../../activesupport/lib/active_support/locale/en.yml"),
0
        File.expand_path("./test/../../actionpack/lib/action_view/locale/en.yml"),
0
        "my/test/locale.yml",
0
-       "my/other/locale.yml" ], I18n.load_path
0
+       "my/other/locale.yml" ], I18n.load_path.collect { |path| path =~ /^\./ ? File.expand_path(path) : path }
0
     end
0
     
0
     def test_setting_another_default_locale
...
48
49
50
51
 
52
53
54
55
 
56
57
58
59
60
 
61
62
63
...
74
75
76
77
 
78
79
80
81
82
 
83
84
85
86
87
 
88
89
90
...
112
113
114
 
 
 
 
 
 
 
 
 
 
 
 
 
115
116
117
...
48
49
50
 
51
52
53
54
 
55
56
57
58
59
 
60
61
62
63
...
74
75
76
 
77
78
79
80
81
 
82
83
84
85
86
 
87
88
89
90
...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
0
@@ -48,16 +48,16 @@ uses_mocha "Plugin Loader Tests" do
0
     end
0
 
0
     def test_should_find_all_availble_plugins_and_return_as_all_plugins
0
-      assert_plugins [:stubby, :plugin_with_no_lib_dir, :gemlike, :acts_as_chunky_bacon, :a], @loader.all_plugins.reverse, @failure_tip
0
+      assert_plugins [ :engine, :stubby, :plugin_with_no_lib_dir, :gemlike, :acts_as_chunky_bacon, :a], @loader.all_plugins.reverse, @failure_tip
0
     end
0
 
0
     def test_should_return_all_plugins_as_plugins_when_registered_plugin_list_is_untouched
0
-      assert_plugins [:a, :acts_as_chunky_bacon, :gemlike, :plugin_with_no_lib_dir, :stubby], @loader.plugins, @failure_tip
0
+      assert_plugins [:a, :acts_as_chunky_bacon, :engine, :gemlike, :plugin_with_no_lib_dir, :stubby], @loader.plugins, @failure_tip
0
     end
0
 
0
     def test_should_return_all_plugins_as_plugins_when_registered_plugin_list_is_nil
0
       @configuration.plugins = nil
0
-      assert_plugins [:a, :acts_as_chunky_bacon, :gemlike, :plugin_with_no_lib_dir, :stubby], @loader.plugins, @failure_tip
0
+      assert_plugins [:a, :acts_as_chunky_bacon, :engine, :gemlike, :plugin_with_no_lib_dir, :stubby], @loader.plugins, @failure_tip
0
     end
0
 
0
     def test_should_return_specific_plugins_named_in_config_plugins_array_if_set
0
@@ -74,17 +74,17 @@ uses_mocha "Plugin Loader Tests" do
0
 
0
     def test_should_load_all_plugins_in_natural_order_when_all_is_used
0
       only_load_the_following_plugins! [:all]
0
-      assert_plugins [:a, :acts_as_chunky_bacon, :gemlike, :plugin_with_no_lib_dir, :stubby], @loader.plugins, @failure_tip
0
+      assert_plugins [:a, :acts_as_chunky_bacon, :engine, :gemlike, :plugin_with_no_lib_dir, :stubby], @loader.plugins, @failure_tip
0
     end
0
 
0
     def test_should_load_specified_plugins_in_order_and_then_all_remaining_plugins_when_all_is_used
0
       only_load_the_following_plugins! [:stubby, :acts_as_chunky_bacon, :all]
0
-      assert_plugins [:stubby, :acts_as_chunky_bacon, :a, :gemlike, :plugin_with_no_lib_dir], @loader.plugins, @failure_tip
0
+      assert_plugins [:stubby, :acts_as_chunky_bacon, :a, :engine, :gemlike, :plugin_with_no_lib_dir], @loader.plugins, @failure_tip
0
     end
0
 
0
     def test_should_be_able_to_specify_loading_of_plugins_loaded_after_all
0
       only_load_the_following_plugins!  [:stubby, :all, :acts_as_chunky_bacon]
0
-      assert_plugins [:stubby, :a, :gemlike, :plugin_with_no_lib_dir, :acts_as_chunky_bacon], @loader.plugins, @failure_tip
0
+      assert_plugins [:stubby, :a, :engine, :gemlike, :plugin_with_no_lib_dir, :acts_as_chunky_bacon], @loader.plugins, @failure_tip
0
     end
0
 
0
     def test_should_accept_plugin_names_given_as_strings
0
@@ -112,6 +112,19 @@ uses_mocha "Plugin Loader Tests" do
0
       assert ActiveSupport::Dependencies.load_paths.include?(File.join(plugin_fixture_path('default/acts/acts_as_chunky_bacon'), 'lib'))
0
     end
0
 
0
+
0
+    def test_should_add_engine_load_paths_to_Dependencies_load_paths
0
+      only_load_the_following_plugins! [:engine]
0
+
0
+      @loader.add_plugin_load_paths
0
+
0
+      %w( models controllers helpers ).each do |app_part|
0
+        assert ActiveSupport::Dependencies.load_paths.include?(
0
+          File.join(plugin_fixture_path('engines/engine'), 'app', app_part)
0
+        ), "Couldn't find #{app_part} in load path"
0
+      end
0
+    end
0
+
0
     def test_should_add_plugin_load_paths_to_Dependencies_load_once_paths
0
       only_load_the_following_plugins! [:stubby, :acts_as_chunky_bacon]
0
 

Comments

svenfuchs Wed Nov 26 07:22:18 -0800 2008

wohoooooo :)

lazyatom Wed Nov 26 07:25:36 -0800 2008

Nice ;)

zargony Wed Nov 26 07:36:20 -0800 2008

Great. I wonder if/how an engine plugin can add routes.

Virtuaffinity Wed Nov 26 07:37:18 -0800 2008

Good to see this making it into core, nice stuff!

tekin Wed Nov 26 07:38:03 -0800 2008

hallelujah!

DefV Wed Nov 26 07:38:08 -0800 2008

@zargony 16:28 :: DHH:: It gets better shortly ;) 16:28 :: DHH:: almost have config/routes.rb working for plugins too

yaroslav Wed Nov 26 07:39:54 -0800 2008

yay!

maxlapshin Wed Nov 26 07:58:39 -0800 2008

Cool!!! Waiting for Django-like apps!

andrewroth Wed Nov 26 08:43:56 -0800 2008

I’m happy to see this change, but I am curious—what made you change your mind?

matthewrudy Wed Nov 26 08:52:13 -0800 2008

need to find a good way to extend routing from a plugin.

lazyatom Wed Nov 26 08:57:33 -0800 2008

@matthewrudy: it’s being taken care of.

dpickett Wed Nov 26 09:33:49 -0800 2008

how would migrations work for models like this? they’d probably still have to be written through a generator, right?

boblmartens Wed Nov 26 11:03:09 -0800 2008

If I knew exactly what this did, I’d be excited.

ioquatix Wed Nov 26 11:28:48 -0800 2008

DHH: How does this integrate into GEM plugins? GEMs have a directory called “rails” so shouldn’t “app” and so on be in that directory to keep things in the correct namespace? How about rake tasks? You might want to check out my fork of engines which solves these problems and others: http://github.com/ioquatix/engines/tree/master

stephankaag Wed Nov 26 11:31:11 -0800 2008

How about views in a plugin?

Roman2K Wed Nov 26 14:53:04 -0800 2008

+1 for <plugin-root>/rails/app instead of <plugin-root>/app (following ioquatix’s comment above).

matthewrudy Wed Nov 26 15:52:47 -0800 2008

you’re on top of everything @lazyatom.

binarylogic Wed Nov 26 16:18:44 -0800 2008

I thought rails was starting to move away from plugins and more towards gems. That seems to make the most sense, since gems have a versioning / update system, can require dependencies, etc. Plugins seem somewhat redundant to the gems system. That being said, it would be nice to do something like this for gems and encourage people to write gems instead of plugins. Now that github makes creating a gem so easy, it seems like it would actually be easier to do it this way.

oboxodo Wed Nov 26 17:10:20 -0800 2008

+1 on engines-like gems support, still supporting rails plugins, but discouraging them.

m3talsmith Wed Nov 26 18:45:25 -0800 2008

-1 for /rails/app instead of /app +1 for bringing engines back

I love having all of the above and the gem dependency options open. I love where rails is headed. Keep it up core.

ioquatix Sat Nov 29 02:49:25 -0800 2008

m3talsmith: can you clarify your -1 comment? Since everything else for rails is in a subdirectory, why not put app there as well. Its much cleaner overall.

m3talsmith Sat Nov 29 06:30:23 -0800 2008

@ioquatix:

I’m more concerned about keeping a pure directory structure in the vendor/plugins/your_plugin_or_engine_name area. When I made the minus comment I hadn’t was in a rush on my way out the door. I overlooked the GEM’s part of the comment. Given that I take my -1 back because it does make sense to keep it in the same namespace. So ….

+1 for /rails/app for the GEMS directory -2 for m3talsmith firing off a comment on the run.
railsdog Sat Nov 29 17:33:33 -0800 2008

Will this be like extensions in Radiant or Spree? Both of these projects already support views, controllers, routes, migrations, etc. in your extensions.

xtoddx Wed Dec 03 16:18:41 -0800 2008

Is there an easy way to run migrations from plugins? Maybe being able to set the schema migrations table name from within the migrations would be enough. I’ve been doing it with monkeypatching and a custom rake task so far.

dhh Thu Dec 04 06:01:04 -0800 2008

xtoddx, we’re working on getting a good story for both migrations and files in public in before this is released.