Merged updates from trunk into stable branch
[feedcatcher.git] / vendor / rails / railties / lib / rails / plugin.rb
1 module Rails
2 # The Plugin class should be an object which provides the following methods:
3 #
4 # * +name+ - Used during initialisation to order the plugin (based on name and
5 # the contents of <tt>config.plugins</tt>).
6 # * +valid?+ - Returns true if this plugin can be loaded.
7 # * +load_paths+ - Each path within the returned array will be added to the <tt>$LOAD_PATH</tt>.
8 # * +load+ - Finally 'load' the plugin.
9 #
10 # These methods are expected by the Rails::Plugin::Locator and Rails::Plugin::Loader classes.
11 # The default implementation returns the <tt>lib</tt> directory as its <tt>load_paths</tt>,
12 # and evaluates <tt>init.rb</tt> when <tt>load</tt> is called.
13 #
14 # You can also inspect the about.yml data programmatically:
15 #
16 # plugin = Rails::Plugin.new(path_to_my_plugin)
17 # plugin.about["author"] # => "James Adam"
18 # plugin.about["url"] # => "http://interblah.net"
19 class Plugin
20 include Comparable
21
22 attr_reader :directory, :name
23
24 def initialize(directory)
25 @directory = directory
26 @name = File.basename(@directory) rescue nil
27 @loaded = false
28 end
29
30 def valid?
31 File.directory?(directory) && (has_app_directory? || has_lib_directory? || has_init_file?)
32 end
33
34 # Returns a list of paths this plugin wishes to make available in <tt>$LOAD_PATH</tt>.
35 def load_paths
36 report_nonexistant_or_empty_plugin! unless valid?
37
38 returning [] do |load_paths|
39 load_paths << lib_path if has_lib_directory?
40 load_paths << app_paths if has_app_directory?
41 end.flatten
42 end
43
44 # Evaluates a plugin's init.rb file.
45 def load(initializer)
46 return if loaded?
47 report_nonexistant_or_empty_plugin! unless valid?
48 evaluate_init_rb(initializer)
49 @loaded = true
50 end
51
52 def loaded?
53 @loaded
54 end
55
56 def <=>(other_plugin)
57 name <=> other_plugin.name
58 end
59
60 def about
61 @about ||= load_about_information
62 end
63
64 # Engines are plugins with an app/ directory.
65 def engine?
66 has_app_directory?
67 end
68
69 # Returns true if the engine ships with a routing file
70 def routed?
71 File.exist?(routing_file)
72 end
73
74
75 def view_path
76 File.join(directory, 'app', 'views')
77 end
78
79 def controller_path
80 File.join(directory, 'app', 'controllers')
81 end
82
83 def metal_path
84 File.join(directory, 'app', 'metal')
85 end
86
87 def routing_file
88 File.join(directory, 'config', 'routes.rb')
89 end
90
91
92 private
93 def load_about_information
94 about_yml_path = File.join(@directory, "about.yml")
95 parsed_yml = File.exist?(about_yml_path) ? YAML.load(File.read(about_yml_path)) : {}
96 parsed_yml || {}
97 rescue Exception
98 {}
99 end
100
101 def report_nonexistant_or_empty_plugin!
102 raise LoadError, "Can not find the plugin named: #{name}"
103 end
104
105
106 def app_paths
107 [ File.join(directory, 'app', 'models'), File.join(directory, 'app', 'helpers'), controller_path, metal_path ]
108 end
109
110 def lib_path
111 File.join(directory, 'lib')
112 end
113
114 def classic_init_path
115 File.join(directory, 'init.rb')
116 end
117
118 def gem_init_path
119 File.join(directory, 'rails', 'init.rb')
120 end
121
122 def init_path
123 File.file?(gem_init_path) ? gem_init_path : classic_init_path
124 end
125
126
127 def has_app_directory?
128 File.directory?(File.join(directory, 'app'))
129 end
130
131 def has_lib_directory?
132 File.directory?(lib_path)
133 end
134
135 def has_init_file?
136 File.file?(init_path)
137 end
138
139
140 def evaluate_init_rb(initializer)
141 if has_init_file?
142 silence_warnings do
143 # Allow plugins to reference the current configuration object
144 config = initializer.configuration
145
146 eval(IO.read(init_path), binding, init_path)
147 end
148 end
149 end
150 end
151
152 # This Plugin subclass represents a Gem plugin. Although RubyGems has already
153 # taken care of $LOAD_PATHs, it exposes its load_paths to add them
154 # to Dependencies.load_paths.
155 class GemPlugin < Plugin
156 # Initialize this plugin from a Gem::Specification.
157 def initialize(spec, gem)
158 directory = spec.full_gem_path
159 super(directory)
160 @name = spec.name
161 end
162
163 def init_path
164 File.join(directory, 'rails', 'init.rb')
165 end
166 end
167 end