characterizable 0.0.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.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Seamus Abshere
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,19 @@
1
+ = characterizable
2
+
3
+ "Cognitive mechanisms, on this view, take mathematically characterizable inputs to deliver mathematically characterizable outputs, and qua computational devices, that is all."
4
+
5
+ http://tinyurl.com/28tcrw2
6
+
7
+ == Note on Patches/Pull Requests
8
+
9
+ * Fork the project.
10
+ * Make your feature addition or bug fix.
11
+ * Add tests for it. This is important so I don't break it in a
12
+ future version unintentionally.
13
+ * Commit, do not mess with rakefile, version, or history.
14
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
15
+ * Send me a pull request. Bonus points for topic branches.
16
+
17
+ == Copyright
18
+
19
+ Copyright (c) 2010 Seamus Abshere. See LICENSE for details.
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "characterizable"
8
+ gem.summary = %Q{Characterize instances of a class}
9
+ gem.description = %Q{Characterize the relationship between "attributes" (getters/setters) of instances of a class}
10
+ gem.email = "seamus@abshere.net"
11
+ gem.homepage = "http://github.com/seamusabshere/characterizable"
12
+ gem.authors = ["Andy Rossmeissl", "Seamus Abshere"]
13
+ gem.add_dependency 'blockenspiel', '>=0.3.2'
14
+ gem.add_dependency 'activesupport', '>=2.3.5'
15
+ gem.add_development_dependency 'activerecord', '>=2.3.5'
16
+ gem.add_development_dependency "shoulda", ">= 0"
17
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
18
+ end
19
+ Jeweler::GemcutterTasks.new
20
+ rescue LoadError
21
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
22
+ end
23
+
24
+ require 'rake/testtask'
25
+ Rake::TestTask.new(:test) do |test|
26
+ test.libs << 'lib' << 'test'
27
+ test.pattern = 'test/**/test_*.rb'
28
+ test.verbose = true
29
+ end
30
+
31
+ begin
32
+ require 'rcov/rcovtask'
33
+ Rcov::RcovTask.new do |test|
34
+ test.libs << 'test'
35
+ test.pattern = 'test/**/test_*.rb'
36
+ test.verbose = true
37
+ end
38
+ rescue LoadError
39
+ task :rcov do
40
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
41
+ end
42
+ end
43
+
44
+ task :test => :check_dependencies
45
+
46
+ task :default => :test
47
+
48
+ require 'rake/rdoctask'
49
+ Rake::RDocTask.new do |rdoc|
50
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
51
+
52
+ rdoc.rdoc_dir = 'rdoc'
53
+ rdoc.title = "characterizable #{version}"
54
+ rdoc.rdoc_files.include('README*')
55
+ rdoc.rdoc_files.include('lib/**/*.rb')
56
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,123 @@
1
+ require 'blockenspiel'
2
+ require 'active_support'
3
+ require 'active_support/version'
4
+ %w{
5
+ active_support/core_ext/class/attribute_accessors
6
+ active_support/core_ext/object/blank
7
+ active_support/core_ext/array/wrap
8
+ active_support/core_ext/module/aliasing
9
+ active_support/core_ext/module/delegation
10
+ }.each do |active_support_3_requirement|
11
+ require active_support_3_requirement
12
+ end if ActiveSupport::VERSION::MAJOR == 3
13
+
14
+ module Characterizable
15
+ def self.included(klass)
16
+ klass.cattr_accessor :characterizable_base
17
+ klass.extend ClassMethods
18
+ end
19
+
20
+ def known_characteristics
21
+ characterizable_base.characteristics.select do |c|
22
+ c.known?(self) and not c.trumped?(self)
23
+ end
24
+ end
25
+
26
+ def unknown_characteristics
27
+ characterizable_base.characteristics.select do |c|
28
+ c.unknown?(self) and c.requited?(self) and not c.trumped?(self)
29
+ end
30
+ end
31
+
32
+ def visible_known_characteristics
33
+ known_characteristics.reject { |c| c.hidden? }
34
+ end
35
+
36
+ def visible_unknown_characteristics
37
+ unknown_characteristics.reject { |c| c.hidden? }
38
+ end
39
+
40
+ module ClassMethods
41
+ def characterize(&block)
42
+ self.characterizable_base = Characterizable::Base.new self
43
+ Blockenspiel.invoke block, characterizable_base
44
+ end
45
+ delegate :characteristics, :to => :characterizable_base
46
+ end
47
+
48
+ # don't want to use a Hash, because that would be annoying to select from
49
+ class ArrayOfCharacteristics < Array
50
+ def [](key_or_index)
51
+ case key_or_index
52
+ when String, Symbol
53
+ detect { |c| c.name == key_or_index }
54
+ else
55
+ super
56
+ end
57
+ end
58
+ end
59
+
60
+ class Base
61
+ attr_reader :klass
62
+ def initialize(klass)
63
+ @klass = klass
64
+ end
65
+ def characteristics
66
+ @_characteristics ||= ArrayOfCharacteristics.new
67
+ end
68
+ include Blockenspiel::DSL
69
+ def has(name, options = {}, &block)
70
+ characteristics.push Characteristic.new(self, name, options, &block)
71
+ end
72
+ end
73
+
74
+ class Characteristic
75
+ attr_reader :base
76
+ attr_reader :name
77
+ attr_reader :trumps
78
+ attr_reader :prerequisite
79
+ attr_reader :hidden
80
+ attr_reader :options
81
+ def initialize(base, name, options = {}, &block)
82
+ @base = base
83
+ @name = name.to_sym
84
+ @trumps = Array.wrap(options.delete(:trumps))
85
+ @prerequisite = options.delete :prerequisite
86
+ @hidden = options.delete :hidden
87
+ @options = options
88
+ Blockenspiel.invoke block, self if block_given?
89
+ end
90
+ delegate :characteristics, :to => :base
91
+ def unknown?(obj)
92
+ obj.send(name).nil?
93
+ end
94
+ def known?(obj)
95
+ not unknown?(obj)
96
+ end
97
+ def trumped?(obj)
98
+ characteristics.any? do |c|
99
+ c.known?(obj) and c.trumps.include?(name)
100
+ end
101
+ end
102
+ def requited?(obj)
103
+ return true if prerequisite.nil?
104
+ characteristics[prerequisite].known? obj
105
+ end
106
+ def hidden?
107
+ hidden
108
+ end
109
+ include Blockenspiel::DSL
110
+ def reveals(other_name, other_options = {}, &block)
111
+ base.has other_name, other_options.merge(:prerequisite => name), &block
112
+ base.klass.module_eval %{
113
+ def #{name}_with_dependent_#{other_name}=(new_#{name})
114
+ if new_#{name}.nil?
115
+ self.#{other_name} = nil
116
+ end
117
+ self.#{name}_without_dependent_#{other_name} = new_#{name}
118
+ end
119
+ alias_method_chain :#{name}=, :dependent_#{other_name}
120
+ }, __FILE__, __LINE__
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'ruby-debug'
5
+
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+ require 'characterizable'
9
+
10
+ class Test::Unit::TestCase
11
+ end
@@ -0,0 +1,123 @@
1
+ require 'helper'
2
+
3
+ # TODO
4
+ class Automobile
5
+ attr_accessor :make, :model_year, :model, :variant, :size_class, :hybridity, :daily_distance_estimate
6
+ attr_accessor :record_creation_date
7
+ include Characterizable
8
+ characterize do
9
+ has :make do |make|
10
+ make.reveals :model_year do |model_year|
11
+ model_year.reveals :model, :trumps => :size_class do |model|
12
+ model.reveals :variant, :trumps => :hybridity
13
+ end
14
+ end
15
+ end
16
+ has :record_creation_date, :hidden => true
17
+ has :size_class
18
+ # has :fuel_type
19
+ # has :fuel_efficiency, :trumps => [:urbanity, :hybridity], :measures => :length_per_volume
20
+ # has :urbanity, :measures => :percentage
21
+ has :hybridity
22
+ has :daily_distance_estimate, :trumps => [:weekly_distance_estimate, :annual_distance_estimate, :daily_duration], :measures => :length #, :weekly_fuel_cost, :annual_fuel_cost]
23
+ # has :daily_duration, :trumps => [:annual_distance_estimate, :weekly_distance_estimate, :daily_distance_estimate], :measures => :time #, :weekly_fuel_cost, :annual_fuel_cost]
24
+ # has :weekly_distance_estimate, :trumps => [:annual_distance_estimate, :daily_distance_estimate, :daily_duration], :measures => :length #, :weekly_fuel_cost, :annual_fuel_cost]
25
+ # has :annual_distance_estimate, :trumps => [:weekly_distance_estimate, :daily_distance_estimate, :daily_duration], :measures => :length #, :weekly_fuel_cost, :annual_fuel_cost]
26
+ # has :acquisition
27
+ # has :retirement
28
+ end
29
+ end
30
+
31
+ class SimpleAutomobile
32
+ include Characterizable
33
+ attr_accessor :make
34
+ attr_accessor :model
35
+ attr_accessor :variant
36
+ characterize do
37
+ has :make
38
+ has :model
39
+ has :variant, :trumps => :model
40
+ end
41
+ end
42
+
43
+ class TestCharacterizable < Test::Unit::TestCase
44
+ should "let you define the relevant characteristics of a class" do
45
+ assert_nothing_raised do
46
+ class OnDemandAutomobile
47
+ include Characterizable
48
+ characterize do
49
+ has :make
50
+ has :model
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ should "tell you what characteristics are known" do
57
+ a = SimpleAutomobile.new
58
+ a.make = 'Ford'
59
+ assert_equal [:make], a.known_characteristics.map(&:name)
60
+ end
61
+
62
+ should "tell you what characteristics are unknown" do
63
+ a = SimpleAutomobile.new
64
+ a.make = 'Ford'
65
+ assert_equal [:model, :variant], a.unknown_characteristics.map(&:name)
66
+ end
67
+
68
+ should "present a concise set of known characteristics by getting rid of those that have been trumped" do
69
+ a = SimpleAutomobile.new
70
+ a.make = 'Ford'
71
+ a.model = 'Taurus'
72
+ a.variant = 'Taurus V6 DOHC'
73
+ assert_equal [:make, :variant], a.known_characteristics.map(&:name)
74
+ end
75
+
76
+ should "not mention a characteristic as unknown if, in fact, it has been trumped" do
77
+ a = SimpleAutomobile.new
78
+ a.make = 'Ford'
79
+ a.variant = 'Taurus V6 DOHC'
80
+ assert_equal [], a.unknown_characteristics.map(&:name)
81
+ end
82
+
83
+ should "not mention a characteristic as unknown if it is waiting on something else to be revealed" do
84
+ a = Automobile.new
85
+ assert !a.unknown_characteristics.map(&:name).include?(:model_year)
86
+ end
87
+
88
+ should "make sure that trumping works even within revealed characteristics" do
89
+ a = Automobile.new
90
+ assert a.unknown_characteristics.map(&:name).include?(:size_class)
91
+ a.make = 'Ford'
92
+ a.model_year = 1999
93
+ a.model = 'Taurus'
94
+ a.size_class = 'mid-size'
95
+ assert_equal [:model, :model_year, :make], a.known_characteristics.map(&:name)
96
+ assert !a.unknown_characteristics.map(&:name).include?(:size_class)
97
+ end
98
+
99
+ should "enforce prerequisites by using an object's setter" do
100
+ a = Automobile.new
101
+ a.make = 'Ford'
102
+ a.model_year = 1999
103
+ a.make = nil
104
+ assert_equal nil, a.model_year
105
+ end
106
+
107
+ should "keep user-defined options on a characteristic" do
108
+ assert_equal :length, Automobile.characteristics[:daily_distance_estimate].options[:measures]
109
+ end
110
+
111
+ should "not confuse user-defined options with other options" do
112
+ assert !Automobile.characteristics[:daily_distance_estimate].options.has_key?(:trumps)
113
+ end
114
+
115
+ should "know which characteristics are 'visible'" do
116
+ a = Automobile.new
117
+ assert a.unknown_characteristics.map(&:name).include?(:record_creation_date)
118
+ assert !a.visible_unknown_characteristics.map(&:name).include?(:record_creation_date)
119
+ a.record_creation_date = 'yesterday'
120
+ assert a.known_characteristics.map(&:name).include?(:record_creation_date)
121
+ assert !a.visible_known_characteristics.map(&:name).include?(:record_creation_date)
122
+ end
123
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: characterizable
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 0
9
+ version: 0.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Andy Rossmeissl
13
+ - Seamus Abshere
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-05-11 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: blockenspiel
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ - 3
31
+ - 2
32
+ version: 0.3.2
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: activesupport
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 2
44
+ - 3
45
+ - 5
46
+ version: 2.3.5
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: activerecord
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ segments:
57
+ - 2
58
+ - 3
59
+ - 5
60
+ version: 2.3.5
61
+ type: :development
62
+ version_requirements: *id003
63
+ - !ruby/object:Gem::Dependency
64
+ name: shoulda
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ type: :development
74
+ version_requirements: *id004
75
+ description: Characterize the relationship between "attributes" (getters/setters) of instances of a class
76
+ email: seamus@abshere.net
77
+ executables: []
78
+
79
+ extensions: []
80
+
81
+ extra_rdoc_files:
82
+ - LICENSE
83
+ - README.rdoc
84
+ files:
85
+ - .document
86
+ - .gitignore
87
+ - LICENSE
88
+ - README.rdoc
89
+ - Rakefile
90
+ - VERSION
91
+ - lib/characterizable.rb
92
+ - test/helper.rb
93
+ - test/test_characterizable.rb
94
+ has_rdoc: true
95
+ homepage: http://github.com/seamusabshere/characterizable
96
+ licenses: []
97
+
98
+ post_install_message:
99
+ rdoc_options:
100
+ - --charset=UTF-8
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ segments:
108
+ - 0
109
+ version: "0"
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ segments:
115
+ - 0
116
+ version: "0"
117
+ requirements: []
118
+
119
+ rubyforge_project:
120
+ rubygems_version: 1.3.6
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: Characterize instances of a class
124
+ test_files:
125
+ - test/helper.rb
126
+ - test/test_characterizable.rb