Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

root/tools/capistrano/lib/capistrano/role.rb

Revision 8905, 3.1 kB (checked in by minam, 10 months ago)

Dynamic roles (closes #11107, thanks for the awesome patch!)

Line 
1
2 module Capistrano
3   class Role
4     include Enumerable
5
6     def initialize(*list)
7       @static_servers = []
8       @dynamic_servers = []
9       push(*list)
10     end
11
12     def each(&block)
13       servers.each &block
14     end
15
16     def push(*list)
17       options = list.last.is_a?(Hash) ? list.pop : {}
18       list.each do |item|
19         if item.respond_to?(:call)
20           @dynamic_servers << DynamicServerList.new(item, options)
21         else
22           @static_servers << self.class.wrap_server(item, options)
23         end
24       end
25     end
26     alias_method :<<, :push
27
28     def servers
29       @static_servers + dynamic_servers
30     end
31     alias_method :to_ary, :servers
32
33     def empty?
34       servers.empty?
35     end
36
37     # Resets the cache, so that proc values may be recalculated.
38     # There should be a command in Configuration::Roles to do this,
39     # but I haven't needed it yet, and I'm not sure yet
40     # what to call that command. Suggestions?
41     def reset!
42       @dynamic_servers.each { |item| item.reset! }
43     end
44
45     # Clears everything. I still thing this should be 'clear!', but that's not
46     # the way Array does it.
47     def clear
48       @dynamic_servers.clear
49       @static_servers.clear
50     end
51
52     # Mostly for documentation purposes. Doesn't seem to do anything.
53     protected
54
55     # This is the combination of a block, a hash of options, and a cached value.
56     # It is protected because it is an implementation detail -- the original
57     # implementation was two lists (blocks and cached results of calling them).
58     class DynamicServerList
59       def initialize (block, options)
60         @block = block
61         @options = options
62         @cached = []
63         @is_cached = false
64       end
65
66       # Convert to a list of ServerDefinitions
67       def to_ary
68         unless @is_cached
69           @cached = Role::wrap_list(@block.call(@options), @options)
70           @is_cached = true
71         end
72         @cached
73       end
74
75       # Clear the cached value
76       def reset!
77         @cached.clear
78         @is_cached = false
79       end
80     end
81
82     # Attribute reader for the cached results of executing the blocks in turn
83     def dynamic_servers
84       @dynamic_servers.inject([]) { |list, item| list.concat item }
85     end
86
87     # Wraps a string in a ServerDefinition, if it isn't already.
88     # This and wrap_list should probably go in ServerDefinition in some form.
89     def self.wrap_server (item, options)
90       item.is_a?(ServerDefinition) ? item : ServerDefinition.new(item, options)
91     end
92
93     # Turns a list, or something resembling a list, into a properly-formatted
94     # ServerDefinition list. Keep an eye on this one -- it's entirely too
95     # magical for its own good. In particular, if ServerDefinition ever inherits
96     # from Array, this will break.
97     def self.wrap_list (*list)
98       options = list.last.is_a?(Hash) ? list.pop : {}
99       if list.length == 1
100         if list.first.nil?
101           return []
102         elsif list.first.is_a?(Array)
103           list = list.first
104         end
105       end
106       options.merge! list.pop if list.last.is_a?(Hash)
107       list.map do |item|
108         self.wrap_server item, options
109       end
110     end
111   end
112 end
Note: See TracBrowser for help on using the browser.