opt_ar 1.0.0 → 1.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 +4 -4
- data/.gitignore +2 -0
- data/Gemfile +10 -4
- data/Gemfile.lock +1 -9
- data/Rakefile +1 -1
- data/bin/console +20 -4
- data/lib/opt_ar/errors.rb +9 -0
- data/lib/opt_ar/helpers/method_finder_helper.rb +43 -8
- data/lib/opt_ar/logger.rb +17 -0
- data/lib/opt_ar/{optimal_active_record.rb → oar.rb} +26 -2
- data/lib/opt_ar/optimal_ar/builder.rb +64 -33
- data/lib/opt_ar/version.rb +1 -1
- data/lib/opt_ar.rb +28 -1
- data/opt_ar.gemspec +6 -5
- metadata +10 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 05daa8fd91d2473f6cf34e98d2e5ac791f920894ba9320494acf5eda3f8ca0eb
|
4
|
+
data.tar.gz: bfa798775b961b5d4d33c83fd78ca53fef8a7535903e0930c802793b1598f3a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea64ea8e8691073516396dd1ac53bd90b08c1a1fab8baeaf80d8c3dad2de6bc83f4f5128328246617052f2761755c5b26ef2c2a0f1e0a3317b547ef93dc21944
|
7
|
+
data.tar.gz: 56d26b34be8033148c3452bd77e1177ab80eeb6247dc88ba4a45329e522f86bf76d719ba67ef997abe1471d0916add31fef4231107f93b20e9eddf84d3790ffc
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
@@ -1,10 +1,16 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
3
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
4
4
|
|
5
5
|
# Specify your gem's dependencies in opt_ar.gemspec
|
6
6
|
gemspec
|
7
7
|
|
8
8
|
gem 'activerecord', '>= 3.2'
|
9
|
-
|
10
|
-
gem '
|
9
|
+
|
10
|
+
# gem 'byebug', '10.0.2'
|
11
|
+
|
12
|
+
# gem 'minitest-reporters'
|
13
|
+
# gem 'minitest-stub-const'
|
14
|
+
# gem 'minitest-logger'
|
15
|
+
|
16
|
+
gem 'mysql2', '>= 0.3'
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
opt_ar (1.0.
|
4
|
+
opt_ar (1.0.1)
|
5
5
|
activerecord (>= 3.2)
|
6
6
|
mysql2 (>= 0.3)
|
7
7
|
|
@@ -21,20 +21,13 @@ GEM
|
|
21
21
|
minitest (~> 5.1)
|
22
22
|
thread_safe (~> 0.3, >= 0.3.4)
|
23
23
|
tzinfo (~> 1.1)
|
24
|
-
ansi (1.5.0)
|
25
24
|
arel (6.0.4)
|
26
25
|
builder (3.2.3)
|
27
26
|
i18n (0.8.1)
|
28
27
|
json (1.8.6)
|
29
28
|
minitest (5.10.1)
|
30
|
-
minitest-reporters (1.3.5)
|
31
|
-
ansi
|
32
|
-
builder
|
33
|
-
minitest (>= 5.0)
|
34
|
-
ruby-progressbar
|
35
29
|
mysql2 (0.4.9)
|
36
30
|
rake (10.4.2)
|
37
|
-
ruby-progressbar (1.10.0)
|
38
31
|
thread_safe (0.3.6)
|
39
32
|
tzinfo (1.2.2)
|
40
33
|
thread_safe (~> 0.1)
|
@@ -46,7 +39,6 @@ DEPENDENCIES
|
|
46
39
|
activerecord (>= 3.2)
|
47
40
|
bundler (~> 1.16)
|
48
41
|
minitest (~> 5.0)
|
49
|
-
minitest-reporters
|
50
42
|
mysql2 (>= 0.3)
|
51
43
|
opt_ar!
|
52
44
|
rake (~> 10.0)
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
2
|
+
require 'bundler/setup'
|
3
|
+
require 'opt_ar'
|
4
|
+
require 'mysql2'
|
5
|
+
require 'active_record'
|
6
|
+
require 'active_record/connection_adapters/mysql2_adapter'
|
7
|
+
require_relative '../test/models/test_models'
|
5
8
|
|
6
9
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
10
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -9,6 +12,19 @@ require "opt_ar"
|
|
9
12
|
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
13
|
# require "pry"
|
11
14
|
# Pry.start
|
15
|
+
require 'irb'
|
16
|
+
|
17
|
+
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
18
|
+
|
19
|
+
ActiveRecord::Base.establish_connection(
|
20
|
+
adapter: 'mysql2',
|
21
|
+
database: 'optar_test',
|
22
|
+
host: 'localhost',
|
23
|
+
username: 'root',
|
24
|
+
password: '',
|
25
|
+
pool: 5
|
26
|
+
)
|
27
|
+
|
28
|
+
# ActiveRecord::Base.connection_pool.clear_reloadable_connections!
|
12
29
|
|
13
|
-
require "irb"
|
14
30
|
IRB.start(__FILE__)
|
data/lib/opt_ar/errors.rb
CHANGED
@@ -14,5 +14,14 @@ module OptAR
|
|
14
14
|
|
15
15
|
class MissingPrimaryKeyError < StandardError
|
16
16
|
end
|
17
|
+
|
18
|
+
class NonActiveRecordError < StandardError
|
19
|
+
end
|
20
|
+
|
21
|
+
class PrimaryKeyBlacklistedError < StandardError
|
22
|
+
end
|
23
|
+
|
24
|
+
class TimeTypeExpectedError < StandardError
|
25
|
+
end
|
17
26
|
end
|
18
27
|
end
|
@@ -1,7 +1,10 @@
|
|
1
1
|
module OptAR
|
2
|
+
# Methods for handling all attributes read
|
2
3
|
module MethodFinderHelper
|
3
4
|
ID_STRING = 'id'.freeze
|
4
5
|
WARN_MSG = 'WARNING :: Trying to access attr that was not requested'.freeze
|
6
|
+
DEFAULT_DATE_TIME_ATTRIBUTES = %i[created_at updated_at].freeze
|
7
|
+
DATE_TIME_CONST_KEY = 'DATE_TIME_ATTRIBUTES'.freeze
|
5
8
|
|
6
9
|
private
|
7
10
|
|
@@ -22,13 +25,14 @@ module OptAR
|
|
22
25
|
# methods on the instance, for attribute that was not requested initially
|
23
26
|
def method_missing(method_name, *args)
|
24
27
|
method_name = method_name.to_sym
|
25
|
-
return
|
28
|
+
return read_from_attributes(method_name) if @attributes.key?(method_name)
|
26
29
|
|
27
30
|
raise OptAR::Errors::MissingPrimaryKeyError if primary_key?(method_name)
|
28
31
|
|
29
32
|
raise OptAR::Errors::MutationNotAllowedError if assign?(method_name)
|
30
33
|
|
31
|
-
|
34
|
+
OptAR::Logger.log("#{WARN_MSG} :: #{method_name}", :warn)
|
35
|
+
|
32
36
|
load_ar_object
|
33
37
|
@klass_object ? @klass_object.send(method_name, *args) : super
|
34
38
|
end
|
@@ -42,24 +46,55 @@ module OptAR
|
|
42
46
|
@klass_object.respond_to?(*args)
|
43
47
|
end
|
44
48
|
|
49
|
+
def read_from_attributes(key)
|
50
|
+
klass = klass_name.constantize
|
51
|
+
if transformable_fields(klass).include?(key)
|
52
|
+
Time.at(attributes[key]).utc
|
53
|
+
else
|
54
|
+
attributes[key]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
45
58
|
# Default scope for the class defined by klass_name will be applied here
|
46
59
|
def load_ar_object
|
47
|
-
@klass_object ||=
|
48
|
-
|
49
|
-
|
60
|
+
@klass_object ||= begin
|
61
|
+
klass_name.constantize
|
62
|
+
.readonly(true)
|
63
|
+
.where("#{klass_primary_key}=#{klass_primary_key_value}")
|
64
|
+
.first
|
65
|
+
end
|
50
66
|
raise OptAR::Errors::ARObjectNotFoundError unless @klass_object
|
51
67
|
end
|
52
68
|
|
69
|
+
def transformable_fields(klass)
|
70
|
+
@transformable_keys ||= begin
|
71
|
+
keys = attributes.keys
|
72
|
+
attrs = if klass.const_defined?(DATE_TIME_CONST_KEY)
|
73
|
+
klass.const_get(DATE_TIME_CONST_KEY)
|
74
|
+
else
|
75
|
+
DEFAULT_DATE_TIME_ATTRIBUTES
|
76
|
+
end
|
77
|
+
keys & attrs
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
53
81
|
def klass_key
|
54
82
|
klass_name.gsub('::', '_').underscore
|
55
83
|
end
|
56
84
|
|
57
|
-
def klass_primary_key(klass)
|
58
|
-
|
85
|
+
def klass_primary_key(klass = nil)
|
86
|
+
@primary_key ||= begin
|
87
|
+
klass ||= klass_name.constantize
|
88
|
+
klass.primary_key.to_sym
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def klass_primary_key_value
|
93
|
+
attributes[klass_primary_key]
|
59
94
|
end
|
60
95
|
|
61
96
|
def primary_key?(method_name)
|
62
|
-
method_name == klass_primary_key
|
97
|
+
method_name == klass_primary_key
|
63
98
|
end
|
64
99
|
|
65
100
|
def assign?(method_name)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module OptAR
|
2
|
+
# Log implementation for the gem
|
3
|
+
#
|
4
|
+
# Tries to use ActiveRecord::Base.logger which is compatible with rails
|
5
|
+
# else, fallbacks to STDOUT
|
6
|
+
module Logger
|
7
|
+
class << self
|
8
|
+
def log(msg, level = :info)
|
9
|
+
logger.send(level, msg)
|
10
|
+
end
|
11
|
+
|
12
|
+
def logger
|
13
|
+
ActiveRecord::Base.logger || ::Logger.new(STDOUT)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,7 +1,14 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/helpers/method_finder_helper'
|
2
2
|
|
3
3
|
module OptAR
|
4
|
-
|
4
|
+
# Dupe of ActiveRecord::Base providing necessary read functionalities
|
5
|
+
# of it, while removing a lot of abstactions that it provides
|
6
|
+
# to reduce memory and processing time utilisation
|
7
|
+
#
|
8
|
+
# attributes : contains the requested attributes from AR
|
9
|
+
# klass_name : class name of original AR model
|
10
|
+
# klass_object : original AR object loaded
|
11
|
+
class OAR
|
5
12
|
include OptAR::MethodFinderHelper
|
6
13
|
|
7
14
|
attr_reader :attributes, :klass_name, :klass_object
|
@@ -47,6 +54,7 @@ module OptAR
|
|
47
54
|
mandatory_attributes(klass) -
|
48
55
|
skipped_attributes(klass)
|
49
56
|
@attributes = obj_attributes.slice(*attribute_keys)
|
57
|
+
transform_datetime_attributes(object.class)
|
50
58
|
end
|
51
59
|
|
52
60
|
def mandatory_attributes(klass)
|
@@ -59,12 +67,28 @@ module OptAR
|
|
59
67
|
# security related information to the outside world
|
60
68
|
def skipped_attributes(klass)
|
61
69
|
if klass.const_defined?(BLACKLISTED_ATTRIBUTES)
|
62
|
-
klass.const_get(BLACKLISTED_ATTRIBUTES)
|
70
|
+
attrs = klass.const_get(BLACKLISTED_ATTRIBUTES)
|
71
|
+
if attrs.include? klass_primary_key(klass)
|
72
|
+
raise OptAR::Errors::PrimaryKeyBlacklistedError
|
73
|
+
end
|
74
|
+
attrs
|
63
75
|
else
|
64
76
|
[]
|
65
77
|
end
|
66
78
|
end
|
67
79
|
|
80
|
+
def transform_datetime_attributes(klass)
|
81
|
+
fields = transformable_fields(klass)
|
82
|
+
return unless fields.present?
|
83
|
+
fields.each do |field|
|
84
|
+
val = attributes[field]
|
85
|
+
raise OptAR::Errors::TimeTypeExpectedError unless val.is_a?(Time)
|
86
|
+
attributes[field] = val.to_i
|
87
|
+
end
|
88
|
+
ensure
|
89
|
+
attributes.freeze
|
90
|
+
end
|
91
|
+
|
68
92
|
def marshal_dump
|
69
93
|
[@attributes, @klass_name]
|
70
94
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'active_support/core_ext/kernel/singleton_class'
|
2
|
-
require File.dirname(__FILE__) + '/../
|
2
|
+
require File.dirname(__FILE__) + '/../oar'
|
3
3
|
|
4
4
|
module OptAR
|
5
5
|
module OptimalAR
|
@@ -7,59 +7,90 @@ module OptAR
|
|
7
7
|
module ClassMethods
|
8
8
|
def build_opt_ar(name, options = {})
|
9
9
|
validate_name(name)
|
10
|
+
validate_scope(options[:scope]) if options[:scope]
|
10
11
|
faker_proc = lambda do |*args|
|
11
|
-
options = options
|
12
|
+
options = fetch_options(options, *args)
|
12
13
|
scope = options[:scope]
|
13
|
-
|
14
|
-
valid_scope?(scope) ? safe_send(scope).opt_ar_objects(options) : throw_error(:undefined_scope, scope: scope)
|
15
|
-
else
|
16
|
-
safe_send(:build_default_scope).opt_ar_objects(options)
|
17
|
-
end
|
14
|
+
fetch_optar_objects(scope, options)
|
18
15
|
end
|
19
|
-
singleton_class.
|
16
|
+
singleton_class.send(:redefine_method, name, &faker_proc)
|
20
17
|
end
|
21
18
|
|
22
19
|
alias show_as build_opt_ar
|
23
20
|
|
24
21
|
private
|
25
22
|
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
def validate_scope(scope_name)
|
24
|
+
valid = valid_scope?(scope_name)
|
25
|
+
return if valid == true
|
26
|
+
throw_error(:undefined_scope, scope: scope_name)
|
27
|
+
end
|
29
28
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
29
|
+
def valid_scope?(scope_name)
|
30
|
+
respond_to? scope_name
|
31
|
+
end
|
34
32
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
else
|
41
|
-
true
|
42
|
-
end
|
43
|
-
end
|
33
|
+
def validate_name(name)
|
34
|
+
valid = valid_name?(name)
|
35
|
+
return true if valid == true
|
36
|
+
throw_error(:invalid_name, name: name, type: valid)
|
37
|
+
end
|
44
38
|
|
45
|
-
|
46
|
-
|
39
|
+
def valid_name?(name)
|
40
|
+
if !name.is_a?(Symbol)
|
41
|
+
:symbol_expected
|
42
|
+
elsif respond_to? name
|
43
|
+
:duplicate_name
|
44
|
+
else
|
45
|
+
true
|
47
46
|
end
|
47
|
+
end
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
def fetch_options(options, *args)
|
50
|
+
if options.respond_to?(:call)
|
51
|
+
unscoped { options.call(*args) }
|
52
|
+
else
|
53
|
+
options
|
52
54
|
end
|
55
|
+
end
|
53
56
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
+
def fetch_optar_objects(scope, options)
|
58
|
+
if scope
|
59
|
+
fetch_scoped_optar(scope, options)
|
60
|
+
else
|
61
|
+
fetch_default_scoped_optars(options)
|
57
62
|
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def fetch_scoped_optar(scope, options)
|
66
|
+
send(scope).opt_ar_objects(options)
|
67
|
+
end
|
68
|
+
|
69
|
+
def fetch_default_scoped_optars(options)
|
70
|
+
send(:build_default_scope).opt_ar_objects(options)
|
71
|
+
end
|
72
|
+
|
73
|
+
def throw_error(error_type, error_options)
|
74
|
+
raise send(error_type, error_options)
|
75
|
+
end
|
76
|
+
|
77
|
+
def undefined_scope(options)
|
78
|
+
msg = " :: show_as defined with Undefined Scope :: #{options[:scope]}"
|
79
|
+
OptAR::Logger.log(msg, :error)
|
80
|
+
OptAR::Errors::UndefinedScopeError.new(options)
|
81
|
+
end
|
82
|
+
|
83
|
+
def invalid_name(options)
|
84
|
+
error_options = "#{options[:name]} :: #{options[:type]}"
|
85
|
+
msg = " :: show_as defined with invalid name :: #{error_options}"
|
86
|
+
OptAR::Logger.log(msg, :error)
|
87
|
+
OptAR::Errors::DuplicateNameError.new(options)
|
88
|
+
end
|
58
89
|
end
|
59
90
|
|
60
91
|
module InstanceMethods
|
61
92
|
def opt_ar_object(options = {})
|
62
|
-
OptAR::
|
93
|
+
OptAR::OAR.new(self, options)
|
63
94
|
end
|
64
95
|
|
65
96
|
alias opt_ar_objects opt_ar_object
|
data/lib/opt_ar/version.rb
CHANGED
data/lib/opt_ar.rb
CHANGED
@@ -1,23 +1,50 @@
|
|
1
1
|
require 'opt_ar/version'
|
2
2
|
require 'active_record'
|
3
3
|
require_relative './opt_ar/optimal_ar/builder'
|
4
|
+
require_relative 'opt_ar/logger'
|
5
|
+
require_relative 'opt_ar/errors'
|
4
6
|
# Dir["#{File.dirname(__FILE__)}/lib/opt_ar/**/*.rb"].each { |f| require f }
|
5
7
|
|
8
|
+
# Base module
|
6
9
|
module OptAR
|
7
10
|
end
|
8
11
|
|
9
12
|
ActiveRecord::Base.send :include, OptAR::OptimalAR::Builder
|
10
13
|
|
11
14
|
module ActiveRecord
|
15
|
+
# Overwriting ActiveRecord::Relation to make opt_ar_objects
|
16
|
+
# method available for all relations, returning array of
|
17
|
+
# `OAR`s which we generate
|
12
18
|
class Relation
|
19
|
+
# TODO: Introduce pluck usage for relations
|
20
|
+
# if ActiveRecord::VERSION::MAJOR < 4
|
21
|
+
# to_a.opt_ar_objects(options)
|
22
|
+
# else
|
23
|
+
# pluck(options[:req_attributes]).opt_ar_objects
|
24
|
+
# end
|
13
25
|
def opt_ar_objects(options = {})
|
14
26
|
to_a.opt_ar_objects(options)
|
15
27
|
end
|
16
28
|
end
|
17
29
|
end
|
18
30
|
|
31
|
+
# Overwriting Array to make opt_ar_objects method available
|
32
|
+
# for all arrays containing ActiveRecord::Base objects, returning
|
33
|
+
# an array of `OAR`s which we generate
|
19
34
|
class Array
|
20
35
|
def opt_ar_objects(options = {})
|
21
|
-
map
|
36
|
+
map do |obj|
|
37
|
+
unless obj.is_a? ActiveRecord::Base
|
38
|
+
raise OptAR::Errors::NonActiveRecordError
|
39
|
+
end
|
40
|
+
obj.opt_ar_object(options)
|
41
|
+
end
|
22
42
|
end
|
23
43
|
end
|
44
|
+
|
45
|
+
# TODO: Implement opt_ar_objects for hash
|
46
|
+
# class Hash
|
47
|
+
# def opt_ar_objects
|
48
|
+
|
49
|
+
# end
|
50
|
+
# end
|
data/opt_ar.gemspec
CHANGED
@@ -9,15 +9,16 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ['ragav0102']
|
10
10
|
spec.email = ['ragavh123@gmail.com']
|
11
11
|
|
12
|
-
spec.summary = 'Generates memory-
|
12
|
+
spec.summary = 'Generates memory-friendly and immutable read-optimized'\
|
13
|
+
' ActiveRecord dupes for caching and other purposes'
|
13
14
|
spec.description = 'Generates memory-optimal immutable ActiveRecord dupes '\
|
14
15
|
'that are easily serializable and behaves much like '\
|
15
|
-
'
|
16
|
-
'
|
17
|
-
'optimization
|
16
|
+
'ARs. Define required attributes before-hand and use '\
|
17
|
+
'them just as you would on an AR, for better memory '\
|
18
|
+
'optimization. Ideally, suitable in place of caching '\
|
18
19
|
'AR objects with cache stores like Memcached, where '\
|
19
20
|
'serialization and de-serialization are memory-hungry'
|
20
|
-
spec.homepage =
|
21
|
+
spec.homepage = 'https://github.com/ragav0102/opt_ar'
|
21
22
|
spec.license = 'MIT'
|
22
23
|
|
23
24
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opt_ar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ragav0102
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-05-
|
11
|
+
date: 2019-05-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -81,10 +81,10 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '10.0'
|
83
83
|
description: Generates memory-optimal immutable ActiveRecord dupes that are easily
|
84
|
-
serializable and behaves much like
|
85
|
-
|
86
|
-
|
87
|
-
|
84
|
+
serializable and behaves much like ARs. Define required attributes before-hand and
|
85
|
+
use them just as you would on an AR, for better memory optimization. Ideally, suitable
|
86
|
+
in place of caching AR objects with cache stores like Memcached, where serialization
|
87
|
+
and de-serialization are memory-hungry
|
88
88
|
email:
|
89
89
|
- ragavh123@gmail.com
|
90
90
|
executables: []
|
@@ -106,7 +106,8 @@ files:
|
|
106
106
|
- lib/opt_ar/core_ext/array.rb
|
107
107
|
- lib/opt_ar/errors.rb
|
108
108
|
- lib/opt_ar/helpers/method_finder_helper.rb
|
109
|
-
- lib/opt_ar/
|
109
|
+
- lib/opt_ar/logger.rb
|
110
|
+
- lib/opt_ar/oar.rb
|
110
111
|
- lib/opt_ar/optimal_ar/builder.rb
|
111
112
|
- lib/opt_ar/version.rb
|
112
113
|
- opt_ar.gemspec
|
@@ -133,5 +134,6 @@ rubyforge_project:
|
|
133
134
|
rubygems_version: 2.7.5
|
134
135
|
signing_key:
|
135
136
|
specification_version: 4
|
136
|
-
summary: Generates memory-
|
137
|
+
summary: Generates memory-friendly and immutable read-optimized ActiveRecord dupes
|
138
|
+
for caching and other purposes
|
137
139
|
test_files: []
|