inherited_class_var 0.2.2 → 1.0.0.beta1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a7e840571a249a64b262bfc9bf8527a8035f9af1
4
- data.tar.gz: 1af56f855f62cd025389c36691459142a2b3ef78
3
+ metadata.gz: c26fdce40dde8a1b5da981e01f10ac4c8a7c6fa3
4
+ data.tar.gz: 84f8404281c828b41232cf61e5f4bc8b60de8bd1
5
5
  SHA512:
6
- metadata.gz: f2a1732a324a908fbe3b7dabed0a9a77dd27f75123158460e682d0d353bef9369bb2ba4f661eebc143330f9719110a3dd69f86bb19018c8389cbf46e29480ee0
7
- data.tar.gz: ede1f603e5815b1f6da2c74fdd3cc3a7395b65600ff2f6b0586208d1fc732698058e76716365cf91ec525202be9081396be779f9e4e0bf8806668abb6feed2ce
6
+ metadata.gz: 097aedaabecfb5b04c235f89267167fda5a9ec45aca6c209befbce890cf8fcbeb824f46be58b8861e6625c29b689358fdf188678b13ee18cecac7f324aaeae38
7
+ data.tar.gz: 6a53d905f6f9cb5675a203775d68d56edc433d2283575881eb4bd8a4a96c3a8e1c8bebd57150e20153072848fde10c256f2d6991ae3087cadcc62e1d648bde94
data/.gitignore CHANGED
@@ -8,3 +8,4 @@
8
8
  /spec/reports/
9
9
  /tmp/
10
10
  /.idea/*
11
+ .byebug_history
data/README.md CHANGED
@@ -1,17 +1,27 @@
1
- # InheritedClassVar
1
+ # InheritedClassVar [![Build Status](https://travis-ci.org/FinalCAD/inherited_class_var.svg?branch=master)](https://travis-ci.org/FinalCAD/inherited_class_var)[![Code Climate](https://codeclimate.com/github/FinalCAD/inherited_class_var.png)](https://codeclimate.com/github/FinalCAD/inherited_class_var)[![Dependency Status](https://gemnasium.com/FinalCAD/inherited_class_var.svg)](https://gemnasium.com/FinalCAD/inherited_class_var)[![Coverage Status](https://coveralls.io/repos/FinalCAD/inherited_class_var/badge.svg?branch=master&service=github)](https://coveralls.io/github/FinalCAD/inherited_class_var?branch=master)[![Gem Version](https://badge.fury.io/rb/inherited_class_var.svg)](http://badge.fury.io/rb/inherited_class_var)
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/inherited_class_var`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Implement class variables that inherit from their ancestors. Such as a `Hash`:
4
4
 
5
- [![Code Climate](https://codeclimate.com/github/FinalCAD/inherited_class_var.png)](https://codeclimate.com/github/FinalCAD/inherited_class_var)
6
-
7
- [![Dependency Status](https://gemnasium.com/FinalCAD/inherited_class_var.svg)](https://gemnasium.com/FinalCAD/inherited_class_var)
8
-
9
- [![Build Status](https://travis-ci.org/FinalCAD/inherited_class_var.svg?branch=master)](https://travis-ci.org/FinalCAD/inherited_class_var) (Travis CI)
5
+ ```ruby
6
+ require 'inherited_class_var'
10
7
 
11
- [![Coverage Status](https://coveralls.io/repos/FinalCAD/inherited_class_var/badge.svg?branch=master&service=github)](https://coveralls.io/github/FinalCAD/inherited_class_var?branch=master)
8
+ class Bird
9
+ include InheritedClassVar
10
+ inherited_class_hash :attributes #, shallow: false, reverse: false (default aoptions)
11
+
12
+ def self.attribute(attribute_name, options={})
13
+ attributes_object.merge(attribute_name.to_sym => options)
14
+ end
15
+ attribute :name, upcase: true
16
+ end
12
17
 
13
- [![Gem Version](https://badge.fury.io/rb/inherited_class_var.svg)](http://badge.fury.io/rb/inherited_class_var)
18
+ class Duck < Bird
19
+ attribute :flying, default: false
20
+ end
14
21
 
22
+ Bird.attributes # => { name: upcase: true }
23
+ Duck.attributes # => { name: upcase: true, flying: false }
24
+ ```
15
25
 
16
26
  ## Installation
17
27
 
@@ -31,70 +41,32 @@ Or install it yourself as:
31
41
 
32
42
  ## Usage
33
43
 
34
- You can follow this example, if you want to create Models with columns information and these informations still available after inheritance
35
-
36
- Create a Model module with `inherited_class_var`
37
-
38
- ```
39
- require 'inherited_class_var'
40
-
41
- module Model
42
- extend ActiveSupport::Concern
43
-
44
- included do
45
- include InheritedClassVar
46
- inherited_class_hash :columns
47
- end
44
+ You can also define your own variable types. This is the source for `Hash`:
48
45
 
49
- module ClassMethods
46
+ ```ruby
47
+ module InheritedClassVar
48
+ class Hash < Variable
49
+ alias_method :merge, :change
50
50
 
51
- protected
51
+ def default_value
52
+ {}
53
+ end
52
54
 
53
- def column(column_name, options={})
54
- merge_columns(column_name.to_sym => options)
55
+ def _change(hash1, hash2)
56
+ method = options[:shallow] ? :merge! : :deep_merge!
57
+ block = options[:reverse] ? Proc.new {|key,left,right| left } : Proc.new {|key,left,right| right }
58
+ hash1.public_send(method, hash2, &block)
55
59
  end
56
60
  end
57
61
  end
58
- ```
59
62
 
60
- `merge_columns` it's bring by `inherited_class_var`
61
-
62
- ```
63
- class ModelBase
64
- include Model
65
-
66
- column :id, type: Integer
67
- end
68
- ```
69
-
70
- Gives
71
- ```
72
- ModelBase.columns # => {:id=>{:type=>Integer}}
73
- ```
74
-
75
- ```
76
- class UserModel < ModelBase
77
-
78
- column :name, type: String
63
+ module InheritedClassVar
64
+ def inherited_class_hash(variable_name, options={})
65
+ inherited_class_var variable_name, InheritedClassVar::Hash, options
66
+ end
79
67
  end
80
68
  ```
81
69
 
82
- Gives
83
- ```
84
- UserModel.columns # => {:id=>{:type=>Integer}, :name=>{:type=>String}}
85
- ```
86
-
87
- ## Development
88
-
89
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
90
-
91
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
92
-
93
- ## Contributing
94
-
95
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/inherited_class_var. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
96
-
97
-
98
70
  ## License
99
71
 
100
72
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -6,8 +6,8 @@ Gem::Specification.new do |spec|
6
6
  spec.authors = ['Steve Chung', 'Joel AZEMAR']
7
7
  spec.email = ['hello@stevenchung.ca','joel.azemar@gmail.com']
8
8
 
9
- spec.summary = %q{Let inherited class var}
10
- spec.description = %q{Let inherited class var to authorize inheritance}
9
+ spec.summary = %q{Implement class variables that inherit from their ancestors.}
10
+ spec.description = %q{Implement class variables that inherit from their ancestors.}
11
11
  spec.homepage = 'https://github.com/FinalCAD/inherited_class_var'
12
12
  spec.license = 'MIT'
13
13
 
@@ -16,5 +16,5 @@ Gem::Specification.new do |spec|
16
16
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
17
17
  spec.require_paths = ['lib']
18
18
 
19
- spec.add_dependency 'activesupport', '~> 4.2'
19
+ spec.add_dependency 'activesupport', '>= 4.2'
20
20
  end
@@ -0,0 +1,15 @@
1
+ module InheritedClassVar
2
+ class Hash < Variable
3
+ alias_method :merge, :change
4
+
5
+ def default_value
6
+ {}
7
+ end
8
+
9
+ def _change(hash1, hash2)
10
+ method = options[:shallow] ? :merge! : :deep_merge!
11
+ block = options[:reverse] ? Proc.new {|key,left,right| left } : Proc.new {|key,left,right| right }
12
+ hash1.public_send(method, hash2, &block)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,68 @@
1
+ module InheritedClassVar
2
+ class Variable
3
+ attr_reader :name, :klass, :options
4
+
5
+ def initialize(name, klass, options={})
6
+ @name = name
7
+ @klass = klass
8
+ @options = options
9
+ end
10
+
11
+ def object_method_name
12
+ self.class.object_method_name(name)
13
+ end
14
+
15
+ def default_value
16
+ raise NotImplementedError
17
+ end
18
+
19
+ def raw_value
20
+ @raw_value ||= default_value
21
+ end
22
+
23
+ def value
24
+ @value ||= klass.inherited_ancestors
25
+ .map { |ancestor| ancestor.try(object_method_name).try(:raw_value) }
26
+ .compact
27
+ .reverse
28
+ .reduce(default_value, &method(:reduce))
29
+ end
30
+
31
+ def change(other_value)
32
+ notify_change
33
+ _change(raw_value, other_value)
34
+ end
35
+
36
+ def _change(value1, value2)
37
+ raise NotImplementedError
38
+ end
39
+ def reduce(*args); _change(*args) end
40
+
41
+ def notify_change
42
+ ([klass] + klass.descendants).each do |descendant|
43
+ descendant.try(object_method_name).try(:clear_memoized_value)
44
+ end
45
+ end
46
+
47
+ def clear_memoized_value
48
+ @value = nil if @value
49
+ end
50
+
51
+ class << self
52
+ def object_method_name(name)
53
+ :"#{name}_object"
54
+ end
55
+
56
+ def define_methods(name, klass, options={})
57
+ variable_class = self
58
+ object_method_name = object_method_name(name)
59
+
60
+ klass.send :define_singleton_method, object_method_name do
61
+ instance_variable_name = :"@#{object_method_name}"
62
+ instance_variable_get(instance_variable_name) || instance_variable_set(instance_variable_name, variable_class.new(name, self, options))
63
+ end
64
+ klass.send(:define_singleton_method, name) { public_send(object_method_name).value }
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,3 +1,3 @@
1
1
  module InheritedClassVar
2
- VERSION = '0.2.2'
2
+ VERSION = '1.0.0.beta1'
3
3
  end
@@ -1,39 +1,26 @@
1
1
  require 'active_support/all'
2
2
 
3
3
  require 'inherited_class_var/version'
4
- require 'inherited_class_var/cache'
4
+ require 'inherited_class_var/variable'
5
+ require 'inherited_class_var/hash'
5
6
 
6
7
  module InheritedClassVar
7
8
  extend ActiveSupport::Concern
8
9
 
9
- include Cache
10
-
11
10
  class_methods do
12
11
  protected
13
12
 
14
- #
15
- # Easy Open API
16
- #
17
-
18
13
  # @param variable_name [Symbol] class variable name
19
- # @option options [Array] :dependencies array of dependent method names
20
- def inherited_class_hash(variable_name)
21
- hidden_variable_name = hidden_variable_name(variable_name)
22
-
23
- define_singleton_method variable_name do
24
- inherited_class_var(hidden_variable_name, {}) do |hash, to_merge|
25
- hash.deep_merge!(to_merge) {|key,left,right| left } # a reverse_deep_merge! implementation, this will keep the parent's key order
26
- end
27
- end
28
-
29
- define_singleton_method :"raw_#{variable_name}" do
30
- class_var(hidden_variable_name, {})
31
- end
14
+ # @param options [Hash] see InheritedClassVar::Hash
15
+ def inherited_class_hash(variable_name, options={})
16
+ inherited_class_var variable_name, InheritedClassVar::Hash, options
17
+ end
32
18
 
33
- define_singleton_method :"merge_#{variable_name}" do |merge_value|
34
- deep_clear_class_cache(hidden_variable_name)
35
- public_send(:"raw_#{variable_name}").deep_merge!(merge_value)
36
- end
19
+ # @param variable_name [Symbol] class variable name
20
+ # @param variable_class [Class] a InheritedClassVar::Variable class
21
+ # @param options [Hash] see the variable_class
22
+ def inherited_class_var(variable_name, variable_class, options={})
23
+ variable_class.define_methods(variable_name, self, options)
37
24
  end
38
25
 
39
26
  # @param accessor_method_name [Symbol] method to access the inherited_custom_class
@@ -54,43 +41,11 @@ module InheritedClassVar
54
41
  parent_class ||= base_parent_class
55
42
 
56
43
  klass = Class.new(parent_class)
57
- # how else can i get the current scopes name...
58
44
  klass.send(:define_singleton_method, :name, &eval("-> { \"#{name}#{base_parent_class.name.demodulize}\" }"))
59
45
  klass
60
46
  end
61
47
 
62
- #
63
- # Helpers to make different types of inherited class variables
64
- #
65
-
66
- # @param variable_name [Symbol] class variable name based on
67
- # @return [Symbol] the hidden variable name for class variable
68
- def hidden_variable_name(variable_name)
69
- :"@_#{variable_name}"
70
- end
71
-
72
- # @param variable_name [Symbol] class variable name
73
- # @param default_value [Object] default value of the class variable
74
- # @return [Object] a class variable of the specific class without taking into account inheritance
75
- def class_var(variable_name, default_value)
76
- instance_variable_get(variable_name) || instance_variable_set(variable_name, default_value)
77
- end
78
-
79
- # @param variable_name [Symbol] class variable name (recommend :@_variable_name)
80
- # @return [Object] a class variable merged across ancestors until inherited_class_module
81
- def inherited_class_var(variable_name, *reduce_args, &block)
82
- class_cache(variable_name) do
83
- inherited_ancestors.map { |ancestor| ancestor.instance_variable_get(variable_name) }
84
- .compact
85
- .reverse
86
- .reduce(*reduce_args, &block)
87
- end
88
- end
89
-
90
- #
91
- # More Helpers
92
- #
93
-
48
+ public
94
49
  # @param included_module [Module] module to search for
95
50
  # @return [Array<Module>] inherited_ancestors of included_module (including self)
96
51
  def inherited_ancestors(included_module=InheritedClassVar)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inherited_class_var
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 1.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Chung
@@ -9,23 +9,23 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2016-06-29 00:00:00.000000000 Z
12
+ date: 2016-07-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - "~>"
18
+ - - ">="
19
19
  - !ruby/object:Gem::Version
20
20
  version: '4.2'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - "~>"
25
+ - - ">="
26
26
  - !ruby/object:Gem::Version
27
27
  version: '4.2'
28
- description: Let inherited class var to authorize inheritance
28
+ description: Implement class variables that inherit from their ancestors.
29
29
  email:
30
30
  - hello@stevenchung.ca
31
31
  - joel.azemar@gmail.com
@@ -46,7 +46,8 @@ files:
46
46
  - bin/setup
47
47
  - inherited_class_var.gemspec
48
48
  - lib/inherited_class_var.rb
49
- - lib/inherited_class_var/cache.rb
49
+ - lib/inherited_class_var/hash.rb
50
+ - lib/inherited_class_var/variable.rb
50
51
  - lib/inherited_class_var/version.rb
51
52
  homepage: https://github.com/FinalCAD/inherited_class_var
52
53
  licenses:
@@ -63,13 +64,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
63
64
  version: '0'
64
65
  required_rubygems_version: !ruby/object:Gem::Requirement
65
66
  requirements:
66
- - - ">="
67
+ - - ">"
67
68
  - !ruby/object:Gem::Version
68
- version: '0'
69
+ version: 1.3.1
69
70
  requirements: []
70
71
  rubyforge_project:
71
72
  rubygems_version: 2.5.1
72
73
  signing_key:
73
74
  specification_version: 4
74
- summary: Let inherited class var
75
+ summary: Implement class variables that inherit from their ancestors.
75
76
  test_files: []
@@ -1,54 +0,0 @@
1
- #
2
- # Methods to help cache the inherited variable
3
- #
4
- # Given:
5
- # Parent -> Child
6
- #
7
- # and Parent.send(:inherited_class_hash, :some_var)
8
- #
9
- # Parent.merge_some_var(a: 1)
10
- # Child.some_var # => { a: 1 }, this requires going up the ancestors (Parent, Grandparent, etc.) and merging, so we cache the result
11
- # Child.some_var # => { a: 1 }, cached, no calculation
12
- #
13
- # Parent.merge_some_var(b: 2) # => this should clear the cache for all descendents
14
- # Child.some_var # => { a: 1, b: 2 } # => cache was cleared, so recalculate via merging up ancestors
15
- #
16
- module InheritedClassVar
17
- module Cache
18
- extend ActiveSupport::Concern
19
-
20
- class_methods do
21
-
22
- # Clears the cache for a variable (must be public)
23
- # @param variable_name [Symbol] variable_name to cache against
24
- def clear_class_cache(variable_name)
25
- instance_variable_set inherited_class_variable_name(variable_name), nil
26
- end
27
-
28
- protected
29
- # Memozies a inherited_class_variable_name
30
- # @param variable_name [Symbol] variable_name to cache against
31
- def class_cache(variable_name)
32
- #
33
- # equal to: (has @)inherited_class_variable_name ||= yield
34
- #
35
- cache_variable_name = inherited_class_variable_name(variable_name)
36
- instance_variable_get(cache_variable_name) || instance_variable_set(cache_variable_name, yield)
37
- end
38
-
39
- # Clears the cache for a variable and the same variable for all it's dependant descendants
40
- # @param variable_name [Symbol] variable_name to cache against
41
- def deep_clear_class_cache(variable_name)
42
- ([self] + descendants).each do |descendant|
43
- descendant.try(:clear_class_cache, variable_name)
44
- end
45
- end
46
-
47
- # @param variable_name [Symbol] variable_name to cache against
48
- # @return [String] the cache variable name for the cache
49
- def inherited_class_variable_name(variable_name)
50
- :"#{variable_name}_inherited_class_cache"
51
- end
52
- end
53
- end
54
- end