demeter 1.0.4 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,103 @@
1
+ Demeter
2
+ =======
3
+
4
+ The Law of Demeter (LoD), or Principle of Least Knowledge, is a simple design style for developing software with the following guidelines:
5
+
6
+ * Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.
7
+ * Each unit should only talk to its friends; don't talk to strangers.
8
+ * Only talk to your immediate friends.
9
+
10
+ Installation
11
+ ------------
12
+
13
+ sudo gem install demeter
14
+
15
+ Usage
16
+ -----
17
+
18
+ require "demeter"
19
+
20
+ class User
21
+ extend Demeter
22
+
23
+ demeter :address
24
+
25
+ attr_accessor :name
26
+ attr_accessor :address
27
+
28
+ def initialize
29
+ @address = Address.new
30
+ end
31
+ end
32
+
33
+ class Address
34
+ attr_accessor :country
35
+ end
36
+
37
+ user = User.new
38
+ user.address.country = "Brazil"
39
+ user.address_country
40
+ #=> Brazil
41
+
42
+ If your using ActiveRecord, you don't have to extend the `Demeter` module.
43
+
44
+ class User < ActiveRecord::Base
45
+ has_one :address
46
+ demeter :address
47
+ end
48
+
49
+ user = User.first
50
+ user.address_country
51
+
52
+ You can easily override a method that has been "demeterized"; just declare it before or after calling the `demeter` method.
53
+
54
+ class User < ActiveRecord::Base
55
+ has_one :address
56
+ demeter_address
57
+
58
+ def address_country
59
+ @address_country ||= address.country.upcase
60
+ end
61
+ end
62
+
63
+ To-Do
64
+ -----
65
+
66
+ * Allow more than one level
67
+ * Automatically create accessors
68
+ * Detect all `has_one` and `belongs_to` relations and automatically "demeterized" them on ActiveRecord
69
+ * RDoc
70
+
71
+ Maintainer
72
+ ----------
73
+
74
+ * Emerson Macedo (<http://codificando.com/>)
75
+
76
+ Contributor
77
+ -----------
78
+
79
+ * Nando Vieira (<http://simplesideias.com.br/>)
80
+
81
+ License:
82
+ --------
83
+
84
+ (The MIT License)
85
+
86
+ Permission is hereby granted, free of charge, to any person obtaining
87
+ a copy of this software and associated documentation files (the
88
+ 'Software'), to deal in the Software without restriction, including
89
+ without limitation the rights to use, copy, modify, merge, publish,
90
+ distribute, sublicense, and/or sell copies of the Software, and to
91
+ permit persons to whom the Software is furnished to do so, subject to
92
+ the following conditions:
93
+
94
+ The above copyright notice and this permission notice shall be
95
+ included in all copies or substantial portions of the Software.
96
+
97
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
98
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
99
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
100
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
101
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
102
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
103
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile CHANGED
@@ -1,39 +1,38 @@
1
- require "spec/rake/spectask"
2
- require "rake/gempackagetask"
3
-
4
- spec = Gem::Specification.new do |s|
5
- s.name = %q{demeter}
6
- s.version = "1.0.4"
7
- s.authors = ['Emerson Macedo']
8
- s.email = ['emerleite@gmail.com']
9
- s.date = %q{2009-11-11}
10
- s.homepage = 'http://github.com/emerleite/demeter'
11
-
12
- s.summary = %q{An easy way to apply law of demeter to your objects}
13
- s.description = %q{An easy way to apply law of demeter to your objects}
14
- s.require_paths = ["lib"]
15
- s.rubygems_version = %q{1.3.5}
16
-
17
- s.files = ['Rakefile',
18
- 'README.md',
19
- 'LICENSE.txt',
20
- 'TODO.txt',
21
- 'lib/demeter.rb',
22
- 'spec/demeter_spec.rb',
23
- ]
24
- end
1
+ require 'rake'
2
+ require 'spec/rake/spectask'
3
+ require 'lib/demeter/version'
4
+ require 'jeweler'
5
+
6
+ desc 'Default: run specs.'
7
+ task :default => :spec
25
8
 
26
- Rake::GemPackageTask.new(spec) do |pkg|
27
- pkg.need_zip = true
28
- pkg.need_tar = true
9
+ desc 'Run the specs'
10
+ Spec::Rake::SpecTask.new(:spec) do |t|
11
+ t.spec_opts = ['--colour --format specdoc --loadby mtime --reverse']
12
+ t.spec_files = FileList['spec/**/*_spec.rb']
13
+
14
+ t.rcov = true
15
+ t.rcov_opts = %w{--exclude spec,rcov,activerecord,active_support,activesupport,builder,sqlite,json}
29
16
  end
30
17
 
31
- Spec::Rake::SpecTask.new do |t|
32
- t.libs << 'lib'
33
- t.spec_files = FileList['spec/*_spec.rb']
34
- t.rcov = true
35
- t.rcov_opts = %w{--exclude spec,rcov}
36
- t.fail_on_error = false
18
+ JEWEL = Jeweler::Tasks.new do |gem|
19
+ gem.name = "demeter"
20
+ gem.version = Demeter::Version::STRING
21
+ gem.summary = "A simple way to apply the Law of Demeter to your Ruby objects."
22
+ gem.description = "A simple way to apply the Law of Demeter to your Ruby objects."
23
+
24
+ gem.authors = ["Emerson Macedo"]
25
+ gem.email = "emerleite@gmail.com"
26
+ gem.homepage = "http://github.com/emerleite/demeter"
27
+
28
+ gem.has_rdoc = false
29
+ gem.files = %w(Rakefile demeter.gemspec VERSION README.markdown) + Dir["{lib,spec}/**/*"]
37
30
  end
38
31
 
39
- task :default => [:spec]
32
+ desc "Generate gemspec and build gem"
33
+ task :build_gem do
34
+ File.open("VERSION", "w+") {|f| f << Demeter::Version::STRING }
35
+
36
+ Rake::Task["gemspec"].invoke
37
+ Rake::Task["build"].invoke
38
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.5
@@ -0,0 +1,57 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{demeter}
8
+ s.version = "1.0.5"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Emerson Macedo"]
12
+ s.date = %q{2010-01-05}
13
+ s.description = %q{A simple way to apply the Law of Demeter to your Ruby objects.}
14
+ s.email = %q{emerleite@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README.markdown"
17
+ ]
18
+ s.files = [
19
+ "README.markdown",
20
+ "Rakefile",
21
+ "VERSION",
22
+ "demeter.gemspec",
23
+ "lib/demeter.rb",
24
+ "lib/demeter/active_record.rb",
25
+ "lib/demeter/version.rb",
26
+ "spec/demeter/active_record_spec.rb",
27
+ "spec/demeter/demeter_spec.rb",
28
+ "spec/resources/classes.rb",
29
+ "spec/resources/models.rb",
30
+ "spec/schema.rb",
31
+ "spec/spec_helper.rb"
32
+ ]
33
+ s.homepage = %q{http://github.com/emerleite/demeter}
34
+ s.rdoc_options = ["--charset=UTF-8"]
35
+ s.require_paths = ["lib"]
36
+ s.rubygems_version = %q{1.3.5}
37
+ s.summary = %q{A simple way to apply the Law of Demeter to your Ruby objects.}
38
+ s.test_files = [
39
+ "spec/demeter/active_record_spec.rb",
40
+ "spec/demeter/demeter_spec.rb",
41
+ "spec/resources/classes.rb",
42
+ "spec/resources/models.rb",
43
+ "spec/schema.rb",
44
+ "spec/spec_helper.rb"
45
+ ]
46
+
47
+ if s.respond_to? :specification_version then
48
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
49
+ s.specification_version = 3
50
+
51
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
52
+ else
53
+ end
54
+ else
55
+ end
56
+ end
57
+
@@ -1,32 +1,45 @@
1
1
  module Demeter
2
- def self.demeter_objects
3
- @@demeter_objects
4
- end
5
-
6
- def self.extended(base)
7
- @@demeter_objects = @@demeter_objects ||= Hash.new
8
- @@demeter_objects[base.to_s.to_sym] = Array.new
9
- base.send(:alias_method, :old_method_missing, :method_missing)
10
- base.send(:include, DemeterMethods)
11
- base.send(:alias_method, :method_missing, :demeter_method_missing)
2
+ def self.extended(base)
3
+ base.class_eval do
4
+ include InstanceMethods
5
+ extend ClassMethods
6
+ end
12
7
  end
13
-
14
- def demeter(*symbols)
15
- symbols.each do |symbol|
16
- @@demeter_objects[self.to_s.to_sym] << symbol
8
+
9
+ module InstanceMethods
10
+ def method_missing(method_name, *attrs, &block)
11
+ object_method_name = method_name.to_s
12
+ object_name = self.class.demeter_names.find {|name| object_method_name =~ /^#{name}_/ }
13
+
14
+ return super unless object_name
15
+
16
+ object_method_name.gsub!(/^#{object_name}_/, "")
17
+
18
+ instance_eval <<-TXT
19
+ def #{method_name} # def address_street
20
+ #{object_name}.#{object_method_name} if #{object_name} # address.street
21
+ end # end
22
+ TXT
23
+
24
+ send(method_name)
17
25
  end
18
26
  end
19
27
 
20
- module DemeterMethods
21
- def demeter_method_missing(method, *args, &block)
22
- message_split = method.to_s.split("_")
23
- if Demeter.demeter_objects[self.class.to_s.to_sym].select { |object| message_split.first.to_sym == object }.length == 0
24
- old_method_missing(method, *args, &block)
25
- else
26
- object = self.send(message_split.first)
27
- message_split.delete message_split.first
28
- object ? object.send(message_split.join("_")) : nil
29
- end
28
+ module ClassMethods
29
+ def demeter(*attr_names)
30
+ @@demeter_names ||= []
31
+ @@demeter_names += attr_names
32
+ end
33
+
34
+ def demeter_names
35
+ @@demeter_names
36
+ end
37
+
38
+ def demeter_names=(names)
39
+ @@demeter_names = names
30
40
  end
31
41
  end
32
42
  end
43
+
44
+ # ActiveRecord support
45
+ require "demeter/active_record"
@@ -0,0 +1,3 @@
1
+ ActiveRecord::Base.class_eval do
2
+ extend ::Demeter
3
+ end if defined? ActiveRecord::Base
@@ -0,0 +1,8 @@
1
+ module Demeter
2
+ module Version
3
+ MAJOR = "1"
4
+ MINOR = "0"
5
+ PATCH = "5"
6
+ STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
7
+ end
8
+ end
@@ -0,0 +1,14 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ describe "Demeter on ActiveRecord" do
4
+ it "should respond to demeter method" do
5
+ ActiveRecord::Base.should respond_to(:demeter)
6
+ end
7
+
8
+ it "should dispatch original method missing" do
9
+ Task.demeter :project
10
+
11
+ task = Task.create!(:name => "Do the right thing", :project_attributes => {:name => "Amazing Project"})
12
+ Task.find_by_name("Do the right thing").should == task
13
+ end
14
+ end
@@ -0,0 +1,68 @@
1
+ require File.dirname(__FILE__) + "/../spec_helper"
2
+
3
+ describe "Demeter" do
4
+ subject { User.new }
5
+
6
+ before do
7
+ User.demeter :address, :video_game
8
+
9
+ subject.name = "John"
10
+ subject.address.street = "Some street"
11
+ subject.address.zip_code = "98005"
12
+ subject.video_game.title = "God of War 3"
13
+ subject.video_game.production_year = 1999
14
+ subject.profile.interests = %w(games programming music movies)
15
+ end
16
+
17
+ it "should allow demeter only one object" do
18
+ Person.demeter :animal
19
+ person = Person.new
20
+ person.animal.name = "marley"
21
+
22
+ person.animal_name.should == "marley"
23
+ end
24
+
25
+ it "should not delegate existing methods" do
26
+ subject.name.should == "John"
27
+ end
28
+
29
+ it "should delegate methods from address object" do
30
+ subject.address_street.should == "Some street"
31
+ subject.address_zip_code.should == "98005"
32
+ end
33
+
34
+ it "should delegate methods from video game object" do
35
+ subject.video_game_title.should == "God of War 3"
36
+ subject.video_game_production_year.should == 1999
37
+ end
38
+
39
+ it "should return nil when demeter object is not set" do
40
+ subject.address = nil
41
+ subject.address_title.should be_nil
42
+ end
43
+
44
+ it "should raise exception when method is not defined on the demeter class" do
45
+ doing { subject.address_foo }.should raise_error(NoMethodError)
46
+ end
47
+
48
+ it "should not delegate unset objects" do
49
+ doing { subject.profile_interests }.should raise_error(NoMethodError)
50
+ end
51
+
52
+ it "should override demeter method" do
53
+ subject.instance_eval do
54
+ def address_street
55
+ address.street.upcase
56
+ end
57
+ end
58
+
59
+ subject.address_street.should == "SOME STREET"
60
+ end
61
+
62
+ it "should replace demeter names" do
63
+ User.demeter_names = []
64
+ User.demeter_names.should == []
65
+
66
+ doing { subject.address_title }.should raise_error(NoMethodError)
67
+ end
68
+ end
@@ -0,0 +1,44 @@
1
+ class User
2
+ attr_accessor :name
3
+ attr_accessor :address
4
+ attr_accessor :video_game
5
+ attr_accessor :profile
6
+
7
+ extend Demeter
8
+
9
+ def initialize
10
+ @video_game = VideoGame.new
11
+ @address = Address.new
12
+ @profile = Profile.new
13
+ end
14
+ end
15
+
16
+ class Address
17
+ attr_accessor :street
18
+ attr_accessor :city
19
+ attr_accessor :country
20
+ attr_accessor :state
21
+ attr_accessor :zip_code
22
+ end
23
+
24
+ class VideoGame
25
+ attr_accessor :title
26
+ attr_accessor :production_year
27
+ end
28
+
29
+ class Profile
30
+ attr_accessor :interests
31
+ end
32
+
33
+ class Person
34
+ extend Demeter
35
+ attr_accessor :animal
36
+
37
+ def initialize
38
+ @animal = Animal.new
39
+ end
40
+ end
41
+
42
+ class Animal
43
+ attr_accessor :name
44
+ end
@@ -0,0 +1,14 @@
1
+ class Project < ActiveRecord::Base
2
+ has_many :tasks
3
+ end
4
+
5
+ class Task < ActiveRecord::Base
6
+ belongs_to :project
7
+ has_one :owner
8
+
9
+ accepts_nested_attributes_for :project
10
+ end
11
+
12
+ class Owner < ActiveRecord::Base
13
+ belongs_to :task
14
+ end
@@ -0,0 +1,15 @@
1
+ ActiveRecord::Schema.define(:version => 0) do
2
+ create_table :projects do |t|
3
+ t.string :name
4
+ end
5
+
6
+ create_table :tasks do |t|
7
+ t.string :name
8
+ t.references :owner, :project
9
+ end
10
+
11
+ create_table :owners do |t|
12
+ t.string :name
13
+ t.references :owner
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ require "rubygems"
2
+ require "spec"
3
+ require "benchmark"
4
+ require "active_record"
5
+
6
+ # Load library
7
+ require "demeter"
8
+
9
+ # Establish connection with in memory SQLite 3 database
10
+ ActiveRecord::Base.establish_connection :adapter => "sqlite3", :database => ":memory:"
11
+
12
+ # Load database schema
13
+ load File.dirname(__FILE__) + "/schema.rb"
14
+
15
+ # Load resources
16
+ require File.dirname(__FILE__) + "/resources/classes"
17
+ require File.dirname(__FILE__) + "/resources/models"
18
+
19
+ # Create an alias for lambda
20
+ alias :doing :lambda
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: demeter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Emerson Macedo
@@ -9,33 +9,39 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-11 00:00:00 -02:00
12
+ date: 2010-01-05 00:00:00 -02:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
16
- description: An easy way to apply law of demeter to your objects
17
- email:
18
- - emerleite@gmail.com
16
+ description: A simple way to apply the Law of Demeter to your Ruby objects.
17
+ email: emerleite@gmail.com
19
18
  executables: []
20
19
 
21
20
  extensions: []
22
21
 
23
- extra_rdoc_files: []
24
-
22
+ extra_rdoc_files:
23
+ - README.markdown
25
24
  files:
25
+ - README.markdown
26
26
  - Rakefile
27
- - README.md
28
- - LICENSE.txt
29
- - TODO.txt
27
+ - VERSION
28
+ - demeter.gemspec
30
29
  - lib/demeter.rb
31
- - spec/demeter_spec.rb
30
+ - lib/demeter/active_record.rb
31
+ - lib/demeter/version.rb
32
+ - spec/demeter/active_record_spec.rb
33
+ - spec/demeter/demeter_spec.rb
34
+ - spec/resources/classes.rb
35
+ - spec/resources/models.rb
36
+ - spec/schema.rb
37
+ - spec/spec_helper.rb
32
38
  has_rdoc: true
33
39
  homepage: http://github.com/emerleite/demeter
34
40
  licenses: []
35
41
 
36
42
  post_install_message:
37
- rdoc_options: []
38
-
43
+ rdoc_options:
44
+ - --charset=UTF-8
39
45
  require_paths:
40
46
  - lib
41
47
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -56,6 +62,11 @@ rubyforge_project:
56
62
  rubygems_version: 1.3.5
57
63
  signing_key:
58
64
  specification_version: 3
59
- summary: An easy way to apply law of demeter to your objects
60
- test_files: []
61
-
65
+ summary: A simple way to apply the Law of Demeter to your Ruby objects.
66
+ test_files:
67
+ - spec/demeter/active_record_spec.rb
68
+ - spec/demeter/demeter_spec.rb
69
+ - spec/resources/classes.rb
70
+ - spec/resources/models.rb
71
+ - spec/schema.rb
72
+ - spec/spec_helper.rb
@@ -1,202 +0,0 @@
1
-
2
- Apache License
3
- Version 2.0, January 2004
4
- http://www.apache.org/licenses/
5
-
6
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
-
8
- 1. Definitions.
9
-
10
- "License" shall mean the terms and conditions for use, reproduction,
11
- and distribution as defined by Sections 1 through 9 of this document.
12
-
13
- "Licensor" shall mean the copyright owner or entity authorized by
14
- the copyright owner that is granting the License.
15
-
16
- "Legal Entity" shall mean the union of the acting entity and all
17
- other entities that control, are controlled by, or are under common
18
- control with that entity. For the purposes of this definition,
19
- "control" means (i) the power, direct or indirect, to cause the
20
- direction or management of such entity, whether by contract or
21
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
- outstanding shares, or (iii) beneficial ownership of such entity.
23
-
24
- "You" (or "Your") shall mean an individual or Legal Entity
25
- exercising permissions granted by this License.
26
-
27
- "Source" form shall mean the preferred form for making modifications,
28
- including but not limited to software source code, documentation
29
- source, and configuration files.
30
-
31
- "Object" form shall mean any form resulting from mechanical
32
- transformation or translation of a Source form, including but
33
- not limited to compiled object code, generated documentation,
34
- and conversions to other media types.
35
-
36
- "Work" shall mean the work of authorship, whether in Source or
37
- Object form, made available under the License, as indicated by a
38
- copyright notice that is included in or attached to the work
39
- (an example is provided in the Appendix below).
40
-
41
- "Derivative Works" shall mean any work, whether in Source or Object
42
- form, that is based on (or derived from) the Work and for which the
43
- editorial revisions, annotations, elaborations, or other modifications
44
- represent, as a whole, an original work of authorship. For the purposes
45
- of this License, Derivative Works shall not include works that remain
46
- separable from, or merely link (or bind by name) to the interfaces of,
47
- the Work and Derivative Works thereof.
48
-
49
- "Contribution" shall mean any work of authorship, including
50
- the original version of the Work and any modifications or additions
51
- to that Work or Derivative Works thereof, that is intentionally
52
- submitted to Licensor for inclusion in the Work by the copyright owner
53
- or by an individual or Legal Entity authorized to submit on behalf of
54
- the copyright owner. For the purposes of this definition, "submitted"
55
- means any form of electronic, verbal, or written communication sent
56
- to the Licensor or its representatives, including but not limited to
57
- communication on electronic mailing lists, source code control systems,
58
- and issue tracking systems that are managed by, or on behalf of, the
59
- Licensor for the purpose of discussing and improving the Work, but
60
- excluding communication that is conspicuously marked or otherwise
61
- designated in writing by the copyright owner as "Not a Contribution."
62
-
63
- "Contributor" shall mean Licensor and any individual or Legal Entity
64
- on behalf of whom a Contribution has been received by Licensor and
65
- subsequently incorporated within the Work.
66
-
67
- 2. Grant of Copyright License. Subject to the terms and conditions of
68
- this License, each Contributor hereby grants to You a perpetual,
69
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
- copyright license to reproduce, prepare Derivative Works of,
71
- publicly display, publicly perform, sublicense, and distribute the
72
- Work and such Derivative Works in Source or Object form.
73
-
74
- 3. Grant of Patent License. Subject to the terms and conditions of
75
- this License, each Contributor hereby grants to You a perpetual,
76
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
- (except as stated in this section) patent license to make, have made,
78
- use, offer to sell, sell, import, and otherwise transfer the Work,
79
- where such license applies only to those patent claims licensable
80
- by such Contributor that are necessarily infringed by their
81
- Contribution(s) alone or by combination of their Contribution(s)
82
- with the Work to which such Contribution(s) was submitted. If You
83
- institute patent litigation against any entity (including a
84
- cross-claim or counterclaim in a lawsuit) alleging that the Work
85
- or a Contribution incorporated within the Work constitutes direct
86
- or contributory patent infringement, then any patent licenses
87
- granted to You under this License for that Work shall terminate
88
- as of the date such litigation is filed.
89
-
90
- 4. Redistribution. You may reproduce and distribute copies of the
91
- Work or Derivative Works thereof in any medium, with or without
92
- modifications, and in Source or Object form, provided that You
93
- meet the following conditions:
94
-
95
- (a) You must give any other recipients of the Work or
96
- Derivative Works a copy of this License; and
97
-
98
- (b) You must cause any modified files to carry prominent notices
99
- stating that You changed the files; and
100
-
101
- (c) You must retain, in the Source form of any Derivative Works
102
- that You distribute, all copyright, patent, trademark, and
103
- attribution notices from the Source form of the Work,
104
- excluding those notices that do not pertain to any part of
105
- the Derivative Works; and
106
-
107
- (d) If the Work includes a "NOTICE" text file as part of its
108
- distribution, then any Derivative Works that You distribute must
109
- include a readable copy of the attribution notices contained
110
- within such NOTICE file, excluding those notices that do not
111
- pertain to any part of the Derivative Works, in at least one
112
- of the following places: within a NOTICE text file distributed
113
- as part of the Derivative Works; within the Source form or
114
- documentation, if provided along with the Derivative Works; or,
115
- within a display generated by the Derivative Works, if and
116
- wherever such third-party notices normally appear. The contents
117
- of the NOTICE file are for informational purposes only and
118
- do not modify the License. You may add Your own attribution
119
- notices within Derivative Works that You distribute, alongside
120
- or as an addendum to the NOTICE text from the Work, provided
121
- that such additional attribution notices cannot be construed
122
- as modifying the License.
123
-
124
- You may add Your own copyright statement to Your modifications and
125
- may provide additional or different license terms and conditions
126
- for use, reproduction, or distribution of Your modifications, or
127
- for any such Derivative Works as a whole, provided Your use,
128
- reproduction, and distribution of the Work otherwise complies with
129
- the conditions stated in this License.
130
-
131
- 5. Submission of Contributions. Unless You explicitly state otherwise,
132
- any Contribution intentionally submitted for inclusion in the Work
133
- by You to the Licensor shall be under the terms and conditions of
134
- this License, without any additional terms or conditions.
135
- Notwithstanding the above, nothing herein shall supersede or modify
136
- the terms of any separate license agreement you may have executed
137
- with Licensor regarding such Contributions.
138
-
139
- 6. Trademarks. This License does not grant permission to use the trade
140
- names, trademarks, service marks, or product names of the Licensor,
141
- except as required for reasonable and customary use in describing the
142
- origin of the Work and reproducing the content of the NOTICE file.
143
-
144
- 7. Disclaimer of Warranty. Unless required by applicable law or
145
- agreed to in writing, Licensor provides the Work (and each
146
- Contributor provides its Contributions) on an "AS IS" BASIS,
147
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
- implied, including, without limitation, any warranties or conditions
149
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
- PARTICULAR PURPOSE. You are solely responsible for determining the
151
- appropriateness of using or redistributing the Work and assume any
152
- risks associated with Your exercise of permissions under this License.
153
-
154
- 8. Limitation of Liability. In no event and under no legal theory,
155
- whether in tort (including negligence), contract, or otherwise,
156
- unless required by applicable law (such as deliberate and grossly
157
- negligent acts) or agreed to in writing, shall any Contributor be
158
- liable to You for damages, including any direct, indirect, special,
159
- incidental, or consequential damages of any character arising as a
160
- result of this License or out of the use or inability to use the
161
- Work (including but not limited to damages for loss of goodwill,
162
- work stoppage, computer failure or malfunction, or any and all
163
- other commercial damages or losses), even if such Contributor
164
- has been advised of the possibility of such damages.
165
-
166
- 9. Accepting Warranty or Additional Liability. While redistributing
167
- the Work or Derivative Works thereof, You may choose to offer,
168
- and charge a fee for, acceptance of support, warranty, indemnity,
169
- or other liability obligations and/or rights consistent with this
170
- License. However, in accepting such obligations, You may act only
171
- on Your own behalf and on Your sole responsibility, not on behalf
172
- of any other Contributor, and only if You agree to indemnify,
173
- defend, and hold each Contributor harmless for any liability
174
- incurred by, or claims asserted against, such Contributor by reason
175
- of your accepting any such warranty or additional liability.
176
-
177
- END OF TERMS AND CONDITIONS
178
-
179
- APPENDIX: How to apply the Apache License to your work.
180
-
181
- To apply the Apache License to your work, attach the following
182
- boilerplate notice, with the fields enclosed by brackets "[]"
183
- replaced with your own identifying information. (Don't include
184
- the brackets!) The text should be enclosed in the appropriate
185
- comment syntax for the file format. We also recommend that a
186
- file or class name and description of purpose be included on the
187
- same "printed page" as the copyright notice for easier
188
- identification within third-party archives.
189
-
190
- Copyright [yyyy] [name of copyright owner]
191
-
192
- Licensed under the Apache License, Version 2.0 (the "License");
193
- you may not use this file except in compliance with the License.
194
- You may obtain a copy of the License at
195
-
196
- http://www.apache.org/licenses/LICENSE-2.0
197
-
198
- Unless required by applicable law or agreed to in writing, software
199
- distributed under the License is distributed on an "AS IS" BASIS,
200
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
- See the License for the specific language governing permissions and
202
- limitations under the License.
data/README.md DELETED
@@ -1,56 +0,0 @@
1
- ## Demeter
2
-
3
- A simple way to apply the Law of Demeter to your objects.
4
-
5
- ## Instalation
6
-
7
- It might not be a bad idea to make sure you are running the latest RubyGems:
8
-
9
- sudo gem update --system
10
-
11
- Install demeter gem from gemcutter
12
-
13
- sudo gem sources -a http://gemcutter.org
14
- sudo gem install demeter
15
-
16
- ## Usuage
17
-
18
- The usuage is very straightforward. You only need to extend one module and use one method.
19
-
20
- ## Example
21
-
22
- require 'demeter'
23
- class Customer
24
- attr_accessor :name
25
- end
26
-
27
- class Manager
28
- attr_accessor :type
29
- end
30
-
31
- class Account
32
- extend Demeter
33
- attr_accessor :customer, :manager
34
- demeter :customer, :manager
35
- end
36
-
37
- c = Customer.new
38
- c.name = "Emerson"
39
-
40
- m = Manager.new
41
- m.type = "General"
42
-
43
- a = Account.new
44
- a.customer = c
45
- a.manager = m
46
- puts a.customer_name #Should print Emerson at console
47
- puts a.manager_type #Should print General at console
48
-
49
- ## Credits
50
- #### Author: Emerson Macedo
51
- #### email: emerleite at gmail dot com
52
- #### twitter: emerleite
53
- #### github: github dot com slash emerleite
54
-
55
- ## Licence
56
- See LICENCE.txt
data/TODO.txt DELETED
@@ -1,3 +0,0 @@
1
- - Allow more than one level of demeter
2
- - Create acessors when not yet created
3
- - Rdoc
@@ -1,264 +0,0 @@
1
- require 'spec'
2
- require 'lib/demeter'
3
-
4
- describe Demeter do
5
- before do
6
- AClass = Class.new
7
- AClass.send(:extend, Demeter)
8
-
9
- Person = Class.new
10
- Animal = Class.new
11
- end
12
-
13
- it 'Should provide demeter class method when module extended' do
14
- AClass.respond_to?(:demeter).should be_true
15
- end
16
-
17
- it 'Should receive an object when demeter' do
18
- AClass.demeter :some_object
19
- end
20
-
21
- it 'Should get value for name when invoke person_name' do
22
- Person.send(:attr_accessor, :name)
23
-
24
- AClass.send(:attr_accessor, :person)
25
- AClass.demeter :person
26
- instance = AClass.new
27
-
28
- person = Person.new
29
- person.name = "emerson"
30
-
31
- instance.person = person
32
- instance.person_name.should be_eql("emerson")
33
-
34
- person2 = Person.new
35
- person2.name = "patricia"
36
-
37
- instance.person = person2
38
- instance.person_name.should be_eql("patricia")
39
- end
40
-
41
- it 'Should get value for gender when invoke person_gender' do
42
- Person.send(:attr_accessor, :gender)
43
-
44
- AClass.send(:attr_accessor, :person)
45
- AClass.demeter :person
46
- instance = AClass.new
47
-
48
- person = Person.new
49
- person.gender = "male"
50
-
51
- instance.person = person
52
- instance.person_gender.should be_eql("male")
53
-
54
- person2 = Person.new
55
- person2.gender = "female"
56
-
57
- instance.person = person2
58
- instance.person_gender.should be_eql("female")
59
- end
60
-
61
- it 'Should allow attribute with undescore' do
62
- Person.send(:attr_accessor, :phone_number)
63
- Person.send(:attr_accessor, :three_undescore_method)
64
-
65
- AClass.send(:attr_accessor, :person)
66
- AClass.demeter :person
67
- instance = AClass.new
68
-
69
- person = Person.new
70
- person.phone_number = 99999999
71
- person.three_undescore_method = "nothing"
72
-
73
- instance.person = person
74
- instance.person_phone_number.should be_eql(99999999)
75
- instance.person_three_undescore_method.should be_eql("nothing")
76
- end
77
-
78
- it 'Should raise error if object is not demetered' do
79
- Person.send(:attr_accessor, :phone_number)
80
-
81
- AClass.send(:attr_accessor, :person)
82
- AClass.demeter :animal
83
- instance = AClass.new
84
-
85
- person = Person.new
86
- person.phone_number = 99999999
87
-
88
- instance.person = person
89
- lambda {instance.person_phone_number}.should raise_error(NoMethodError)
90
- end
91
-
92
- it 'Should demeter 2 attribute objects' do
93
-
94
- Animal.send(:attr_accessor, :name)
95
-
96
- Person.send(:attr_accessor, :phone_number)
97
-
98
- AClass.send(:attr_accessor, :person)
99
- AClass.send(:attr_accessor, :animal)
100
- AClass.demeter :person
101
- AClass.demeter :animal
102
-
103
- instance = AClass.new
104
-
105
- person = Person.new
106
- person.phone_number = 99999999
107
-
108
- animal = Animal.new
109
- animal.name = "marley"
110
-
111
- instance.person = person
112
- instance.animal = animal
113
- instance.person_phone_number.should be_eql(99999999)
114
- instance.animal_name.should be_eql("marley")
115
- end
116
-
117
- it 'Should allow to extend Demeter in 2 classes' do
118
- Animal.send(:attr_accessor, :name)
119
-
120
- Person.send(:attr_accessor, :phone_number)
121
-
122
- AClass.send(:attr_accessor, :person)
123
- AClass.send(:attr_accessor, :animal)
124
- AClass.demeter :person
125
- AClass.demeter :animal
126
-
127
- ASecondClass = AClass
128
-
129
- instance = AClass.new
130
-
131
- person = Person.new
132
- person.phone_number = 99999999
133
-
134
- animal = Animal.new
135
- animal.name = "marley"
136
-
137
- instance.person = person
138
- instance.animal = animal
139
- instance.person_phone_number.should be_eql(99999999)
140
- instance.animal_name.should be_eql("marley")
141
-
142
- instance2 = ASecondClass.new
143
-
144
- person2 = Person.new
145
- person2.phone_number = 88888888
146
-
147
- animal2 = Animal.new
148
- animal2.name = "fox"
149
-
150
- instance2.person = person2
151
- instance2.animal = animal2
152
- instance2.person_phone_number.should be_eql(88888888)
153
- instance2.animal_name.should be_eql("fox")
154
- end
155
-
156
- it 'Should demeter 2 attributes with one call' do
157
- Animal.send(:attr_accessor, :name)
158
-
159
- Person.send(:attr_accessor, :phone_number)
160
-
161
- AClass.send(:attr_accessor, :person)
162
- AClass.send(:attr_accessor, :animal)
163
- AClass.demeter :person, :animal
164
-
165
- instance = AClass.new
166
-
167
- person = Person.new
168
- person.phone_number = 99999999
169
-
170
- animal = Animal.new
171
- animal.name = "marley"
172
-
173
- instance.person = person
174
- instance.animal = animal
175
- instance.person_phone_number.should be_eql(99999999)
176
- instance.animal_name.should be_eql("marley")
177
- end
178
-
179
- it 'Should get value when instance attribute have diferent name' do
180
- Person.class_eval do
181
- define_method :initialize do |name|
182
- @a_name = name
183
- end
184
- define_method :name do
185
- @a_name
186
- end
187
- end
188
-
189
- AClass.send(:attr_accessor, :person)
190
- AClass.demeter :person
191
- instance = AClass.new
192
-
193
- person = Person.new "emerson"
194
-
195
- instance.person = person
196
- instance.person_name.should be_eql("emerson")
197
- end
198
-
199
- it 'Should allow override the demeter method' do
200
- Person.send(:attr_accessor, :name)
201
-
202
- AClass.send(:attr_accessor, :person)
203
- AClass.demeter :person
204
- AClass.class_eval do
205
- define_method :person_name do
206
- "name overrided"
207
- end
208
- end
209
- instance = AClass.new
210
-
211
- person = Person.new
212
- person.name = "emerson"
213
-
214
- instance.person = person
215
- instance.person_name.should be_eql("name overrided")
216
- end
217
-
218
- it 'Should return nil when demetered object is nil' do
219
- AClass.send(:attr_accessor, :person)
220
- AClass.demeter :person
221
-
222
- instance = AClass.new
223
- instance.person_name.should be_nil
224
- end
225
-
226
- it 'Should invoke old method missing when not demeter' do
227
- AClass.class_eval do
228
- define_method :method_missing do | method, *args |
229
- "original #{method}"
230
- end
231
- end
232
-
233
- AClass.send(:attr_accessor, :person)
234
- AClass.demeter :person
235
-
236
- instance = AClass.new
237
- instance.some_method.should be_eql("original some_method")
238
- end
239
-
240
- it 'Should demeter when have old method missing but invoke demetered method' do
241
- AClass = Class.new
242
- AClass.class_eval do
243
- define_method :method_missing do | method, *args |
244
- "original #{method}"
245
- end
246
- end
247
- AClass.send(:extend, Demeter)
248
-
249
- Person = Class.new
250
- Person.send(:attr_accessor, :name)
251
-
252
- AClass.send(:attr_accessor, :person)
253
- AClass.demeter :person
254
-
255
- instance = AClass.new
256
-
257
- person = Person.new
258
- person.name = "emerson"
259
-
260
- instance.person = person
261
- puts instance.person_name
262
- instance.person_name.should be_eql("emerson")
263
- end
264
- end