auto_demeter 0.0.2 → 0.0.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.
data/README.md CHANGED
@@ -1,6 +1,16 @@
1
1
  # AutoDemeter
2
2
 
3
- TODO: Write a gem description
3
+ AutoDemeter is an automated delegator to associations. The name comes from the rule of demeter is a mechanism to try to
4
+ prevent the bad things that happen when that rule is violated.
5
+
6
+ It's a little like the new &. (praying dot), but also works with older versions
7
+ of Ruby.
8
+
9
+ It was created after spending hours refactoring lots of ancient code that reached through models and associations with little
10
+ regard for the fact that there could be a nil somewhere which would make the whole thing blow up and the fact that I hated
11
+ the alternative of checking nil manually at every point whilst on the route to refactoring properly.
12
+
13
+
4
14
 
5
15
  ## Installation
6
16
 
@@ -18,7 +28,21 @@ Or install it yourself as:
18
28
 
19
29
  ## Usage
20
30
 
21
- TODO: Write usage instructions here
31
+ You can replace things like:
32
+
33
+ @object.user.manager.name
34
+
35
+ with
36
+
37
+ @object.user_manager_name
38
+
39
+ and rather than blowing up when user or manager return nil, the method itself will return nil.
40
+
41
+ It also let's you do things like:
42
+
43
+ @object.users.map(&:manager_name)
44
+
45
+ without having to define manager_name on the association.
22
46
 
23
47
  ## Contributing
24
48
 
@@ -27,3 +51,9 @@ TODO: Write usage instructions here
27
51
  3. Commit your changes (`git commit -am 'Add some feature'`)
28
52
  4. Push to the branch (`git push origin my-new-feature`)
29
53
  5. Create new Pull Request
54
+
55
+ ## Todo
56
+
57
+ 1. Tests
58
+ 2. More tests around the is and is_not mechanism
59
+ 3. Potentially deprecate the is and is_not mechanism which should really be handled in a different gem.
data/auto_demeter.gemspec CHANGED
@@ -18,6 +18,17 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.3"
22
- spec.add_development_dependency "rake"
21
+ spec.add_development_dependency 'sqlite3'
22
+
23
+ if RUBY_VERSION >= '1.9'
24
+ spec.add_development_dependency 'bundler'
25
+ spec.add_development_dependency 'rake'
26
+ spec.add_development_dependency 'active_record'
27
+ spec.add_development_dependency 'simplecov'
28
+ else
29
+ spec.add_development_dependency 'bundler', '~> 1.3'
30
+ spec.add_development_dependency 'rake', '~>0.9.2'
31
+ spec.add_development_dependency 'activerecord'
32
+ spec.add_development_dependency 'rcov'
33
+ end
23
34
  end
data/lib/auto_demeter.rb CHANGED
@@ -1,14 +1,5 @@
1
- require "auto_demeter/version"
2
- require 'auto_demeter/methods'
3
-
4
- class ActiveRecord::Base
5
- include AutoDemeter
6
- end
7
-
8
- class ActiveRecord::Associations::BelongsToAssociation
9
- include AutoDemeter
10
- end
11
-
12
- class ActiveRecord::Associations::HasOneAssociation
13
- include AutoDemeter
14
- end
1
+ require (File.join(File.dirname(__FILE__), 'auto_demeter', 'version'))
2
+ require (File.join(File.dirname(__FILE__), 'auto_demeter', 'methods'))
3
+ ActiveRecord::Base.send :include, AutoDemeter
4
+ ActiveRecord::Associations::BelongsToAssociation.send :include, AutoDemeter
5
+ ActiveRecord::Associations::HasOneAssociation.send :include, AutoDemeter
@@ -1,9 +1,13 @@
1
1
  module AutoDemeter
2
+ private
3
+ def base_names
4
+ @base_names||=self.class.reflect_on_all_associations.find_all { |x| [:has_one, :belongs_to].include?(x.send(:macro)) }.map { |x| x.send(:name).to_s }
5
+ end
6
+
2
7
  def children_names
3
- base_names=self.class.reflect_on_all_associations.find_all { |x| [:has_one, :belongs_to].include?(x.instance_variable_get("@macro")) }.map { |x| x.instance_variable_get("@name").to_s }
4
8
  class_name=base_names.map { |x| x.gsub(/^#{self.class.name.underscore}_/, '') }
5
9
  class_name=class_name | base_names.map { |x| x.gsub(/^#{self.base_name.underscore}_/, '') } if self.respond_to?(:base_name) && self.class.name!=self.base_name
6
- base_names | class_name
10
+ @children_names||=base_names | class_name
7
11
  end
8
12
 
9
13
  def reflected_children_regex
@@ -11,19 +15,19 @@ module AutoDemeter
11
15
  end
12
16
 
13
17
  def respond_through_association?(method_id)
14
- return false unless children_names
15
- if (match_data=method_id.to_s.match(reflected_children_regex)) && match_data[1].present?
18
+ if children_names && (match_data=method_id.to_s.match(reflected_children_regex)) && match_data[1].present?
16
19
  association_name=self.methods.include?(match_data[1]) ? match_data[1] : "#{self.class.name.underscore}_#{match_data[1]}"
17
- if send(association_name)
18
- true
19
- else
20
- match_data[2][0..2] == 'is_' ? true : false
21
- end
20
+ send(association_name) ? true : match_data[2][0..2] == 'is_'
22
21
  else
23
22
  false
24
23
  end
25
24
  end
26
25
 
26
+ public
27
+ def respond_to?(method_id)
28
+ super || (method_id != :base_name && respond_through_association?(method_id))
29
+ end
30
+
27
31
  def method_missing(method_id, *args, &block)
28
32
  begin
29
33
  super
@@ -1,3 +1,3 @@
1
1
  module AutoDemeter
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,78 @@
1
+ require 'rubygems'
2
+ if RUBY_VERSION >= '1.9'
3
+ require 'minitest/autorun'
4
+ require 'active_record'
5
+ else
6
+ require 'test/unit'
7
+ require 'activerecord'
8
+ end
9
+
10
+ $:.unshift File.dirname(__FILE__) + '/../lib'
11
+ require File.dirname(__FILE__) + '/../lib/auto_demeter'
12
+
13
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
14
+
15
+ def setup_db
16
+ ActiveRecord::Base.logger
17
+ ActiveRecord::Schema.define(:version => 1) do
18
+ create_table :users do |t|
19
+ t.references :manager
20
+ t.string :name
21
+ end
22
+ create_table :addresses do |t|
23
+ t.references :user
24
+ t.string :postcode
25
+ end
26
+ create_table :managers do |t|
27
+ t.string :name
28
+ end
29
+ end
30
+ end
31
+
32
+ class Manager < ActiveRecord::Base
33
+ has_many :users
34
+ end
35
+
36
+ class User < ActiveRecord::Base
37
+ belongs_to :manager
38
+ has_one :address
39
+ end
40
+
41
+ class Address < ActiveRecord::Base
42
+ belongs_to :user
43
+ end
44
+
45
+ def teardown_db
46
+ ActiveRecord::Base.connection.tables.each do |table|
47
+ ActiveRecord::Base.connection.drop_table(table)
48
+ end
49
+ end
50
+
51
+ class AutoDemeterTest < (
52
+ begin
53
+ MiniTest::Test rescue Test::Unit::TestCase
54
+ end)
55
+
56
+ def setup
57
+ setup_db
58
+ @paul=Manager.create(:name => 'paul')
59
+ User.create(:name => 'ophelia')
60
+ User.create(:name => 'nigel')
61
+ @michael=User.create(:name => 'michael', :manager => @paul)
62
+ @luke=User.create(:name => 'luke', :manager => @paul)
63
+ @michael_address=Address.create(:postcode => 'n111n', :user => @michael)
64
+ @luke_address=Address.create(:postcode => 'bt401uu', :user => @luke)
65
+ Address.create(:postcode => 'gu261aa')
66
+ end
67
+
68
+ def test_happy_path
69
+ assert @luke.respond_to?(:address_postcode)
70
+ assert @luke_address.respond_to?(:user_manager_name)
71
+ assert_equal @luke.address_postcode, @luke_address.postcode
72
+ assert_equal [@michael_address.postcode, @luke_address.postcode], @paul.users.map(&:address_postcode)
73
+ assert_equal @luke.name, @luke_address.user_name
74
+ assert_equal @paul.name, @luke_address.user_manager_name
75
+ assert_equal @paul.name, @luke_address.user_manager.name
76
+ assert_equal @paul.name, @luke_address.user.manager_name
77
+ end
78
+ end
metadata CHANGED
@@ -1,56 +1,105 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: auto_demeter
3
- version: !ruby/object:Gem::Version
4
- version: 0.0.2
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 3
10
+ version: 0.0.3
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Paul McKibbin
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2013-07-02 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2016-03-19 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: sqlite3
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :development
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
15
35
  name: bundler
16
- requirement: !ruby/object:Gem::Requirement
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
17
38
  none: false
18
- requirements:
39
+ requirements:
19
40
  - - ~>
20
- - !ruby/object:Gem::Version
21
- version: '1.3'
41
+ - !ruby/object:Gem::Version
42
+ hash: 9
43
+ segments:
44
+ - 1
45
+ - 3
46
+ version: "1.3"
22
47
  type: :development
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: rake
23
51
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
52
+ requirement: &id003 !ruby/object:Gem::Requirement
25
53
  none: false
26
- requirements:
54
+ requirements:
27
55
  - - ~>
28
- - !ruby/object:Gem::Version
29
- version: '1.3'
30
- - !ruby/object:Gem::Dependency
31
- name: rake
32
- requirement: !ruby/object:Gem::Requirement
56
+ - !ruby/object:Gem::Version
57
+ hash: 63
58
+ segments:
59
+ - 0
60
+ - 9
61
+ - 2
62
+ version: 0.9.2
63
+ type: :development
64
+ version_requirements: *id003
65
+ - !ruby/object:Gem::Dependency
66
+ name: activerecord
67
+ prerelease: false
68
+ requirement: &id004 !ruby/object:Gem::Requirement
33
69
  none: false
34
- requirements:
35
- - - ! '>='
36
- - !ruby/object:Gem::Version
37
- version: '0'
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
38
77
  type: :development
78
+ version_requirements: *id004
79
+ - !ruby/object:Gem::Dependency
80
+ name: rcov
39
81
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
82
+ requirement: &id005 !ruby/object:Gem::Requirement
41
83
  none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: '0'
46
- description: Create automated methods for all children or parents to allow a request
47
- to be handled more easily than defining a long chain
48
- email:
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 3
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ type: :development
92
+ version_requirements: *id005
93
+ description: Create automated methods for all children or parents to allow a request to be handled more easily than defining a long chain
94
+ email:
49
95
  - pmckibbin@gmail.com
50
96
  executables: []
97
+
51
98
  extensions: []
99
+
52
100
  extra_rdoc_files: []
53
- files:
101
+
102
+ files:
54
103
  - .gitignore
55
104
  - Gemfile
56
105
  - LICENSE.txt
@@ -60,29 +109,39 @@ files:
60
109
  - lib/auto_demeter.rb
61
110
  - lib/auto_demeter/methods.rb
62
111
  - lib/auto_demeter/version.rb
63
- homepage: ''
64
- licenses:
112
+ - test/auto_demeter_test.rb
113
+ homepage: ""
114
+ licenses:
65
115
  - MIT
66
116
  post_install_message:
67
117
  rdoc_options: []
68
- require_paths:
118
+
119
+ require_paths:
69
120
  - lib
70
- required_ruby_version: !ruby/object:Gem::Requirement
121
+ required_ruby_version: !ruby/object:Gem::Requirement
71
122
  none: false
72
- requirements:
73
- - - ! '>='
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ hash: 3
127
+ segments:
128
+ - 0
129
+ version: "0"
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
131
  none: false
78
- requirements:
79
- - - ! '>='
80
- - !ruby/object:Gem::Version
81
- version: '0'
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ hash: 3
136
+ segments:
137
+ - 0
138
+ version: "0"
82
139
  requirements: []
140
+
83
141
  rubyforge_project:
84
- rubygems_version: 1.8.25
142
+ rubygems_version: 1.8.15
85
143
  signing_key:
86
144
  specification_version: 3
87
145
  summary: Automated demeter methods
88
- test_files: []
146
+ test_files:
147
+ - test/auto_demeter_test.rb