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.
@@ -0,0 +1,5 @@
1
+ ---
2
+ abc_max: "10"
3
+ line_length: "80"
4
+ no_doc: "y"
5
+ no_readme: "y"
@@ -0,0 +1,6 @@
1
+ ---
2
+ ignore_files:
3
+ - spec
4
+ - config
5
+ minimum_churn_count: 0
6
+ start_date: "1 year ago"
@@ -0,0 +1,2 @@
1
+ ---
2
+ minimum_score: 8
@@ -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,3 @@
1
+ ---
2
+ warn_cyclo: 3
3
+ error_cyclo: 4
@@ -0,0 +1,6 @@
1
+ ---
2
+ output: tmp/coverage
3
+ filters: # The list of paths to be excluded from coverage checkup
4
+ - "spec/"
5
+ - "config/"
6
+ groups: []
@@ -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
@@ -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,4 @@
1
+ # encoding: utf-8
2
+
3
+ # Loads spec matcher to check the immutability
4
+ require_relative "../../spec/support/immutable"
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ module Immutability
4
+
5
+ # The semantic version of the gem.
6
+ # @see http://semver.org/ Semantic versioning 2.0
7
+ VERSION = "0.0.1".freeze
8
+
9
+ 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
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ shared_examples :user do
4
+ before do
5
+ class User
6
+ attr_reader :name, :age
7
+
8
+ def initialize(name, age)
9
+ @name = name
10
+ @age = age
11
+ end
12
+ end
13
+ end
14
+
15
+ after { Object.send :remove_const, :User }
16
+ end
@@ -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"