davidlee-state-fu 0.3.1 → 0.10.0

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 (90) hide show
  1. data/README.textile +124 -34
  2. data/Rakefile +36 -30
  3. data/lib/no_stdout.rb +1 -1
  4. data/lib/state-fu.rb +9 -8
  5. data/lib/state_fu/active_support_lite/array/access.rb +12 -5
  6. data/lib/state_fu/active_support_lite/array/conversions.rb +10 -4
  7. data/lib/state_fu/active_support_lite/array/extract_options.rb +5 -4
  8. data/lib/state_fu/active_support_lite/array/grouping.rb +7 -4
  9. data/lib/state_fu/active_support_lite/array/random_access.rb +4 -3
  10. data/lib/state_fu/active_support_lite/array/wrapper.rb +4 -3
  11. data/lib/state_fu/active_support_lite/array.rb +3 -1
  12. data/lib/state_fu/active_support_lite/blank.rb +18 -9
  13. data/lib/state_fu/active_support_lite/cattr_reader.rb +4 -1
  14. data/lib/state_fu/active_support_lite/keys.rb +8 -3
  15. data/lib/state_fu/active_support_lite/misc.rb +6 -4
  16. data/lib/state_fu/active_support_lite/module/delegation.rb +130 -0
  17. data/lib/state_fu/active_support_lite/module.rb +1 -0
  18. data/lib/state_fu/active_support_lite/object.rb +5 -2
  19. data/lib/state_fu/active_support_lite/string.rb +6 -1
  20. data/lib/state_fu/active_support_lite/symbol.rb +2 -1
  21. data/lib/state_fu/applicable.rb +41 -0
  22. data/lib/state_fu/{helper.rb → arrays.rb} +45 -121
  23. data/lib/state_fu/binding.rb +136 -159
  24. data/lib/state_fu/core_ext.rb +78 -10
  25. data/lib/state_fu/event.rb +112 -48
  26. data/lib/state_fu/exceptions.rb +80 -34
  27. data/lib/state_fu/executioner.rb +149 -0
  28. data/lib/state_fu/has_options.rb +16 -0
  29. data/lib/state_fu/hooks.rb +21 -16
  30. data/lib/state_fu/interface.rb +80 -83
  31. data/lib/state_fu/lathe.rb +361 -148
  32. data/lib/state_fu/logger.rb +122 -45
  33. data/lib/state_fu/machine.rb +60 -32
  34. data/lib/state_fu/method_factory.rb +180 -72
  35. data/lib/state_fu/methodical.rb +17 -0
  36. data/lib/state_fu/persistence/active_record.rb +6 -1
  37. data/lib/state_fu/persistence/attribute.rb +1 -0
  38. data/lib/state_fu/persistence/base.rb +8 -6
  39. data/lib/state_fu/persistence.rb +94 -23
  40. data/lib/state_fu/sprocket.rb +26 -11
  41. data/lib/state_fu/state.rb +8 -27
  42. data/lib/state_fu/transition.rb +207 -98
  43. data/lib/state_fu/transition_query.rb +214 -0
  44. data/lib/state_fu.rb +1 -0
  45. data/lib/tasks/spec_last.rake +46 -0
  46. data/lib/tasks/state_fu.rake +57 -0
  47. data/lib/vizier.rb +61 -61
  48. data/spec/custom_formatter.rb +49 -0
  49. data/spec/features/binding_and_transition_helper_mixin_spec.rb +2 -2
  50. data/spec/features/method_missing_only_once_spec.rb +28 -0
  51. data/spec/features/not_requirements_spec.rb +83 -46
  52. data/spec/features/plotter_spec.rb +97 -0
  53. data/spec/features/shared_log_spec.rb +7 -0
  54. data/spec/features/singleton_machine_spec.rb +39 -0
  55. data/spec/features/state_and_array_options_accessor_spec.rb +1 -1
  56. data/spec/features/{transition_boolean_comparison.rb → transition_boolean_comparison_spec.rb} +29 -18
  57. data/spec/helper.rb +6 -117
  58. data/spec/integration/active_record_persistence_spec.rb +18 -4
  59. data/spec/integration/binding_extension_spec.rb +1 -1
  60. data/spec/integration/class_accessor_spec.rb +49 -59
  61. data/spec/integration/event_definition_spec.rb +20 -20
  62. data/spec/integration/example_01_document_spec.rb +13 -8
  63. data/spec/integration/example_02_string_spec.rb +3 -2
  64. data/spec/integration/instance_accessor_spec.rb +16 -19
  65. data/spec/integration/lathe_extension_spec.rb +2 -2
  66. data/spec/integration/machine_duplication_spec.rb +59 -37
  67. data/spec/integration/relaxdb_persistence_spec.rb +6 -3
  68. data/spec/integration/requirement_reflection_spec.rb +66 -57
  69. data/spec/integration/state_definition_spec.rb +72 -66
  70. data/spec/integration/transition_spec.rb +169 -173
  71. data/spec/spec.opts +5 -3
  72. data/spec/spec_helper.rb +132 -0
  73. data/spec/state_fu_spec.rb +870 -0
  74. data/spec/units/binding_spec.rb +33 -22
  75. data/spec/units/event_spec.rb +3 -22
  76. data/spec/units/exceptions_spec.rb +7 -0
  77. data/spec/units/lathe_spec.rb +7 -7
  78. data/spec/units/machine_spec.rb +67 -75
  79. data/spec/units/method_factory_spec.rb +55 -48
  80. data/spec/units/sprocket_spec.rb +5 -7
  81. data/spec/units/state_spec.rb +33 -24
  82. metadata +31 -19
  83. data/lib/state_fu/active_support_lite/inheritable_attributes.rb +0 -1
  84. data/lib/state_fu/fu_space.rb +0 -51
  85. data/lib/state_fu/mock_transition.rb +0 -38
  86. data/spec/BDD/plotter_spec.rb +0 -115
  87. data/spec/integration/dynamic_requirement_spec.rb +0 -160
  88. data/spec/integration/ex_machine_for_accounts_spec.rb +0 -79
  89. data/spec/integration/sanity_spec.rb +0 -31
  90. data/spec/units/fu_space_spec.rb +0 -95
data/README.textile CHANGED
@@ -4,25 +4,35 @@ h2. What is it?
4
4
 
5
5
  State-Fu is:
6
6
 
7
- * an unique toolkit for state-oriented programming
7
+ * a generalized, extensible framework for state-oriented,
8
+ event-driven programming in Ruby.
8
9
 
9
- * a rich DSL for describing workflows, rules engines and behaviour
10
+ * a rich DSL for describing workflows, rules engines, behaviours and
11
+ processes
10
12
 
11
- * something you've probably wanted for a long time but didn't know it
13
+ * useful both as a Rails plugin, and in standalone ruby programs
14
+ without any additional dependencies.
12
15
 
13
16
  It lets you describe:
14
17
 
15
18
  * series of discrete states
16
19
 
17
- * events which can change the current state
20
+ * events which allow transitions to occur between states
18
21
 
19
- * rules about when these events can occur
22
+ * rules (requirements) about when these transitions can occur
20
23
 
21
24
  * behaviours which occur when they do
22
25
 
26
+ Which adds up to a surprisingly useful way to skin a lot of
27
+ problems
28
+
23
29
  Other libraries exist for ruby which do some or all of these
24
30
  things. "What's different about State-Fu?", you may ask.
25
31
 
32
+ h2. Why StateFu is not your grandmother's state machine
33
+
34
+ h3. Flippant answer:
35
+
26
36
  Those libraries you've played with are toys. They're made of
27
37
  plastic. State-Fu is forged from a reassuringly dense but
28
38
  unidentifiable metal which comes only from the rarest of meteorites,
@@ -61,6 +71,13 @@ It is also delightfully elegant and easy to use for simple things:
61
71
  event :delete, :from => :ALL, :to => :deleted do
62
72
  execute :destroy
63
73
  end
74
+
75
+ # save all states once transition is complete.
76
+ # this wants to be last, as it iterates over each state which is
77
+ # already defined.
78
+ states do
79
+ accepted { object.save! }
80
+ end
64
81
  end
65
82
  end
66
83
 
@@ -80,18 +97,17 @@ It is also delightfully elegant and easy to use for simple things:
80
97
 
81
98
  </code></pre>
82
99
 
83
- A few of the features which set State-Fu apart for more ambitious work are:
100
+ h3. Feature Comparison and Detailed Answer
84
101
 
85
- * a lovely, simple and flexible API gives you plenty of choices
102
+ A few of the features which set State-Fu apart for more ambitious work are:
86
103
 
87
- * use an ActiveRecord field for state persistence, or just an
88
- attribute - or use both, on the same class, for different workflows
104
+ * a lovely, simple and flexible API gives you plenty of choices about
105
+ how to describe your problem domain.
89
106
 
90
- * customising the persistence mechanism (eg to use a Rails session,
91
- or a text file) is as easy as defining a getter and setter method
92
-
93
- * define any number of workflows on the same object / model, or re-use
94
- them across multiple classes
107
+ * define any number of workflows on the same object / model;
108
+ workflows (Machines) can be entirely separate, or interact with
109
+ each other. Re-use machines across multiple classes, serialize them
110
+ to a database, or build them on the fly.
95
111
 
96
112
  * events can transition from / to any number of states
97
113
 
@@ -101,8 +117,8 @@ A few of the features which set State-Fu apart for more ambitious work are:
101
117
  state machine itself
102
118
 
103
119
  * requirements determine at runtime whether a particular state
104
- transition can occur, and if not, can tell a user what they must do
105
- to satisfy the requirements.
120
+ transition can occur, and if not, can tell a user (or developer)
121
+ what they must do to satisfy the requirements.
106
122
 
107
123
  * requirement failure messages can be generated at runtime, making
108
124
  use of whatever application and state-machine context they need
@@ -111,23 +127,51 @@ A few of the features which set State-Fu apart for more ambitious work are:
111
127
  determine why, and where from
112
128
 
113
129
  * in every event hook, requirement filter, and other method calls,
114
- you have complete and tidy access to your classes, the state
115
- machine, and the transition context. Use real ruby code anywhere,
116
- without breathing through a straw!
130
+ you have complete and consistent access to your classes, its
131
+ StateFu::Machines, and any Transition context. Use real ruby code
132
+ anywhere, without breathing through a straw!
133
+
134
+ * extend State-Fu (with Lathe#helper) Binding and Transition
135
+ instances for your Machine to define your a DSL customized for your
136
+ problem domain, and to keep your class definitions clean. Helper
137
+ methods have easy access to all the context associated with your
138
+ object instance, its StateFu::Machines and any Transition in
139
+ progress.
117
140
 
118
- * extend State-Fu with helper modules, or raw blocks of ruby code, to
119
- model your problem domain - globally, per state machine / workflow,
120
- or for an individual event transition
141
+ * extend a State-Fu Lathe (with Lathe#tool) to keep your Machine
142
+ definitions DRY
121
143
 
122
144
  * store arbitrary meta-data on any component of State-Fu - a simple
123
- but extremely powerful tool for integration
145
+ but extremely powerful tool for integration with almost anything.
124
146
 
125
147
  * designed for transparency, introspection and ease of debugging,
126
148
  which means a dynamic, powerful system you can actually use without
127
- headaches
149
+ headaches.
150
+
151
+ * flexible and helpful logging out of the box - will use the Rails
152
+ logger if you're in a Rails project, or standalone logging to
153
+ STDOUT or a file. Configurable loglevel and message prefixes help
154
+ StateFu be a good citizen in a shared application log.
128
155
 
129
156
  * magically generate diagrams of state machines / workflows with graphviz
130
157
 
158
+ * "magically" use an ActiveRecord field for state persistence, or just an
159
+ attribute - or use both, on the same class, for different
160
+ workflows. If an ActiveRecord field exists for a machine's
161
+ field_name (by default, the machine's name suffixed with '_field';
162
+ the default machine name is 'state_fu', so if you don't explicitly
163
+ name a machine it will look for 'state_fu_field' in your
164
+ ActiveRecord columns (if ActiveRecord is included) and use
165
+ that. Otherwise, an attr_accessor will be used (and created, if
166
+ necessary).
167
+
168
+ * customising the persistence mechanism (eg to use a Rails session,
169
+ or a text file, or your choice of ORM) is usually as easy as
170
+ defining a getter and setter method for the persistence field, and
171
+ a rule about when to use it. If you want to use StateFu with a
172
+ persistence mechanism which is not yet supported, I'd like to hear
173
+ about it.
174
+
131
175
  * fast, lightweight and useful enough to use in any ruby
132
176
  project - works with Rails but does not require it.
133
177
 
@@ -146,6 +190,32 @@ I'd also like to tip my hat at John Barnette, who's own
146
190
  (coincidentally named) Stateful set a very high standard with an
147
191
  exceptionally elegant API.
148
192
 
193
+ h3. StateFu is not a complete BPM (Business Process Management) platform
194
+
195
+ It's worth noting that StateFu is at it's core a state machine, which
196
+ strives to be powerful enough to be able to drive many kinds of
197
+ application behaviour.
198
+
199
+ It is not, however, a "proper" workflow engine on par with Ruote. In
200
+ StateFu the basic units with which "workflows" are built are states
201
+ and events; Ruote takes a higher level view, dealing with processes
202
+ and participants. As a result, it's capable of directly implementing
203
+ these design patterns:
204
+
205
+ http://openwferu.rubyforge.org/patterns.html
206
+
207
+ Whereas StateFu cannot, for example, readily model forking / merging
208
+ of processes (nor does it handles scheduling, process management, etc.
209
+
210
+ The author of Ruote, the Ruby Workflow Engine, outlines the difference
211
+ pretty clearly here:
212
+
213
+ http://jmettraux.wordpress.com/2009/07/03/state-machine-workflow-engine/
214
+
215
+ If your application can be described with StateFu, you'll likely find
216
+ it simpler to get running and work with; if not, you may find Ruote,
217
+ or a combination of the two, suits your needs perfectly.
218
+
149
219
  h2. Getting started
150
220
 
151
221
  You can either clone the repository in the usual fashion (eg to
@@ -183,22 +253,42 @@ To install the dependencies for running specs:
183
253
 
184
254
  Now you can simply <code>include StateFu</code> in any class you wish to make stateful.
185
255
 
186
- The spec folder is currently the best source of documentation.
256
+ The spec/ and features/ folders are currently one of the best source
257
+ of documentation. The documentation is gradually evolving to catch up
258
+ with the features, but if you have any questions I'm happy to help you
259
+ get started.
187
260
 
188
- If you have questions, feature request or ideas, please join the "google group":http://groups.google.com/group/state-fu
261
+ If you have questions, feature request or ideas, please join the
262
+ "google group":http://groups.google.com/group/state-fu or send me a
263
+ message on GitHub.
189
264
 
190
- A note about ActiveSupport:
265
+ h3. A note about ActiveSupport
191
266
 
192
267
  StateFu will use ActiveSupport if it is already loaded. If not, it
193
- will load its own (very heavily cut down) 'lite' version. This means
194
- that if you require StateFu *before* other libraries which require
195
- ActiveSupport (e.g. ActiveRecord), you may have to explicitly
196
- <code>require 'activesupport'</code> before loading the dependent
197
- libraries.
268
+ will load its own (heavily trimmed) 'lite' version.
269
+
270
+ In most projects this will behave transparently, but it does mean that
271
+ if you require StateFu *before* other libraries which
272
+ require ActiveSupport (e.g. ActiveRecord), you may have to
273
+ explicitly <code>require 'activesupport'</code> before loading the
274
+ dependent libraries.
275
+
276
+ So if you plan to use ActiveSupport in a stand-alone project with
277
+ StateFu, you should require it before StateFu.
278
+
279
+ h3. Addditional Resources
198
280
 
199
281
  Also see the "issue tracker":http://github.com/davidlee/state-fu/issues
200
282
 
201
283
  And the "build monitor":http://runcoderun.com/davidlee/state-fu/
202
284
 
203
- And the "RDoc":http://rdoc.info/projects/davidlee/state-fu/ , which
204
- needs a bit of love.
285
+ And the "RDoc":http://rdoc.info/projects/davidlee/state-fu
286
+
287
+ h3. Thanks
288
+
289
+ * dsturnbull, for helping w/ a patch to stop an error being raised
290
+ when an activerecord model has no database table
291
+
292
+ * lachie, benkimball for pointing out README bugs / typos
293
+
294
+ * Ryan Allen for his original Workflow library
data/Rakefile CHANGED
@@ -1,16 +1,21 @@
1
- #!/usr/bin/ruby1.9
1
+ #!/usr/bin/env ruby
2
2
  require "spec/rake/spectask"
3
3
  #require 'cucumber/rake/task'
4
4
  require "date"
5
5
  require "fileutils"
6
6
  require "rubygems"
7
7
 
8
+ load File.join( File.dirname(__FILE__),"/lib/tasks/state_fu.rake" )
9
+
8
10
  module Rakefile
9
11
  def self.windows?
10
12
  /djgpp|(cyg|ms|bcc)win|mingw/ =~ RUBY_PLATFORM
11
13
  end
12
14
  end
13
15
 
16
+ load 'lib/tasks/spec_last.rake'
17
+ load 'lib/tasks/state_fu.rake'
18
+
14
19
  # to build the gem:
15
20
  #
16
21
  # gem install jeweller
@@ -38,30 +43,37 @@ rescue LoadError
38
43
  end
39
44
 
40
45
  namespace :spec do
41
- desc "Run all specs"
46
+
47
+ desc 'run the nice new specs'
48
+ Spec::Rake::SpecTask.new(:state_fu) do |t|
49
+ t.spec_files = FileList["spec/state_fu_spec.rb"]
50
+ t.spec_opts = ["--options", "spec/spec.opts"]
51
+ end
52
+
53
+
54
+ desc "Run all (old) specs"
42
55
  Spec::Rake::SpecTask.new(:all) do |t|
43
56
  t.spec_files = FileList["spec/**/*_spec.rb"]
44
57
  t.spec_opts = ["--options", "spec/spec.opts"]
45
58
  end
46
59
 
47
- desc "Run unit specs"
48
- Spec::Rake::SpecTask.new(:units) do |t|
49
- t.spec_files = FileList["spec/units/*_spec.rb"]
50
- t.spec_opts = ["--options", "spec/spec.opts"]
60
+ task :skip_slow do
61
+ ENV['SKIP_SLOW_SPECS'] = 'true'
51
62
  end
52
- task :unit => :units
53
63
 
54
- desc "Run integration specs"
55
- Spec::Rake::SpecTask.new(:integration) do |t|
56
- t.spec_files = FileList["spec/integration/*_spec.rb"]
57
- t.spec_opts = ["--options", "spec/spec.opts"]
64
+ desc "Run all specs, except especially slow ones"
65
+ task :quick => [:skip_slow, :all]
66
+
67
+ desc "Run all specs with profiling & backtrace"
68
+ Spec::Rake::SpecTask.new(:prof) do |t|
69
+ t.spec_files = FileList["spec/**/*_spec.rb"]
70
+ t.spec_opts = ['-c','-b','-u','-f','profile','-R','-L','mtime']
58
71
  end
59
- task :system => :integration
60
72
 
61
73
  desc "Print Specdoc for all specs (eaxcluding plugin specs)"
62
74
  Spec::Rake::SpecTask.new(:doc) do |t|
63
75
  t.spec_files = FileList["spec/**/*_spec.rb"]
64
- t.spec_opts = ["--format", "nested","--backtrace","--color"]
76
+ t.spec_opts = ["--format", "nested","--color"]
65
77
  end
66
78
 
67
79
  desc "Run autotest"
@@ -69,26 +81,12 @@ namespace :spec do
69
81
  exec 'autospec'
70
82
  end
71
83
 
72
- def find_last_modified_spec
73
- require 'find'
74
- specs = []
75
- Find.find( File.expand_path(File.join(File.dirname(__FILE__),'spec'))) do |f|
76
- next unless f !~ /\.#/ && f =~ /_spec.rb$/
77
- specs << f
78
- end
79
- spec = specs.sort_by { |spec| File.stat( spec ).mtime }.last
80
- end
81
-
82
- desc "runs the last modified spec, without mucking about"
83
- Spec::Rake::SpecTask.new(:last) do |t|
84
- t.spec_opts = ['--options', "\"#{File.dirname(__FILE__)}/spec/spec.opts\""]
85
- t.spec_files = FileList[find_last_modified_spec]
86
- end
84
+ task :default => :state_fu
87
85
  end
88
86
 
89
87
  desc 'Runs irb in this project\'s context'
90
88
  task :irb do |t|
91
- exec 'irb -I lib -r state-fu'
89
+ exec 'irb -I lib -I spec -r state-fu -r spec_helper'
92
90
  end
93
91
 
94
92
  desc 'Runs rdoc on the project lib directory'
@@ -96,6 +94,13 @@ task :doc do |t|
96
94
  exec 'rdoc lib/'
97
95
  end
98
96
 
97
+ desc 'Delete logfiles'
98
+ namespace :log do
99
+ task :clear do |t|
100
+ Dir['log/*.log'].each { |log| File.rm(log) }
101
+ end
102
+ end
103
+
99
104
  begin
100
105
  require 'cucumber/rake/task'
101
106
 
@@ -105,4 +110,5 @@ begin
105
110
  rescue LoadError => e
106
111
  end
107
112
 
108
- task :default => 'spec:all'
113
+ task :all => 'spec:all'
114
+ task :default => :all
data/lib/no_stdout.rb CHANGED
@@ -3,7 +3,7 @@ require 'stringio'
3
3
  # a module for suppressing or capturing STDOUT or STDERR.
4
4
  # useful when shelling out to "noisy" applications or to suppress
5
5
  # output during tests.
6
- module NoStdout
6
+ module NoStdout #:nodoc:all
7
7
  module InstanceMethods
8
8
 
9
9
  # Suppresses or redirects STDOUT inside the given block.
data/lib/state-fu.rb CHANGED
@@ -59,9 +59,12 @@ require 'rubygems'
59
59
 
60
60
  [ 'core_ext',
61
61
  'logger',
62
- 'helper',
62
+ 'applicable',
63
+ 'arrays',
64
+ 'methodical',
65
+ 'has_options',
66
+ 'executioner',
63
67
  'exceptions',
64
- 'fu_space',
65
68
  'machine',
66
69
  'lathe',
67
70
  'method_factory',
@@ -77,21 +80,19 @@ require 'rubygems'
77
80
  'hooks',
78
81
  'interface',
79
82
  'transition',
80
- 'mock_transition',
83
+ 'transition_query',
81
84
  'plotter' ].each do |lib|
82
85
  require File.expand_path( File.join( File.dirname(__FILE__), 'state_fu', lib ))
83
86
  end
84
87
 
85
88
  module StateFu
86
- DEFAULT_MACHINE = :state_fu
89
+ DEFAULT = :default
90
+ DEFAULT_FIELD = :state_fu_field
87
91
 
88
92
  def self.included( klass )
89
93
  klass.extend( Interface::ClassMethods )
90
94
  klass.send( :include, Interface::InstanceMethods )
95
+ klass.extend( Interface::Aliases )
91
96
  end
92
97
  end
93
98
 
94
- if __FILE__ == $0
95
- # drop into irb?
96
- end
97
-
@@ -1,49 +1,56 @@
1
- module ActiveSupport #:nodoc:
2
- module CoreExtensions #:nodoc:
3
- module Array #:nodoc:
1
+ module ActiveSupport #:nodoc:all
2
+ module CoreExtensions #:nodoc
3
+ module Array #:nodoc
4
4
  # Makes it easier to access parts of an array.
5
- module Access
5
+ module Access #:nodoc:all
6
6
  # Returns the tail of the array from +position+.
7
7
  #
8
8
  # %w( a b c d ).from(0) # => %w( a b c d )
9
9
  # %w( a b c d ).from(2) # => %w( c d )
10
10
  # %w( a b c d ).from(10) # => nil
11
11
  # %w().from(0) # => nil
12
+ #:nodoc
12
13
  def from(position)
13
14
  self[position..-1]
14
15
  end
15
-
16
+
16
17
  # Returns the beginning of the array up to +position+.
17
18
  #
18
19
  # %w( a b c d ).to(0) # => %w( a )
19
20
  # %w( a b c d ).to(2) # => %w( a b c )
20
21
  # %w( a b c d ).to(10) # => %w( a b c d )
21
22
  # %w().to(0) # => %w()
23
+ #:nodoc
22
24
  def to(position)
23
25
  self[0..position]
24
26
  end
25
27
 
26
28
  # Equal to <tt>self[1]</tt>.
29
+ #:nodoc
27
30
  def second
28
31
  self[1]
29
32
  end
30
33
 
31
34
  # Equal to <tt>self[2]</tt>.
35
+ #:nodoc
32
36
  def third
33
37
  self[2]
34
38
  end
35
39
 
36
40
  # Equal to <tt>self[3]</tt>.
41
+ #:nodoc
37
42
  def fourth
38
43
  self[3]
39
44
  end
40
45
 
41
46
  # Equal to <tt>self[4]</tt>.
47
+ #:nodoc
42
48
  def fifth
43
49
  self[4]
44
50
  end
45
51
 
46
52
  # Equal to <tt>self[41]</tt>. Also known as accessing "the reddit".
53
+ #:nodoc
47
54
  def forty_two
48
55
  self[41]
49
56
  end
@@ -1,11 +1,12 @@
1
- module ActiveSupport #:nodoc:
2
- module CoreExtensions #:nodoc:
3
- module Array #:nodoc:
1
+ module ActiveSupport #:nodoc
2
+ module CoreExtensions #:nodoc
3
+ module Array #:nodoc
4
4
  module Conversions
5
5
  # Converts the array to a comma-separated sentence where the last element is joined by the connector word. Options:
6
6
  # * <tt>:words_connector</tt> - The sign or word used to join the elements in arrays with two or more elements (default: ", ")
7
7
  # * <tt>:two_words_connector</tt> - The sign or word used to join the elements in arrays with two elements (default: " and ")
8
8
  # * <tt>:last_word_connector</tt> - The sign or word used to join the last element in arrays with three or more elements (default: ", and ")
9
+ #:nodoc
9
10
  def to_sentence(options = {})
10
11
  default_words_connector = I18n.translate(:'support.array.words_connector', :locale => options[:locale])
11
12
  default_two_words_connector = I18n.translate(:'support.array.two_words_connector', :locale => options[:locale])
@@ -42,6 +43,7 @@ module ActiveSupport #:nodoc:
42
43
 
43
44
  # Calls <tt>to_param</tt> on all its elements and joins the result with
44
45
  # slashes. This is used by <tt>url_for</tt> in Action Pack.
46
+ #:nodoc
45
47
  def to_param
46
48
  collect { |e| e.to_param }.join '/'
47
49
  end
@@ -50,12 +52,14 @@ module ActiveSupport #:nodoc:
50
52
  # using the given +key+ as the param name.
51
53
  #
52
54
  # ['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
55
+ #:nodoc
53
56
  def to_query(key)
54
57
  prefix = "#{key}[]"
55
58
  collect { |value| value.to_query(prefix) }.join '&'
56
59
  end
57
60
 
58
- def self.included(base) #:nodoc:
61
+ #:nodoc
62
+ def self.included(base) #:nodoc
59
63
  base.class_eval do
60
64
  alias_method :to_default_s, :to_s
61
65
  alias_method :to_s, :to_formatted_s
@@ -71,6 +75,7 @@ module ActiveSupport #:nodoc:
71
75
  # output:
72
76
  #
73
77
  # Blog.find(:all).to_formatted_s(:db) # => "First Post,Second Post,Third Post"
78
+ #:nodoc
74
79
  def to_formatted_s(format = :default)
75
80
  case format
76
81
  when :db
@@ -159,6 +164,7 @@ module ActiveSupport #:nodoc:
159
164
  # </message>
160
165
  # </messages>
161
166
  #
167
+ #:nodoc
162
168
  def to_xml(options = {})
163
169
  raise "Not all elements respond to to_xml" unless all? { |e| e.respond_to? :to_xml }
164
170
  require 'builder' unless defined?(Builder)
@@ -1,7 +1,7 @@
1
- module ActiveSupport #:nodoc:
2
- module CoreExtensions #:nodoc:
3
- module Array #:nodoc:
4
- module ExtractOptions
1
+ module ActiveSupport #:nodoc
2
+ module CoreExtensions #:nodoc
3
+ module Array #:nodoc
4
+ module ExtractOptions #:nodoc:all
5
5
  # Extracts options from a set of arguments. Removes and returns the last
6
6
  # element in the array if it's a hash, otherwise returns a blank hash.
7
7
  #
@@ -11,6 +11,7 @@ module ActiveSupport #:nodoc:
11
11
  #
12
12
  # options(1, 2) # => {}
13
13
  # options(1, 2, :a => :b) # => {:a=>:b}
14
+ #:nodoc
14
15
  def extract_options!
15
16
  last.is_a?(::Hash) ? pop : {}
16
17
  end
@@ -1,9 +1,9 @@
1
1
  require 'enumerator'
2
2
 
3
- module ActiveSupport #:nodoc:
4
- module CoreExtensions #:nodoc:
5
- module Array #:nodoc:
6
- module Grouping
3
+ module ActiveSupport #:nodoc
4
+ module CoreExtensions #:nodoc
5
+ module Array #:nodoc
6
+ module Grouping #:nodoc:all
7
7
  # Splits or iterates over the array in groups of size +number+,
8
8
  # padding any remaining slots with +fill_with+ unless it is +false+.
9
9
  #
@@ -19,6 +19,7 @@ module ActiveSupport #:nodoc:
19
19
  # %w(1 2 3).in_groups_of(2, false) {|group| p group}
20
20
  # ["1", "2"]
21
21
  # ["3"]
22
+ #:nodoc
22
23
  def in_groups_of(number, fill_with = nil)
23
24
  if fill_with == false
24
25
  collection = self
@@ -56,6 +57,7 @@ module ActiveSupport #:nodoc:
56
57
  # ["1", "2", "3"]
57
58
  # ["4", "5"]
58
59
  # ["6", "7"]
60
+ #:nodoc
59
61
  def in_groups(number, fill_with = nil)
60
62
  # size / number gives minor group size;
61
63
  # size % number gives how many objects need extra accomodation;
@@ -87,6 +89,7 @@ module ActiveSupport #:nodoc:
87
89
  #
88
90
  # [1, 2, 3, 4, 5].split(3) # => [[1, 2], [4, 5]]
89
91
  # (1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
92
+ #:nodoc
90
93
  def split(value = nil)
91
94
  using_block = block_given?
92
95
 
@@ -1,8 +1,9 @@
1
- module ActiveSupport #:nodoc:
2
- module CoreExtensions #:nodoc:
3
- module Array #:nodoc:
1
+ module ActiveSupport #:nodoc
2
+ module CoreExtensions #:nodoc
3
+ module Array #:nodoc
4
4
  module RandomAccess
5
5
  # Returns a random element from the array.
6
+ #:nodoc
6
7
  def rand
7
8
  self[Kernel.rand(length)]
8
9
  end
@@ -1,9 +1,10 @@
1
- module ActiveSupport #:nodoc:
2
- module CoreExtensions #:nodoc:
3
- module Array #:nodoc:
1
+ module ActiveSupport #:nodoc
2
+ module CoreExtensions #:nodoc
3
+ module Array #:nodoc
4
4
  module Wrapper
5
5
  # Wraps the object in an Array unless it's an Array. Converts the
6
6
  # object to an Array using #to_ary if it implements that.
7
+ #:nodoc
7
8
  def wrap(object)
8
9
  case object
9
10
  when nil
@@ -1,7 +1,9 @@
1
1
  require File.join( File.dirname( __FILE__),'array/extract_options')
2
+ require File.join( File.dirname( __FILE__),'array/random_access')
2
3
  require File.join( File.dirname( __FILE__),'array/grouping')
3
4
 
4
- class Array #:nodoc:
5
+ class Array #:nodoc:all:
5
6
  include ActiveSupport::CoreExtensions::Array::ExtractOptions
7
+ include ActiveSupport::CoreExtensions::Array::RandomAccess
6
8
  include ActiveSupport::CoreExtensions::Array::Grouping
7
9
  end