mood_swing 0.0.1

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,36 @@
1
+ = Mood Swing
2
+
3
+ As we've been taught, conditional statements can be a code smell and a good way to clean them up is polymorphism. I've
4
+ found that with rails coupling the persistence layer and the business logic sometimes the standard form of inheritance-
5
+ based polymorphism is awkward or not feasible. However, Ruby with it's dynamic object model can provide a form of
6
+ inheritance via extending instances by mixing in modules dynamically. Mood Swing embraces this and provides a convenient
7
+ means of doing it.
8
+
9
+ == Usage
10
+
11
+ You simply define the class macro mood_trigger and pass it the attribute in which will be used to load the module. The
12
+ value of the attribute will be inflected with .classify and then a module matching "#{value}Extension" will be loaded if
13
+ it is available with in the class namespace. Given the mood_trigger attribute is breed, with a value of hound, in the
14
+ class named Dog, then the module would be named Dog::HoundExtension.
15
+
16
+ class Dog < ActiveRecord::Base
17
+ mood_trigger 'breed'
18
+
19
+ def bark
20
+ 'woof'
21
+ end
22
+
23
+ module HoundExtension
24
+ def bark
25
+ 'Hoooooowl'
26
+ end
27
+ end
28
+ end
29
+
30
+ Now whenever you load a dog with the breed set to hound, or if you assign the breed to hound, it will bark out "Hoooooowl"
31
+
32
+ Optionally, you can supply a writer attribute if the writer is not the same as the reader. This is the case with with
33
+ polymorphic associations.
34
+
35
+ belongs_to 'body', :polymorphic => true
36
+ mood_trigger 'body_type', :writer => 'body'
@@ -0,0 +1,68 @@
1
+ # Allows polymorphic behavior based on the value of an attribute by including a module dynamically.
2
+ module MoodSwing
3
+
4
+ # reader is the value to use as the basis of the included module. The convention for naming the include is:
5
+ # YourClass::YourNameExtension
6
+ #
7
+ # An example would be:
8
+ #
9
+ # class Dog < ActiveRecord::Base
10
+ # mood_trigger 'breed'
11
+ #
12
+ # def bark
13
+ # puts 'woof'
14
+ # end
15
+ # end
16
+ #
17
+ # module Dog::HoundExtension
18
+ # def bark
19
+ # puts 'Hoooooowl'
20
+ # end
21
+ # end
22
+ #
23
+ # When a instance of dog is initialized the breed attribute is read and it's value is used to extend the current
24
+ # instance's behavior with the module matching following the previously mentioned convention. If the Dog instance's
25
+ # breed was "Hound" then it would be extended with the Dog::HoundExtension. Now when you call @dog.bark, your dog will
26
+ # howl instead of woof.
27
+ #
28
+ # The module is updated when the attribute changes. An example of the behavior to expect with a new object is:
29
+ #
30
+ # spot = Dog.new
31
+ # spot.bark
32
+ # => "woof"
33
+ # spot.breed = "hound"
34
+ # spot.bark
35
+ # => 'Hoooooowl'
36
+ #
37
+ # If your attribute writer is different from the reader, then you can pass in :writer => "your_writer_method" and it
38
+ # will use that. This is the case when using a polymorphic belongs_to accessor as the attribute.
39
+ #
40
+ # belongs_to 'body', :polymorphic => true
41
+ # mood_trigger 'body_type', :writer => 'body'
42
+ def mood_trigger(reader, options ={})
43
+ options[:writer] ||= reader
44
+
45
+ define_method("#{options[:writer]}_with_extension=") do |value|
46
+ self.send "#{options[:writer]}_without_extension=", value
47
+ self.send "#{reader}_extension!"
48
+ self.send reader
49
+ end
50
+
51
+ define_method("#{reader}_extension!") do
52
+ begin
53
+ self.extend "#{self.class}::#{self[reader].classify}Extension".constantize
54
+ rescue NameError
55
+ end
56
+ end
57
+
58
+ class_eval do
59
+ alias_method_chain "#{options[:writer]}=", 'extension'
60
+ after_initialize "#{reader}_extension!"
61
+ end
62
+ end
63
+ end
64
+
65
+ ActiveSupport.on_load(:active_record) do
66
+ extend MoodSwing
67
+ end
68
+
@@ -0,0 +1,3 @@
1
+ module MoodSwing
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mood_swing
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - TJ Singleton
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-06-23 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Allows polymorphic behavior based on the value of an attribute by including a module dynamically.
23
+ email: tjsingleton@vantagestreet.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - lib/mood_swing/version.rb
32
+ - lib/mood_swing.rb
33
+ - README.rdoc
34
+ has_rdoc: true
35
+ homepage: http://github.com/tjsingleton/mood_swing
36
+ licenses: []
37
+
38
+ post_install_message:
39
+ rdoc_options: []
40
+
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ hash: 3
49
+ segments:
50
+ - 0
51
+ version: "0"
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ requirements: []
62
+
63
+ rubyforge_project:
64
+ rubygems_version: 1.3.7
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: Polymorphic behavior based on the value of an attribute
68
+ test_files: []
69
+