calculated_attributes 0.0.15
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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.rubocop.yml +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +83 -0
- data/Rakefile +1 -0
- data/calculated_attributes.gemspec +27 -0
- data/lib/calculated_attributes.rb +121 -0
- data/lib/calculated_attributes/version.rb +3 -0
- data/spec/lib/calculated_attributes_spec.rb +81 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/support/data.rb +7 -0
- data/spec/support/models.rb +15 -0
- data/spec/support/schema.rb +14 -0
- metadata +148 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9c877786aece3b27fdc6487e1f0fde18e972e509
|
4
|
+
data.tar.gz: 7aea77ccc13a0ac2ccc8177dfc69dc799c606100
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8376dbbcbb9eb0590c813574dea24279282b6ba01062b647c395d545926128b5cf640fd40cd986b6edbf8a4a3d74756ecf1a4e6487c961ebdecafe8791367043
|
7
|
+
data.tar.gz: 3653cf42956ff9a77528981e6429d3e372747e2b1a219870090fa108a0b5fc9367718c0d1631a3550446ada3e8848370bd5a8fd04033119cce6c03148aac252f
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- db/**/*
|
4
|
+
|
5
|
+
BlockNesting:
|
6
|
+
Max: 4
|
7
|
+
ClassLength:
|
8
|
+
Enabled: False
|
9
|
+
ClassVars:
|
10
|
+
Enabled: False
|
11
|
+
CyclomaticComplexity:
|
12
|
+
Enabled: False
|
13
|
+
Documentation:
|
14
|
+
Enabled: false
|
15
|
+
LineLength:
|
16
|
+
Enabled: false
|
17
|
+
MethodLength:
|
18
|
+
Enabled: false
|
19
|
+
Metrics/AbcSize:
|
20
|
+
Enabled: false
|
21
|
+
Metrics/PerceivedComplexity:
|
22
|
+
Enabled: false
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Aha! Labs Inc
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# CalculatedAttributes
|
2
|
+
|
3
|
+
Automatically add calculated attributes from accessory select queries to ActiveRecord models.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'calculated_attributes'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install calculated_attributes
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Add each calculated attribute to your model using the `calculated` keyword. It accepts two parameters: a symbol representing the name of the calculated attribute, and a lambda containing a string to calculate the attribute.
|
24
|
+
|
25
|
+
For example, if we have two models, `Post` and `Comment`, and `Comment` has a `post_id` attribute, we might write the following code to add a comments count to each `Post` record in a relation:
|
26
|
+
|
27
|
+
class Post < ActiveRecord::Base
|
28
|
+
...
|
29
|
+
calculated :comments_count, -> { "select count(*) from comments where comments.post_id = posts.id" }
|
30
|
+
...
|
31
|
+
end
|
32
|
+
|
33
|
+
Then, the comments count may be accessed as follows:
|
34
|
+
|
35
|
+
Post.scoped.calculated(:comments_count).first.comments_count
|
36
|
+
#=> 5
|
37
|
+
|
38
|
+
Multiple calculated attributes may be attached to each model. If we add a `Tag` model that also has a `post_id`, we can update the Post model as following:
|
39
|
+
|
40
|
+
class Post < ActiveRecord::Base
|
41
|
+
...
|
42
|
+
calculated :comments_count, -> { "select count(*) from comments where comments.post_id = posts.id" }
|
43
|
+
calculated :tags_count, -> { "select count(*) from tags where tags.post_id = posts.id" }
|
44
|
+
...
|
45
|
+
end
|
46
|
+
|
47
|
+
And then access both the `comments_count` and `tags_count` like so:
|
48
|
+
|
49
|
+
post = Post.scoped.calculated(:comments_count, :tags_count).first
|
50
|
+
post.comments_count
|
51
|
+
#=> 5
|
52
|
+
post.tags_count
|
53
|
+
#=> 2
|
54
|
+
|
55
|
+
You may also use the `calculated` method on a single model instance, like so:
|
56
|
+
|
57
|
+
Post.first.calculated(:comments_count).comments_count
|
58
|
+
#=> 5
|
59
|
+
|
60
|
+
If you have defined a `calculated` method, results of that method will be returned rather than throwing a method missing error even if you don't explicitly use the `calculated()` call on the instance:
|
61
|
+
|
62
|
+
Post.first.comments_count
|
63
|
+
#=> 5
|
64
|
+
|
65
|
+
If you like, you may define `calculated` lambdas using Arel syntax:
|
66
|
+
|
67
|
+
class Post < ActiveRecord::Base
|
68
|
+
...
|
69
|
+
calculated :comments_count, -> { Comment.select(Arel::Nodes::NamedFunction.new("COUNT", [Comment.arel_table[:id]])).where(Comment.arel_table[:post_id].eq(Post.arel_table[:id])) }
|
70
|
+
...
|
71
|
+
end
|
72
|
+
|
73
|
+
## Contributing
|
74
|
+
|
75
|
+
1. Fork it ( https://github.com/aha-app/calculated_attributes/fork )
|
76
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
77
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
78
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
79
|
+
5. Create a new Pull Request
|
80
|
+
|
81
|
+
## Credits
|
82
|
+
|
83
|
+
Written by Zach Schneider based on ideas from Chris Waters.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'calculated_attributes/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'calculated_attributes'
|
8
|
+
spec.version = CalculatedAttributes::VERSION
|
9
|
+
spec.authors = ['Zach Schneider']
|
10
|
+
spec.email = ['zach@aha.io']
|
11
|
+
spec.summary = 'Automatically add calculated attributes to ActiveRecord models.'
|
12
|
+
spec.homepage = 'https://github.com/aha-app/calculated_attributes'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
|
20
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
21
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
22
|
+
spec.add_development_dependency 'rspec', '~> 3.1'
|
23
|
+
spec.add_development_dependency 'rubocop'
|
24
|
+
spec.add_development_dependency 'sqlite3'
|
25
|
+
|
26
|
+
spec.add_dependency 'activerecord', '3.2.21'
|
27
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'calculated_attributes/version'
|
2
|
+
require 'active_record'
|
3
|
+
|
4
|
+
module CalculatedAttributes
|
5
|
+
def calculated(*args)
|
6
|
+
@config ||= CalculatedAttributes::Config.new
|
7
|
+
@config.calculated(args.first, args.last) if args.size == 2
|
8
|
+
@config
|
9
|
+
end
|
10
|
+
|
11
|
+
class CalculatedAttributes
|
12
|
+
class Config
|
13
|
+
def calculated(title = nil, lambda = nil)
|
14
|
+
@calculations ||= {}
|
15
|
+
@calculations[title] ||= lambda if title && lambda
|
16
|
+
@calculations
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
ActiveRecord::Base.extend CalculatedAttributes
|
22
|
+
|
23
|
+
ActiveRecord::Base.send(:include, Module.new do
|
24
|
+
def calculated(*args)
|
25
|
+
self.class.scoped.calculated(*args).find(id)
|
26
|
+
end
|
27
|
+
|
28
|
+
def method_missing(sym, *args, &block)
|
29
|
+
if !@attributes.include?(sym.to_s) && (self.class.calculated.calculated[sym] || self.class.base_class.calculated.calculated[sym])
|
30
|
+
Rails.logger.warn("Using calculated value without including it in the relation: #{sym}") if defined? Rails
|
31
|
+
class_with_attr =
|
32
|
+
if self.class.calculated.calculated[sym]
|
33
|
+
self.class
|
34
|
+
else
|
35
|
+
self.class.base_class
|
36
|
+
end
|
37
|
+
class_with_attr.scoped.calculated(sym).find(id).send(sym)
|
38
|
+
else
|
39
|
+
super(sym, *args, &block)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def respond_to?(method, include_private = false)
|
44
|
+
super || (!@attributes.include?(method.to_s) && (self.class.calculated.calculated[method] || self.class.base_class.calculated.calculated[method]))
|
45
|
+
end
|
46
|
+
end)
|
47
|
+
|
48
|
+
ActiveRecord::Relation.send(:include, Module.new do
|
49
|
+
def calculated(*args)
|
50
|
+
projections = arel.projections
|
51
|
+
args.each do |arg|
|
52
|
+
lam = klass.calculated.calculated[arg] || klass.base_class.calculated.calculated[arg]
|
53
|
+
sql = lam.call
|
54
|
+
if sql.is_a? String
|
55
|
+
new_projection = Arel.sql("(#{sql})").as(arg.to_s)
|
56
|
+
new_projection.calculated_attr!
|
57
|
+
projections.push new_projection
|
58
|
+
else
|
59
|
+
new_projection = sql.as(arg.to_s)
|
60
|
+
new_projection.calculated_attr!
|
61
|
+
projections.push new_projection
|
62
|
+
end
|
63
|
+
end
|
64
|
+
select(projections)
|
65
|
+
end
|
66
|
+
end)
|
67
|
+
|
68
|
+
Arel::SelectManager.send(:include, Module.new do
|
69
|
+
def projections
|
70
|
+
@ctx.projections
|
71
|
+
end
|
72
|
+
end)
|
73
|
+
|
74
|
+
module ActiveRecord
|
75
|
+
module FinderMethods
|
76
|
+
def construct_relation_for_association_find(join_dependency)
|
77
|
+
calculated_columns = arel.projections.select { |p| p.is_a?(Arel::Nodes::Node) && p.calculated_attr? }
|
78
|
+
relation = except(:includes, :eager_load, :preload, :select).select(join_dependency.columns.concat(calculated_columns))
|
79
|
+
join_dependency.calculated_columns = calculated_columns
|
80
|
+
apply_join_dependency(relation, join_dependency)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
module ActiveRecord
|
86
|
+
module Associations
|
87
|
+
class JoinDependency
|
88
|
+
attr_writer :calculated_columns
|
89
|
+
|
90
|
+
def instantiate(rows)
|
91
|
+
primary_key = join_base.aliased_primary_key
|
92
|
+
parents = {}
|
93
|
+
|
94
|
+
records = rows.map do |model|
|
95
|
+
primary_id = model[primary_key]
|
96
|
+
parent = parents[primary_id] ||= join_base.instantiate(model)
|
97
|
+
construct(parent, @associations, join_associations, model)
|
98
|
+
@calculated_columns.each { |column| parent[column.right] = model[column.right] }
|
99
|
+
parent
|
100
|
+
end.uniq
|
101
|
+
|
102
|
+
remove_duplicate_results!(active_record, records, @associations)
|
103
|
+
records
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
module Arel
|
110
|
+
module Nodes
|
111
|
+
class Node
|
112
|
+
def calculated_attr!
|
113
|
+
@is_calculated_attr = true
|
114
|
+
end
|
115
|
+
|
116
|
+
def calculated_attr?
|
117
|
+
@is_calculated_attr
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'calculated_attributes' do
|
4
|
+
it 'includes calculated attributes' do
|
5
|
+
expect(Post.scoped.calculated(:comments).first.comments).to eq(1)
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'includes multiple calculated attributes' do
|
9
|
+
post = Post.scoped.calculated(:comments, :comments_two).first
|
10
|
+
expect(post.comments).to eq(1)
|
11
|
+
expect(post.comments_two).to eq(1)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'includes chained calculated attributes' do
|
15
|
+
post = Post.scoped.calculated(:comments).calculated(:comments_two).first
|
16
|
+
expect(post.comments).to eq(1)
|
17
|
+
expect(post.comments_two).to eq(1)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'nests with where query' do
|
21
|
+
expect(Post.where(id: 1).calculated(:comments).first.comments).to eq(1)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'nests with order query' do
|
25
|
+
expect(Post.order('id DESC').calculated(:comments).first.id).to eq(Post.count)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'allows access via model instance method' do
|
29
|
+
expect(Post.first.calculated(:comments).comments).to eq(1)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'allows anonymous access via model instance method' do
|
33
|
+
expect(Post.first.comments).to eq(1)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'allows anonymous access via model instance method with STI and lambda on base class' do
|
37
|
+
expect(Tutorial.first.comments).to eq(1)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'allows anonymous access via model instance method with STI and lambda on subclass' do
|
41
|
+
expect(Article.first.sub_comments).to eq(1)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'does not allow anonymous access for nonexisting calculated block' do
|
45
|
+
expect { Post.first.some_attr }.to raise_error(NoMethodError)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'does not allow anonymous access for nonexisting calculated block with STI' do
|
49
|
+
expect { Tutorial.first.some_attr }.to raise_error(NoMethodError)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'allows access to multiple calculated attributes via model instance method' do
|
53
|
+
post = Post.first.calculated(:comments, :comments_two)
|
54
|
+
expect(post.comments).to eq(1)
|
55
|
+
expect(post.comments_two).to eq(1)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'allows attributes to be defined using AREL' do
|
59
|
+
expect(Post.scoped.calculated(:comments_arel).first.comments_arel).to eq(1)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'maintains previous scope' do
|
63
|
+
expect(Post.where(text: 'First post!').calculated(:comments).count).to eq(1)
|
64
|
+
expect(Post.where(text: 'First post!').calculated(:comments).first.comments).to eq(1)
|
65
|
+
expect(Post.where("posts.text = 'First post!'").calculated(:comments).first.comments).to eq(1)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'maintains subsequent scope' do
|
69
|
+
expect(Post.scoped.calculated(:comments).where(text: 'First post!').count).to eq(1)
|
70
|
+
expect(Post.scoped.calculated(:comments).where(text: 'First post!').first.comments).to eq(1)
|
71
|
+
expect(Post.scoped.calculated(:comments).where("posts.text = 'First post!'").first.comments).to eq(1)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'includes calculated attributes with STI and lambda on base class' do
|
75
|
+
expect(Tutorial.scoped.calculated(:comments).first.comments).to eq(1)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'includes calculated attributes with STI and lambda on subclass' do
|
79
|
+
expect(Article.scoped.calculated(:sub_comments).first.sub_comments).to eq(1)
|
80
|
+
end
|
81
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
require 'calculated_attributes'
|
2
|
+
|
3
|
+
ActiveRecord::Base.establish_connection(adapter: 'sqlite3',
|
4
|
+
database: File.dirname(__FILE__) + '/calculated_attributes.sqlite3')
|
5
|
+
|
6
|
+
load File.dirname(__FILE__) + '/support/schema.rb'
|
7
|
+
load File.dirname(__FILE__) + '/support/models.rb'
|
8
|
+
load File.dirname(__FILE__) + '/support/data.rb'
|
@@ -0,0 +1,7 @@
|
|
1
|
+
p = Post.create(text: 'First post!')
|
2
|
+
Comment.create(post_id: p.id, text: 'First comment!')
|
3
|
+
Post.create(text: 'Second post!')
|
4
|
+
t = Tutorial.create(text: 'Tutorial!')
|
5
|
+
Comment.create(post_id: t.id, text: 'First comment!')
|
6
|
+
a = Article.create(text: 'Article!')
|
7
|
+
Comment.create(post_id: a.id, text: 'First comment!')
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Post < ActiveRecord::Base
|
2
|
+
calculated :comments, -> { 'select count(*) from comments where comments.post_id = posts.id' }
|
3
|
+
calculated :comments_two, -> { 'select count(*) from comments where comments.post_id = posts.id' }
|
4
|
+
calculated :comments_arel, -> { Comment.where(Comment.arel_table[:post_id].eq(Post.arel_table[:id])).select(Arel.sql('count(*)')) }
|
5
|
+
end
|
6
|
+
|
7
|
+
class Tutorial < Post
|
8
|
+
end
|
9
|
+
|
10
|
+
class Article < Post
|
11
|
+
calculated :sub_comments, -> { 'select count(*) from comments where comments.post_id = posts.id' }
|
12
|
+
end
|
13
|
+
|
14
|
+
class Comment < ActiveRecord::Base
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: calculated_attributes
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.15
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Zach Schneider
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-06-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.1'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sqlite3
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: activerecord
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 3.2.21
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 3.2.21
|
97
|
+
description:
|
98
|
+
email:
|
99
|
+
- zach@aha.io
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- ".rspec"
|
106
|
+
- ".rubocop.yml"
|
107
|
+
- Gemfile
|
108
|
+
- LICENSE.txt
|
109
|
+
- README.md
|
110
|
+
- Rakefile
|
111
|
+
- calculated_attributes.gemspec
|
112
|
+
- lib/calculated_attributes.rb
|
113
|
+
- lib/calculated_attributes/version.rb
|
114
|
+
- spec/lib/calculated_attributes_spec.rb
|
115
|
+
- spec/spec_helper.rb
|
116
|
+
- spec/support/data.rb
|
117
|
+
- spec/support/models.rb
|
118
|
+
- spec/support/schema.rb
|
119
|
+
homepage: https://github.com/aha-app/calculated_attributes
|
120
|
+
licenses:
|
121
|
+
- MIT
|
122
|
+
metadata: {}
|
123
|
+
post_install_message:
|
124
|
+
rdoc_options: []
|
125
|
+
require_paths:
|
126
|
+
- lib
|
127
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
requirements: []
|
138
|
+
rubyforge_project:
|
139
|
+
rubygems_version: 2.4.6
|
140
|
+
signing_key:
|
141
|
+
specification_version: 4
|
142
|
+
summary: Automatically add calculated attributes to ActiveRecord models.
|
143
|
+
test_files:
|
144
|
+
- spec/lib/calculated_attributes_spec.rb
|
145
|
+
- spec/spec_helper.rb
|
146
|
+
- spec/support/data.rb
|
147
|
+
- spec/support/models.rb
|
148
|
+
- spec/support/schema.rb
|