shattered_support 0.3.2 → 0.3.3

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.
@@ -0,0 +1,178 @@
1
+ require 'singleton'
2
+
3
+ # The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without,
4
+ # and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept
5
+ # in inflections.rb.
6
+ module Inflector
7
+ # A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional
8
+ # inflection rules. Examples:
9
+ #
10
+ # Inflector.inflections do |inflect|
11
+ # inflect.plural /^(ox)$/i, '\1\2en'
12
+ # inflect.singular /^(ox)en/i, '\1'
13
+ #
14
+ # inflect.irregular 'octopus', 'octopi'
15
+ #
16
+ # inflect.uncountable "equipment"
17
+ # end
18
+ #
19
+ # New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the
20
+ # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may
21
+ # already have been loaded.
22
+ class Inflections
23
+ include Singleton
24
+
25
+ attr_reader :plurals, :singulars, :uncountables
26
+
27
+ def initialize
28
+ @plurals, @singulars, @uncountables = [], [], []
29
+ end
30
+
31
+ # Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
32
+ # The replacement should always be a string that may include references to the matched data from the rule.
33
+ def plural(rule, replacement)
34
+ @plurals.insert(0, [rule, replacement])
35
+ end
36
+
37
+ # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
38
+ # The replacement should always be a string that may include references to the matched data from the rule.
39
+ def singular(rule, replacement)
40
+ @singulars.insert(0, [rule, replacement])
41
+ end
42
+
43
+ # Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
44
+ # for strings, not regular expressions. You simply pass the irregular in singular and plural form.
45
+ #
46
+ # Examples:
47
+ # irregular 'octopus', 'octopi'
48
+ # irregular 'person', 'people'
49
+ def irregular(singular, plural)
50
+ plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
51
+ singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
52
+ end
53
+
54
+ # Add uncountable words that shouldn't be attempted inflected.
55
+ #
56
+ # Examples:
57
+ # uncountable "money"
58
+ # uncountable "money", "information"
59
+ # uncountable %w( money information rice )
60
+ def uncountable(*words)
61
+ (@uncountables << words).flatten!
62
+ end
63
+
64
+ # Clears the loaded inflections within a given scope (default is :all). Give the scope as a symbol of the inflection type,
65
+ # the options are: :plurals, :singulars, :uncountables
66
+ #
67
+ # Examples:
68
+ # clear :all
69
+ # clear :plurals
70
+ def clear(scope = :all)
71
+ case scope
72
+ when :all
73
+ @plurals, @singulars, @uncountables = [], [], []
74
+ else
75
+ instance_variable_set "@#{scope}", []
76
+ end
77
+ end
78
+ end
79
+
80
+ extend self
81
+
82
+ def inflections
83
+ if block_given?
84
+ yield Inflections.instance
85
+ else
86
+ Inflections.instance
87
+ end
88
+ end
89
+
90
+ def pluralize(word)
91
+ result = word.to_s.dup
92
+
93
+ if inflections.uncountables.include?(result.downcase)
94
+ result
95
+ else
96
+ inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
97
+ result
98
+ end
99
+ end
100
+
101
+ def singularize(word)
102
+ result = word.to_s.dup
103
+
104
+ if inflections.uncountables.include?(result.downcase)
105
+ result
106
+ else
107
+ inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
108
+ result
109
+ end
110
+ end
111
+
112
+ def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
113
+ if first_letter_in_uppercase
114
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
115
+ else
116
+ lower_case_and_underscored_word.first + camelize(lower_case_and_underscored_word)[1..-1]
117
+ end
118
+ end
119
+
120
+ def titleize(word)
121
+ humanize(underscore(word)).gsub(/\b([a-z])/) { $1.capitalize }
122
+ end
123
+
124
+ def underscore(camel_cased_word)
125
+ camel_cased_word.to_s.gsub(/::/, '/').
126
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
127
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
128
+ tr("-", "_").
129
+ downcase
130
+ end
131
+
132
+ def dasherize(underscored_word)
133
+ underscored_word.gsub(/_/, '-')
134
+ end
135
+
136
+ def humanize(lower_case_and_underscored_word)
137
+ lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
138
+ end
139
+
140
+ def demodulize(class_name_in_module)
141
+ class_name_in_module.to_s.gsub(/^.*::/, '')
142
+ end
143
+
144
+ def tableize(class_name)
145
+ pluralize(underscore(class_name))
146
+ end
147
+
148
+ def classify(table_name)
149
+ camelize(singularize(table_name))
150
+ end
151
+
152
+ def foreign_key(class_name, separate_class_name_and_id_with_underscore = true)
153
+ underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id")
154
+ end
155
+
156
+ def constantize(camel_cased_word)
157
+ raise NameError, "#{camel_cased_word.inspect} is not a valid constant name!" unless
158
+ /^(::)?([A-Z]\w*)(::[A-Z]\w*)*$/ =~ camel_cased_word
159
+
160
+ camel_cased_word = "::#{camel_cased_word}" unless $1
161
+ Object.module_eval(camel_cased_word, __FILE__, __LINE__)
162
+ end
163
+
164
+ def ordinalize(number)
165
+ if (11..13).include?(number.to_i % 100)
166
+ "#{number}th"
167
+ else
168
+ case number.to_i % 10
169
+ when 1: "#{number}st"
170
+ when 2: "#{number}nd"
171
+ when 3: "#{number}rd"
172
+ else "#{number}th"
173
+ end
174
+ end
175
+ end
176
+ end
177
+
178
+ require File.dirname(__FILE__) + '/inflections'
@@ -1,64 +1,2 @@
1
- require 'rubygems'
2
-
3
- class Object
4
- def method_defined?(method)
5
- return self.class.method_defined?(method)
6
- end
7
-
8
- # This is a shorthand to define vector object coordinates.
9
- #
10
- # Creates a vector object at coordinates x,y,z
11
- def v(x, y, z)
12
- Vector.new(x, y, z)
13
- end
14
- end
15
-
16
- class File #:nodoc:
17
- # File.each_in_path will recursively look for all files, starting at the given path.
18
- # It will yield with each result.
19
- def self.each_in_path(path)
20
- Dir.each_in_path(path) do |directory|
21
- Dir.foreach( directory ) do |filename|
22
- resource = directory + "/#{filename}"
23
- yield(resource) if File.file? resource
24
- end
25
- end
26
- end
27
-
28
- # This finds all files in paths (an array or string) matching the given extensions:
29
- #
30
- # Usage:
31
- # -File.find_by_extensions(SHATTERED_ROOT,"ogg","mp3","wav")
32
- # -File.find_by_extension(["apps","media","plugins"], "rmaterial")
33
- def self.find_by_extensions(paths, *extensions)
34
- paths = [paths] if paths.is_a? String
35
- extensions.collect! { |ext| ext[0].chr == "." ? ext[1..-1] : ext } # get rid of "." in ".ogg"
36
- reg_exp = /\.(#{extensions.join("|")})$/
37
- files = []
38
- paths.each do |path|
39
- each_in_path(path) do |filename|
40
- files << filename if filename =~ reg_exp
41
- end
42
- end
43
- return files
44
- end
45
- # See File#find_by_extensions
46
- def self.find_by_extension(paths, extension)
47
- find_by_extensions(paths, extension)
48
- end
49
- end
50
-
51
- class Dir #:nodoc:
52
- # Dir.each_in_path will recursively yield all non-hidden directories from the given path.
53
- def self.each_in_path(path, &block)
54
- return unless File.directory? path
55
- yield path
56
- foreach(path) do |directory|
57
- next if directory =~ /\..*/
58
- each_in_path("#{path}/#{directory}", &block)
59
- end
60
- end
61
- end
62
-
63
- require File.dirname(__FILE__)+"/base"
64
- require File.dirname(__FILE__)+"/runner"
1
+ require 'shattered_support/core_ext'
2
+ require 'shattered_support/inflector'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.10
2
+ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: shattered_support
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.3.2
7
- date: 2006-06-04
6
+ version: 0.3.3
7
+ date: 2006-07-18 00:00:00 -06:00
8
8
  summary: "Shattered Support: Allows a common derivation point for shattered MVC."
9
9
  require_paths:
10
- - lib
10
+ - lib
11
11
  email:
12
12
  homepage: http://www.hastilymade.com
13
13
  rubyforge_project:
@@ -18,25 +18,47 @@ bindir: bin
18
18
  has_rdoc: "true"
19
19
  required_ruby_version: !ruby/object:Gem::Version::Requirement
20
20
  requirements:
21
- -
22
- - ">"
23
- - !ruby/object:Gem::Version
24
- version: 0.0.0
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
25
24
  version:
26
25
  platform: ruby
26
+ signing_key:
27
+ cert_chain:
27
28
  authors: []
29
+
28
30
  files:
29
- - lib/base.rb
30
- - lib/runner.rb
31
- - lib/shattered_support.rb
32
- - lib/vector.rb
33
- - lib/timer/timed_event.rb
34
- - lib/timer/timer.rb
31
+ - lib/shattered_support.rb
32
+ - lib/shattered_support/core_ext.rb
33
+ - lib/shattered_support/inflections.rb
34
+ - lib/shattered_support/inflector.rb
35
+ - lib/shattered_support/core_ext/class.rb
36
+ - lib/shattered_support/core_ext/dir.rb
37
+ - lib/shattered_support/core_ext/file.rb
38
+ - lib/shattered_support/core_ext/numeric.rb
39
+ - lib/shattered_support/core_ext/string.rb
40
+ - lib/shattered_support/core_ext/class/attribute_accessors.rb
41
+ - lib/shattered_support/core_ext/class/inheritable_attributes.rb
42
+ - lib/shattered_support/core_ext/class/removal.rb
43
+ - lib/shattered_support/core_ext/dir/search.rb
44
+ - lib/shattered_support/core_ext/file/search.rb
45
+ - lib/shattered_support/core_ext/numeric/time.rb
46
+ - lib/shattered_support/core_ext/string/access.rb
47
+ - lib/shattered_support/core_ext/string/conversions.rb
48
+ - lib/shattered_support/core_ext/string/inflections.rb
49
+ - lib/shattered_support/core_ext/string/iterators.rb
50
+ - lib/shattered_support/core_ext/string/starts_ends_with.rb
35
51
  test_files: []
52
+
36
53
  rdoc_options: []
54
+
37
55
  extra_rdoc_files: []
56
+
38
57
  executables: []
58
+
39
59
  extensions: []
60
+
40
61
  requirements:
41
- - Shattered Support is a base for the rest of shattered.
42
- dependencies: []
62
+ - Shattered Support is a base for the rest of shattered.
63
+ dependencies: []
64
+
data/lib/base.rb DELETED
@@ -1,221 +0,0 @@
1
-
2
- $:.unshift(File.dirname(__FILE__)) unless
3
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
4
-
5
- require 'active_support'
6
- require 'timer/timer'
7
- require 'vector'
8
-
9
- module ShatteredSupport #:nodoc:
10
-
11
- BEFORE_INIT_CALL_VALUES = :before_init_call_values
12
- BEFORE_INIT_SET_VALUES = :before_init_set_values
13
-
14
-
15
- def self.append_features(base)
16
- super
17
- base.extend(ClassMethods)
18
- end
19
- module ClassMethods
20
- # In the pre_initialization phase (see #before_init_call), send an object a bunch of sets.
21
- #
22
- # This is used in actor, camera, mesh, and virtually everywhere to support the format of:
23
- # mesh "ruby", :position => v(1,0,0)
24
- #
25
- # becomes
26
- # before_init_set( :ruby, {:position => v(1,0,0) } )
27
- # becomes
28
- # ruby.position=v(1,0,0)
29
- # when the obect is initialized.
30
- def before_init_set(variable, options={})
31
- self.write_inheritable_array(BEFORE_INIT_SET_VALUES, [[ variable, options ]] )
32
- end
33
-
34
- # All shattered objects have a pre_initialization phase. Use this to specify that
35
- # a function should be called when the object is created.
36
- #
37
- # _Example_:
38
- # class BulletModel < ShatteredModel::Base
39
- # before_init_call(:calculate_trajectory, v(0,0,0), v(0,0,1))
40
- # def calculate_trajectory
41
- # #called before initialize is
42
- # end
43
- # end
44
- #
45
- def before_init_call(function, *arguments)
46
- self.write_inheritable_array(BEFORE_INIT_CALL_VALUES, [[function, [*arguments]]])
47
- end
48
- end
49
- class Base
50
-
51
- # This is overwritten to allow for a pre_initialize before initialize
52
- def self.new(*options) #:nodoc
53
- new_base = allocate
54
- new_base.pre_initialize
55
- new_base.send(:initialize, *options)
56
- return new_base
57
- end
58
-
59
- # Retrieve the current state
60
- def state
61
- Configuration.environment[:state]
62
- end
63
-
64
- # This function is called after an object is allocated, but before it's initialized.
65
- #
66
- # See ShatteredSupport::ClassMethods#before_init_call for usage.
67
- def pre_initialize #:nodoc:
68
- pre_initialize_set
69
- pre_initialize_call
70
- end
71
-
72
- # Used in pre_initialize
73
- def each_init_value(name) #:nodoc:
74
- startup_attributes = self.class.read_inheritable_attribute( name ) || []
75
- startup_attributes.each do |actor, options|
76
- next if options.nil?
77
- yield actor, options
78
- end
79
- end
80
-
81
- # Used in pre_initialize for before_init_set
82
- def pre_initialize_set #:nodoc:
83
- each_init_value(BEFORE_INIT_SET_VALUES) do |variable, options|
84
- call_object_function_for_each_key( variable, options )
85
- end
86
- end
87
-
88
- # Used in pre_initialize for before_init_call
89
- def pre_initialize_call #:nodoc:
90
- each_init_value(BEFORE_INIT_CALL_VALUES) do |function, args|
91
- call_object_function( :self, function, args )
92
- end
93
- end
94
-
95
-
96
- # TODO - is this called anymore?
97
- def update_event(time_elapsed) #:nodoc:
98
- actors.each do |actor|
99
- actor.update_actors(time_elapsed)
100
- actor.update(time_elapsed)
101
- end
102
- end
103
-
104
- # remove_from_scene? should just be defined in model.
105
- # Refactor? TODO
106
- def remove_from_scene? #:nodoc:
107
- return false
108
- end
109
-
110
- # TODO outdated?
111
- def update_actors(time_elapsed) #:nodoc:
112
- update_event time_elapsed
113
- remove_dead_actors
114
- end
115
-
116
- # TODO outdated?
117
- def remove_dead_actors #:nodoc:
118
- actors.each do |actor|
119
- remove_from_scene actor if actor.remove_from_scene?
120
- end
121
- end
122
-
123
- # TODO outdated?
124
- def remove_from_scene(actor)
125
- actors.delete actor
126
- actor.unload!
127
- end
128
-
129
- protected
130
- def call_object_function_for_each_key( actor, options )
131
- call_object_function(actor, :position=, options.delete(:position)) if options.has_key? :position
132
- options.each_pair do |action, params|
133
- call_object_function actor, "#{action}=", params
134
- end
135
- end
136
-
137
- def call_object_function(actor, action, params)
138
- begin
139
- if params.is_a? Symbol #|| (params.length == 1 && params[0].is_a?(Symbol)) this will allow substitution in before_init_call. This may not be intended behavior.
140
- params = eval(params.to_s)
141
- end
142
- rescue NameError
143
- puts "It is not advisable to pass #{params.inspect} to #{action.inspect} for #{actor.inspect}."
144
- puts " It will try to be evaluated. Use a string instead."
145
- end
146
- begin
147
- sendee = eval(actor.to_s)
148
- sendee.send( action.to_sym, *params )
149
- rescue NoMethodError, ArgumentError => bang
150
- message="Error upon #{actor.to_s}.send(#{action.to_sym.inspect}, #{params.inspect}):\n\r #{bang.class}: #{bang.message}"
151
- bang = ShatteredSupport::RetossError.new(bang,message)
152
- raise bang
153
- end
154
- end
155
-
156
- public
157
-
158
- # attr helpers. These are instance level attr_* functions.
159
- def attr_reader(*args)
160
- name, value = args
161
- attr_define(:reader, name, value)
162
- end
163
-
164
- # attr helpers. These are instance level attr_* functions.
165
- # attr_writer accepts a value as the second argument
166
- def attr_writer(*args)
167
- name, value = args
168
- attr_define(:writer, name, value)
169
- end
170
-
171
- # attr helpers. These are instance level attr_* functions.
172
- # attr_accessor accepts a value as the second argument
173
- def attr_accessor(*args)
174
- name, value = args
175
- attr_define(:accessor, name, value)
176
- end
177
-
178
- # Define a block to execute when an object is unloaded.
179
- def when_unloaded(&block)
180
- @unloaded_events ||= []
181
- @unloaded_events << block
182
- end
183
-
184
- protected
185
-
186
- def attr_define(accessor_level, name, value)
187
- self.class.send("attr_#{accessor_level}".to_sym, "#{name}".to_sym)
188
- instance_variable_set("@#{name}".to_sym, value) if !value.nil?
189
- end
190
-
191
- private
192
-
193
- def disabled?
194
- @unloaded_events == nil
195
- end
196
-
197
- def unload!
198
- return if disabled?
199
- @unloaded_events.each do |event|
200
- event.call
201
- end
202
- @unloaded_events = nil
203
- end
204
-
205
- end
206
-
207
- class Error < StandardError # :nodoc:
208
- end
209
-
210
- class RetossError < StandardError # :nodoc:
211
- attr_accessor :message
212
- def initialize(error, message)
213
- self.message = message
214
- set_backtrace error.backtrace
215
- end
216
- end
217
- end
218
-
219
- ShatteredSupport::Base.class_eval do
220
- include ShatteredSupport::Timer
221
- end
data/lib/runner.rb DELETED
@@ -1,11 +0,0 @@
1
- module ShatteredSupport
2
- class Configuration #:nodoc:
3
- def self.environment
4
- @@environment={} unless defined? @@environment
5
- return @@environment
6
- end
7
- def self.environment=(environment)
8
- @@environment=environment
9
- end
10
- end
11
- end
@@ -1,77 +0,0 @@
1
- module ShatteredSupport
2
- module Timer #:nodoc:all
3
-
4
- class Timer
5
- attr_reader :events_remaining
6
- def initialize
7
- @events_remaining = []
8
- end
9
- def in(seconds, &block)
10
- @events_remaining << TimedEvent.new(seconds, &block)
11
- end
12
- def every(seconds, &block)
13
- @events_remaining << ContinuousTimedEvent.new(seconds,&block)
14
- end
15
- def update(time_elapsed)
16
- events_for_update = @events_remaining.dup
17
- events_for_update.each do |event|
18
- event.update(time_elapsed)
19
- @events_remaining.delete(event) if event.processed?
20
- end
21
- end
22
- end
23
-
24
- class TimedEvent
25
- attr_accessor :time_remaining
26
- def initialize(seconds, &block)
27
- @event = block
28
- if(seconds != :frame)
29
- @time_remaining = seconds
30
- @initial_time = @time_remaining
31
- else
32
- @time_remaining = 0
33
- @initial_time = 0
34
- end
35
- end
36
- def update(time_elapsed)
37
- return if processed?
38
- @time_remaining -= time_elapsed
39
- if time_up?
40
- process_event
41
- @processed=true
42
- end
43
- end
44
- def processed?
45
- return @processed == true
46
- end
47
- def reset
48
- @time_remaining = @initial_time
49
- end
50
- private
51
- def process_event
52
- @event.call(@initial_time - @time_remaining)
53
- end
54
- def time_up?
55
- return @time_remaining <= 0
56
- end
57
- end
58
-
59
- class ContinuousTimedEvent < TimedEvent
60
- def update(time_elapsed)
61
- @time_remaining -= time_elapsed
62
- if(time_up?)
63
- process_event
64
- reset
65
- end
66
- end
67
- def reset
68
- @time_remaining += @initial_time
69
- @time_remaining = 0 if @time_remaining < 0
70
- end
71
- def processed?
72
- false
73
- end
74
- end
75
-
76
- end
77
- end
data/lib/timer/timer.rb DELETED
@@ -1,67 +0,0 @@
1
- require File.dirname(__FILE__)+'/timed_event'
2
-
3
- module ShatteredSupport
4
- module Timer #:nodoc:
5
- def self.append_features(base)
6
- super
7
- base.extend(ClassMethods)
8
- base.send(:include, InstanceMethods)
9
- end
10
- module ClassMethods
11
- # Timers are controller events that occur after a specified period of time.
12
- # The time values are seconds by default.
13
- #
14
- # timer :in
15
- # If you want an event to occur once after a specified amount of time, use
16
- # timer :in => 3.seconds, :action => :method_to_call
17
- #
18
- # timer :every
19
- # If you want an event to occur once every specified amount of time, use
20
- # timer :every => 3.seconds, :action => :method_to_call
21
- # If you want to be notified of every frame update, use
22
- # timer :every => :frame, :action => :method_to_call
23
- #
24
- # Inside the instance, you can still create timer events, using the timer object:
25
- # timer.in( 3.seconds ) { ... }
26
- # timer.every( 3.seconds ) { ... }
27
- def timer(options = {})
28
- if options[:action].nil?
29
- throw ShatteredSupport::Error,
30
- "Timer event must specify an :action => :method"
31
- end
32
- if options[:in].nil? && options[:every].nil?
33
- throw ShatteredSupport::Error,
34
- "Timer event must specify a time. (timer :in or timer :every)"
35
- end
36
- time = options[:in] || options[:every]
37
- action = options[:action]
38
- before_init_call(:timer_in, time, action) unless options[:in].nil?
39
- before_init_call(:timer_every, time, action) unless options[:every].nil?
40
- end
41
- end
42
- module InstanceMethods
43
- def timer
44
- @timer ||= Timer.new
45
- end
46
- private
47
- def timer_in(time, action)
48
- timer.in(time) do |time_elapsed|
49
- timer_enactment(action, time_elapsed)
50
- end
51
- end
52
- def timer_every(time, action)
53
- timer.every(time) do |time_elapsed|
54
- timer_enactment(action, time_elapsed)
55
- end
56
- end
57
- def timer_enactment(action, time_elapsed)
58
- begin
59
- send(action.to_sym)
60
- rescue ArgumentError => argument_error
61
- raise argument_error unless argument_error.message.to_sym == :"wrong number of arguments (0 for 1)"
62
- send(action.to_sym,time_elapsed)
63
- end
64
- end
65
- end
66
- end
67
- end