immutability 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.
- checksums.yaml +15 -0
- data/.coveralls.yml +2 -0
- data/.gitignore +9 -0
- data/.metrics +9 -0
- data/.rspec +2 -0
- data/.rubocop.yml +2 -0
- data/.travis.yml +24 -0
- data/.yardopts +3 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +7 -0
- data/Guardfile +14 -0
- data/LICENSE +21 -0
- data/README.md +201 -0
- data/Rakefile +34 -0
- data/config/metrics/STYLEGUIDE +230 -0
- data/config/metrics/cane.yml +5 -0
- data/config/metrics/churn.yml +6 -0
- data/config/metrics/flay.yml +2 -0
- data/config/metrics/metric_fu.yml +14 -0
- data/config/metrics/reek.yml +1 -0
- data/config/metrics/roodi.yml +24 -0
- data/config/metrics/rubocop.yml +71 -0
- data/config/metrics/saikuro.yml +3 -0
- data/config/metrics/simplecov.yml +6 -0
- data/config/metrics/yardstick.yml +37 -0
- data/immutability.gemspec +25 -0
- data/lib/immutability.rb +126 -0
- data/lib/immutability/rspec.rb +4 -0
- data/lib/immutability/version.rb +9 -0
- data/lib/immutability/with_memory.rb +70 -0
- data/spec/shared/user.rb +16 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/support/immutable.rb +25 -0
- data/spec/unit/immutability/with_memory_spec.rb +101 -0
- data/spec/unit/immutability_spec.rb +63 -0
- metadata +113 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
---
|
2
|
+
folders: # The list of folders to be used by any metric.
|
3
|
+
- lib
|
4
|
+
metrics: # The list of allowed metrics. The other metrics are disabled.
|
5
|
+
- cane
|
6
|
+
- churn
|
7
|
+
- flay
|
8
|
+
- flog
|
9
|
+
- reek
|
10
|
+
- roodi
|
11
|
+
- saikuro
|
12
|
+
format: html
|
13
|
+
output: tmp/metric_fu
|
14
|
+
verbose: false
|
@@ -0,0 +1 @@
|
|
1
|
+
---
|
@@ -0,0 +1,24 @@
|
|
1
|
+
---
|
2
|
+
AssignmentInConditionalCheck:
|
3
|
+
CaseMissingElseCheck:
|
4
|
+
ClassLineCountCheck:
|
5
|
+
line_count: 100
|
6
|
+
ClassNameCheck:
|
7
|
+
pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
|
8
|
+
ClassVariableCheck:
|
9
|
+
CyclomaticComplexityBlockCheck:
|
10
|
+
complexity: 2
|
11
|
+
CyclomaticComplexityMethodCheck:
|
12
|
+
complexity: 3
|
13
|
+
EmptyRescueBodyCheck:
|
14
|
+
ForLoopCheck:
|
15
|
+
MethodLineCountCheck:
|
16
|
+
line_count: 6
|
17
|
+
MethodNameCheck:
|
18
|
+
pattern: !ruby/regexp /^[\||\^|\&|\!]$|^[_a-z<>=\[|+-\/\*`]+[_a-z0-9_<>=~@\[\]]*[=!\?]?$/
|
19
|
+
ModuleLineCountCheck:
|
20
|
+
line_count: 120
|
21
|
+
ModuleNameCheck:
|
22
|
+
pattern: !ruby/regexp /^[A-Z][a-zA-Z0-9]*$/
|
23
|
+
ParameterNumberCheck:
|
24
|
+
parameter_count: 4
|
@@ -0,0 +1,71 @@
|
|
1
|
+
---
|
2
|
+
AllCops:
|
3
|
+
Exclude:
|
4
|
+
- '**/db/schema.rb'
|
5
|
+
|
6
|
+
Lint/HandleExceptions:
|
7
|
+
Exclude:
|
8
|
+
- '**/*_spec.rb'
|
9
|
+
|
10
|
+
Lint/RescueException:
|
11
|
+
Exclude:
|
12
|
+
- '**/*_spec.rb'
|
13
|
+
|
14
|
+
Style/AccessorMethodName:
|
15
|
+
Exclude:
|
16
|
+
- '**/*_spec.rb'
|
17
|
+
|
18
|
+
Style/AsciiComments:
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
Style/ClassAndModuleChildren:
|
22
|
+
Enabled: false
|
23
|
+
|
24
|
+
Style/Documentation:
|
25
|
+
Enabled: false
|
26
|
+
|
27
|
+
Style/EmptyLinesAroundBlockBody:
|
28
|
+
Enabled: false
|
29
|
+
|
30
|
+
Style/EmptyLinesAroundClassBody:
|
31
|
+
Enabled: false
|
32
|
+
|
33
|
+
Style/EmptyLinesAroundMethodBody:
|
34
|
+
Enabled: false
|
35
|
+
|
36
|
+
Style/EmptyLinesAroundModuleBody:
|
37
|
+
Enabled: false
|
38
|
+
|
39
|
+
Style/EmptyLineBetweenDefs:
|
40
|
+
Enabled: false
|
41
|
+
|
42
|
+
Style/FileName:
|
43
|
+
Enabled: false
|
44
|
+
|
45
|
+
Style/NumericLiterals:
|
46
|
+
Enabled: false
|
47
|
+
|
48
|
+
Style/RaiseArgs:
|
49
|
+
EnforcedStyle: compact
|
50
|
+
|
51
|
+
Style/SingleLineMethods:
|
52
|
+
Exclude:
|
53
|
+
- '**/*_spec.rb'
|
54
|
+
|
55
|
+
Style/SingleSpaceBeforeFirstArg:
|
56
|
+
Enabled: false
|
57
|
+
|
58
|
+
Style/SpecialGlobalVars:
|
59
|
+
Exclude:
|
60
|
+
- '**/Gemfile'
|
61
|
+
- '**/*.gemspec'
|
62
|
+
|
63
|
+
Style/StringLiterals:
|
64
|
+
EnforcedStyle: double_quotes
|
65
|
+
|
66
|
+
Style/StringLiteralsInInterpolation:
|
67
|
+
EnforcedStyle: double_quotes
|
68
|
+
|
69
|
+
Style/TrivialAccessors:
|
70
|
+
Exclude:
|
71
|
+
- '**/*_spec.rb'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
---
|
2
|
+
# Settings added by the 'hexx-suit' gem
|
3
|
+
output: "tmp/yardstick/output.log"
|
4
|
+
path: "lib/**/*.rb"
|
5
|
+
rules:
|
6
|
+
ApiTag::Presence:
|
7
|
+
enabled: true
|
8
|
+
exclude: []
|
9
|
+
ApiTag::Inclusion:
|
10
|
+
enabled: true
|
11
|
+
exclude: []
|
12
|
+
ApiTag::ProtectedMethod:
|
13
|
+
enabled: true
|
14
|
+
exclude: []
|
15
|
+
ApiTag::PrivateMethod:
|
16
|
+
enabled: false
|
17
|
+
exclude: []
|
18
|
+
ExampleTag:
|
19
|
+
enabled: true
|
20
|
+
exclude: []
|
21
|
+
ReturnTag:
|
22
|
+
enabled: true
|
23
|
+
exclude: []
|
24
|
+
Summary::Presence:
|
25
|
+
enabled: true
|
26
|
+
exclude: []
|
27
|
+
Summary::Length:
|
28
|
+
enabled: true
|
29
|
+
exclude: []
|
30
|
+
Summary::Delimiter:
|
31
|
+
enabled: true
|
32
|
+
exclude: []
|
33
|
+
Summary::SingleLine:
|
34
|
+
enabled: true
|
35
|
+
exclude: []
|
36
|
+
threshold: 100
|
37
|
+
verbose: false
|
@@ -0,0 +1,25 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require "immutability/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
|
6
|
+
gem.name = "immutability"
|
7
|
+
gem.version = Immutability::VERSION.dup
|
8
|
+
gem.author = "Andrew Kozin"
|
9
|
+
gem.email = "andrew.kozin@gmail.com"
|
10
|
+
gem.homepage = "https://github.com/nepalez/immutability"
|
11
|
+
gem.summary = "Make instances immutable (deeply frozen) and versioned"
|
12
|
+
gem.license = "MIT"
|
13
|
+
|
14
|
+
gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
15
|
+
gem.test_files = Dir["spec/**/*.rb"]
|
16
|
+
gem.extra_rdoc_files = Dir["README.md", "LICENSE"]
|
17
|
+
gem.require_paths = ["lib"]
|
18
|
+
|
19
|
+
gem.required_ruby_version = ">= 1.9.3"
|
20
|
+
|
21
|
+
gem.add_runtime_dependency "ice_nine", "~> 0.11.1"
|
22
|
+
|
23
|
+
gem.add_development_dependency "hexx-rspec", "~> 0.5"
|
24
|
+
|
25
|
+
end # Gem::Specification
|
data/lib/immutability.rb
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "ice_nine"
|
4
|
+
|
5
|
+
require_relative "immutability/with_memory"
|
6
|
+
|
7
|
+
# Makes the object immutable (deeply frozen) with possibility to remember
|
8
|
+
# and forget previous states (snapshots).
|
9
|
+
#
|
10
|
+
# Uses 'ice_nine' to freeze object deeply by the initializer
|
11
|
+
#
|
12
|
+
# @example Without memory
|
13
|
+
# require "immutability"
|
14
|
+
#
|
15
|
+
# class User
|
16
|
+
# include Immutability
|
17
|
+
#
|
18
|
+
# attr_reader :name
|
19
|
+
#
|
20
|
+
# def initialize(name)
|
21
|
+
# @name = name
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# user = User.new "Andre"
|
26
|
+
# user.name # => "Andre"
|
27
|
+
# # It is frozen deeply
|
28
|
+
# user.frozen? # => true
|
29
|
+
# user.name.frozen? # => true
|
30
|
+
#
|
31
|
+
# new_user = user.update { @name = "Andrew" }
|
32
|
+
# new_user.name # => "Andrew"
|
33
|
+
# # It is frozen deeply
|
34
|
+
# new_user.frozen? # => true
|
35
|
+
# new_user.name.frozen? # => true
|
36
|
+
#
|
37
|
+
# @example With memory
|
38
|
+
# class User
|
39
|
+
# include Immutability.with_memory
|
40
|
+
#
|
41
|
+
# attr_reader :name
|
42
|
+
#
|
43
|
+
# def initialize(name)
|
44
|
+
# @name = name
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# user = User.new "Andre"
|
49
|
+
# user.name # => "Andre"
|
50
|
+
# # It has version and reference to the parent (nil for the first version)
|
51
|
+
# user.version # => 0
|
52
|
+
# user.parent # => nil
|
53
|
+
#
|
54
|
+
# new_user = user.update { @name = "Andrew" }
|
55
|
+
# new_user.name # => "Andrew"
|
56
|
+
# # It stores current version and reference to the parent
|
57
|
+
# new_user.version # => 1
|
58
|
+
# new_user.parent # => #<User @name="Andre">
|
59
|
+
#
|
60
|
+
# mankurt = new_user.forget_history
|
61
|
+
# mankurt.name # => "Andrew"
|
62
|
+
# # It doesn't refer to previous states (they can be garbage collected)
|
63
|
+
# mankurt.version # => 0
|
64
|
+
# mankurt.parent # => nil
|
65
|
+
#
|
66
|
+
# @author Andrew Kozin <Andrew.Kozin@gmail.com>
|
67
|
+
#
|
68
|
+
module Immutability
|
69
|
+
|
70
|
+
# Methods to be added to class, that included the `Immutability` module
|
71
|
+
#
|
72
|
+
# @api private
|
73
|
+
#
|
74
|
+
module ClassMethods
|
75
|
+
|
76
|
+
# Reloads instance's constructor to make it immutable
|
77
|
+
#
|
78
|
+
# @api private
|
79
|
+
#
|
80
|
+
# @param [Object, Array<Object>] args
|
81
|
+
#
|
82
|
+
# @return [Object]
|
83
|
+
#
|
84
|
+
def new(*args)
|
85
|
+
IceNine.deep_freeze __new__(*args)
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def __new__(*args, &block)
|
91
|
+
allocate.tap do |instance|
|
92
|
+
instance.__send__(:initialize, *args)
|
93
|
+
instance.instance_eval(&block) if block_given?
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end # module ClassMethods
|
98
|
+
|
99
|
+
# Returns the new immutable instances that preserves old variables and
|
100
|
+
# updates some of them from inside the block
|
101
|
+
#
|
102
|
+
# @param [Proc] block
|
103
|
+
# The block to be evaluated by new instance's "initializer"
|
104
|
+
#
|
105
|
+
# @return [Object] the updated instance
|
106
|
+
#
|
107
|
+
def update(&block)
|
108
|
+
instance = dup
|
109
|
+
instance.instance_eval(&block) if block_given?
|
110
|
+
IceNine.deep_freeze(instance)
|
111
|
+
end
|
112
|
+
|
113
|
+
# @private
|
114
|
+
def self.included(klass)
|
115
|
+
klass.instance_exec(ClassMethods) { |mod| extend(mod) }
|
116
|
+
end
|
117
|
+
|
118
|
+
# Returns the module extended by features to record history
|
119
|
+
#
|
120
|
+
# @return [Module]
|
121
|
+
#
|
122
|
+
def self.with_memory
|
123
|
+
WithMemory
|
124
|
+
end
|
125
|
+
|
126
|
+
end # module Immutability
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Immutability
|
4
|
+
|
5
|
+
# Extends +Immutability+ to remember version and previous state of instance.
|
6
|
+
#
|
7
|
+
# @author Andrew Kozin <Andrew.Kozin@gmail.com>
|
8
|
+
#
|
9
|
+
module WithMemory
|
10
|
+
|
11
|
+
# @private
|
12
|
+
class << self
|
13
|
+
private
|
14
|
+
|
15
|
+
def included(klass)
|
16
|
+
klass.__send__ :include, Immutability
|
17
|
+
klass.__send__ :extend, ClassMethods
|
18
|
+
klass.__send__ :define_method, :update, update
|
19
|
+
end
|
20
|
+
|
21
|
+
# Redefines the +update+ so that it increment version and refer
|
22
|
+
# to the previous snapshot of the continuous object
|
23
|
+
#
|
24
|
+
def update
|
25
|
+
proc do |&block|
|
26
|
+
current = [(version + 1), self]
|
27
|
+
super() do
|
28
|
+
@version, @parent = current
|
29
|
+
instance_eval(&block) if block
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Adds version and parent variables to newly created instance
|
36
|
+
#
|
37
|
+
module ClassMethods
|
38
|
+
private
|
39
|
+
|
40
|
+
def __new__(*args)
|
41
|
+
super(*args) { @version, @parent = 0 }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# @!attribute [r] version
|
46
|
+
#
|
47
|
+
# @return [Integer] the current version number of the instance
|
48
|
+
#
|
49
|
+
attr_reader :version
|
50
|
+
|
51
|
+
# @!attribute [r] parent
|
52
|
+
#
|
53
|
+
# @return [Object] the previous version (immutable instance)
|
54
|
+
#
|
55
|
+
attr_reader :parent
|
56
|
+
|
57
|
+
# Forgets the previous history of the object
|
58
|
+
#
|
59
|
+
# Returns a new instance with the same variables,
|
60
|
+
# except for [#version] and [#parent] that are set to +0+ and +nil+.
|
61
|
+
#
|
62
|
+
# @return [Object]
|
63
|
+
#
|
64
|
+
def forget_history
|
65
|
+
update { @version, @parent = 0 }
|
66
|
+
end
|
67
|
+
|
68
|
+
end # module WithMemory
|
69
|
+
|
70
|
+
end # module Immutability
|
data/spec/shared/user.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "hexx-suit"
|
5
|
+
Hexx::Suit.load_metrics_for(self)
|
6
|
+
rescue LoadError
|
7
|
+
require "hexx-rspec"
|
8
|
+
Hexx::RSpec.load_metrics_for(self)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Loads the code under test
|
12
|
+
require "immutability"
|
13
|
+
|
14
|
+
# Loads custom matchers
|
15
|
+
require "immutability/rspec"
|
16
|
+
|
17
|
+
# Loads shared examples
|
18
|
+
require_relative "shared/user"
|