inherited_class_var 0.2.2 → 1.0.0.beta1

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