auto_demeter 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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