active_record_batteries 1.0.0
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/MIT-LICENSE +20 -0
- data/Rakefile +14 -0
- data/lib/active_record_batteries.rb +7 -0
- data/lib/active_record_batteries/concerns.rb +11 -0
- data/lib/active_record_batteries/concerns/deletable.rb +22 -0
- data/lib/active_record_batteries/concerns/filterable.rb +30 -0
- data/lib/active_record_batteries/concerns/paginable.rb +56 -0
- data/lib/active_record_batteries/concerns/relationship_scopes.rb +24 -0
- data/lib/active_record_batteries/concerns/sluggable.rb +70 -0
- data/lib/active_record_batteries/engine.rb +5 -0
- data/lib/active_record_batteries/loader.rb +19 -0
- data/lib/active_record_batteries/version.rb +3 -0
- data/lib/tasks/active_record_batteries_tasks.rake +4 -0
- data/spec/active_record_batteries_spec.rb +200 -0
- data/spec/spec_helper.rb +55 -0
- metadata +103 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 627d133bd03a971733af4b6c13f785c7818fc091
|
4
|
+
data.tar.gz: da576d73fc56b2908ee439d57602f16190393d05
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dd346dedc4c333d84854dbf6ba7c207d64ee1c33cd27f3c14f7ed1decba4e66c64a86f0931616f03e05d811ec49caaf33e6b2e61dde007d20867f7f8e5859300
|
7
|
+
data.tar.gz: a9d073f004d367713145512ef781600970b3b39f177e29fa6c199836d0f37cf4132efc3c76e32edd6ae8a2dc665fd56a6a2ac39126a7d29c1cd578ac71e87fd9
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2015
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rspec/core'
|
8
|
+
require 'rspec/core/rake_task'
|
9
|
+
|
10
|
+
RSpec::Core::RakeTask.new(:spec)
|
11
|
+
|
12
|
+
load 'rails/tasks/statistics.rake'
|
13
|
+
|
14
|
+
Bundler::GemHelper.install_tasks
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module ActiveRecordBatteries
|
2
|
+
module Concerns
|
3
|
+
extend ActiveSupport::Autoload
|
4
|
+
|
5
|
+
autoload :Deletable, 'active_record_batteries/concerns/deletable'
|
6
|
+
autoload :Filterable, 'active_record_batteries/concerns/filterable'
|
7
|
+
autoload :Paginable, 'active_record_batteries/concerns/paginable'
|
8
|
+
autoload :Sluggable, 'active_record_batteries/concerns/sluggable'
|
9
|
+
autoload :RelationshipScopes, 'active_record_batteries/concerns/relationship_scopes'
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ActiveRecordBatteries
|
2
|
+
module Concerns
|
3
|
+
module Deletable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
default_scope { where(deleted_at: nil) }
|
8
|
+
|
9
|
+
scope :including_deleted, -> { unscope(where: :deleted_at) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def delete!
|
13
|
+
self.deleted_at = Time.current
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def deleted?
|
18
|
+
!!self.deleted_at
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ActiveRecordBatteries
|
2
|
+
module Concerns
|
3
|
+
module Filterable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
scope :filtered, ->(values) {
|
8
|
+
current = all
|
9
|
+
filters.each do |key, method|
|
10
|
+
if values.try(:key?, key) && current.respond_to?(method)
|
11
|
+
current = current.send(method, values[key])
|
12
|
+
end
|
13
|
+
end
|
14
|
+
current
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
module ClassMethods
|
19
|
+
def filter_add(method_name, callable = nil)
|
20
|
+
scope(method_name, callable) if callable
|
21
|
+
filters[method_name] = method_name
|
22
|
+
end
|
23
|
+
|
24
|
+
def filters
|
25
|
+
@filters ||= {}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module ActiveRecordBatteries
|
2
|
+
module Concerns
|
3
|
+
module Paginable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
# Default items per page
|
8
|
+
page_items 25
|
9
|
+
|
10
|
+
scope :paginate, lambda { |page, page_items = @page_items|
|
11
|
+
limit(page_items)
|
12
|
+
.offset(([page.to_i, 1].max - 1) * page_items)
|
13
|
+
.extending do
|
14
|
+
|
15
|
+
def current_page
|
16
|
+
@current_page ||=
|
17
|
+
if total_pages.zero?
|
18
|
+
0
|
19
|
+
else
|
20
|
+
(offset_value / limit_value.to_f).ceil + 1
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# If pagination is used this
|
25
|
+
def total_items
|
26
|
+
@total_items ||=
|
27
|
+
begin
|
28
|
+
total_rows = except(:offset, :limit, :order)
|
29
|
+
total_rows = total_rows.except(:includes) if eager_loading?
|
30
|
+
total_rows.distinct(:id).count
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def total_pages
|
35
|
+
@total_pages ||=
|
36
|
+
begin
|
37
|
+
(total_items / limit_value.to_f).ceil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
module ClassMethods
|
45
|
+
def page_items(items)
|
46
|
+
@page_items = items
|
47
|
+
end
|
48
|
+
|
49
|
+
def pages(page_items = @page_items)
|
50
|
+
(all.except(:offset, :limit, :order, :includes)
|
51
|
+
.distinct(:id).count / page_items.to_f).ceil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module ActiveRecordBatteries
|
2
|
+
module Concerns
|
3
|
+
module RelationshipScopes
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
module ClassMethods
|
7
|
+
def relationship_scopes(relationship, suffix = nil)
|
8
|
+
suffix ||= relationship
|
9
|
+
|
10
|
+
with_scope_name = "with_#{ suffix }".to_sym
|
11
|
+
include_scope_name = "include_#{ suffix }".to_sym
|
12
|
+
|
13
|
+
scope with_scope_name, -> { joins(relationship) }
|
14
|
+
scope include_scope_name, -> { includes(relationship) }
|
15
|
+
scope "and_#{ suffix }".to_sym, -> { send(with_scope_name).send(include_scope_name) }
|
16
|
+
scope "pload_#{ suffix }".to_sym, -> { preload(relationship) }
|
17
|
+
scope "eload_#{ suffix }".to_sym, -> { eager_load(relationship) }
|
18
|
+
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module ActiveRecordBatteries
|
2
|
+
module Concerns
|
3
|
+
module Sluggable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
# Backwards compatibility
|
8
|
+
slug_base_column :name
|
9
|
+
|
10
|
+
# Be sure to create a valid slug before validating and saving.
|
11
|
+
before_validation :set_slug, on: [:create, :update]
|
12
|
+
after_validation :delete_slug_errors
|
13
|
+
|
14
|
+
# Scope to query by slug
|
15
|
+
scope :by_slug, ->(slug) { where(slug: slug) }
|
16
|
+
|
17
|
+
# Slug must be present
|
18
|
+
validates :slug, presence: true, uniqueness:true, length: { maximum: 256 }
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
def slug_base_column(column_name)
|
23
|
+
@slug_base_column_name = column_name.to_sym
|
24
|
+
end
|
25
|
+
|
26
|
+
# Find by slug
|
27
|
+
def find_by_slug(slug)
|
28
|
+
by_slug(slug).take
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_param
|
33
|
+
slug
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def slug_base_column_value
|
39
|
+
send(self.class.instance_variable_get(:@slug_base_column_name))
|
40
|
+
end
|
41
|
+
|
42
|
+
def set_slug
|
43
|
+
self.slug = qualify_slug(slug_base_column_value.parameterize) if
|
44
|
+
slug_base_column_value.present? && slug.blank?
|
45
|
+
end
|
46
|
+
|
47
|
+
def delete_slug_errors
|
48
|
+
errors.delete(:slug)
|
49
|
+
end
|
50
|
+
|
51
|
+
def qualify_slug(base_slug)
|
52
|
+
tentative_slug = base_slug
|
53
|
+
while duplicate_slug?(tentative_slug)
|
54
|
+
tentative_slug = generate_slug_name(base_slug)
|
55
|
+
end
|
56
|
+
tentative_slug
|
57
|
+
end
|
58
|
+
|
59
|
+
def duplicate_slug?(slug)
|
60
|
+
self.class
|
61
|
+
.where.not(id: id)
|
62
|
+
.exists?(slug: slug)
|
63
|
+
end
|
64
|
+
|
65
|
+
def generate_slug_name(slug)
|
66
|
+
"#{slug}-#{SecureRandom.urlsafe_base64(4)}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ActiveRecordBatteries
|
2
|
+
module Loader
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def batteries! (*modules)
|
7
|
+
modules = modules.is_a?(Array) ? modules : [ modules ]
|
8
|
+
|
9
|
+
modules.each.map{|i| i.to_s.camelize }.each do |mod|
|
10
|
+
include ActiveRecordBatteries::Concerns.const_get(mod)
|
11
|
+
end
|
12
|
+
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
ActiveRecord::Base.send(:include, self)
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe ActiveRecordBatteries do
|
4
|
+
before :all do
|
5
|
+
# Have some authors
|
6
|
+
Author.create((1..5).map { |i| { name: SecureRandom.urlsafe_base64(5) } })
|
7
|
+
|
8
|
+
# And have eah author have some articles
|
9
|
+
Author.all.each do |author|
|
10
|
+
Article.create((1..10).map { |i|
|
11
|
+
{
|
12
|
+
title: SecureRandom.urlsafe_base64(10),
|
13
|
+
body: SecureRandom.urlsafe_base64(100),
|
14
|
+
author: author
|
15
|
+
}
|
16
|
+
})
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "Deletable" do
|
21
|
+
before :all do
|
22
|
+
Article.create(title: "article_deletable", author: Author.first)
|
23
|
+
end
|
24
|
+
|
25
|
+
after :all do
|
26
|
+
Article.including_deleted.find_by(title: "article_deletable").destroy
|
27
|
+
end
|
28
|
+
|
29
|
+
it "new instance should not deleted" do
|
30
|
+
expect(Article.new.deleted?).to be false
|
31
|
+
end
|
32
|
+
|
33
|
+
it "new instance should be deleted" do
|
34
|
+
expect(Article.new(deleted_at: Date.today).deleted?).to be true
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should delete a new instance" do
|
38
|
+
obj = Article.new
|
39
|
+
obj.delete!
|
40
|
+
|
41
|
+
expect(obj.deleted?).to be true
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should not be deleted" do
|
45
|
+
obj = Article.find_by(title: "article_deletable")
|
46
|
+
|
47
|
+
expect(obj.deleted?).to be false
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should delete" do
|
51
|
+
obj = Article.find_by(title: "article_deletable")
|
52
|
+
obj.delete!
|
53
|
+
obj.save
|
54
|
+
|
55
|
+
expect(obj.deleted?).to be true
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should not find" do
|
59
|
+
obj = Article.find_by(title: "article_deletable")
|
60
|
+
expect(obj).to eq(nil)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should find" do
|
64
|
+
obj = Article.including_deleted.find_by(title: "article_deletable")
|
65
|
+
expect(obj).not_to eq(nil)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should stay deleted" do
|
69
|
+
obj = Article.including_deleted.find_by(title: "article_deletable")
|
70
|
+
expect(obj.deleted?).to be true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "Filterable" do
|
75
|
+
before :all do
|
76
|
+
Article.create(title: "article_filterable", author: Author.first)
|
77
|
+
Article.create(title: "article_filterable2", author: Author.first, slug: 'filtered_1')
|
78
|
+
end
|
79
|
+
|
80
|
+
after :all do
|
81
|
+
Article.by_title("article_filterable").destroy_all
|
82
|
+
Article.by_title("article_filterable2").destroy_all
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should be hash" do
|
86
|
+
expect(Article.filters).to be_an_instance_of(Hash)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should have filters" do
|
90
|
+
expect(Article.filters.keys.size).to be > 0
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should have filter" do
|
94
|
+
expect(Article.filters[:by_title]).to be_truthy
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should find" do
|
98
|
+
results = Article.by_title("article_filterable")
|
99
|
+
expect(results).not_to be_empty
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should filter" do
|
103
|
+
results = Article.filtered(by_title: "article_filterable2", by_slug: 'filtered_1')
|
104
|
+
expect(results).not_to be_empty
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "Paginable" do
|
109
|
+
it "should set items per page" do
|
110
|
+
expect(Author.page_items(2)).to eql(2)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should count pages" do
|
114
|
+
expect(Article.pages).to eql((Article.count / 5.0).ceil)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should count pages with parameter passed" do
|
118
|
+
expect(Article.pages(3)).to eql((Article.count / 3.0).ceil)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should paginate" do
|
122
|
+
expect(Article.paginate(2).current_page).to eq(2)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should paginate with params" do
|
126
|
+
expect(Article.paginate(3, 50).current_page).to eq(3)
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should not lose items" do
|
130
|
+
expect(Article.paginate(1).total_items).to eq(Article.count)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should count pages correctly after pagination" do
|
134
|
+
expect(Article.paginate(2).total_pages).to eq(Article.pages)
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should not be affected by includes" do
|
138
|
+
expect(Author.includes(:articles).
|
139
|
+
paginate(2).
|
140
|
+
total_pages).to eq(Author.pages)
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should not be affected by joins" do
|
144
|
+
expect(Author.joins(:articles).
|
145
|
+
paginate(2).
|
146
|
+
total_pages).to eq(Author.pages)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
context "RelationshipScopes" do
|
151
|
+
before :all do
|
152
|
+
Author.create(name: "articleless")
|
153
|
+
end
|
154
|
+
|
155
|
+
# Scopes should be added
|
156
|
+
[ :with_articles, :include_articles, :and_articles,
|
157
|
+
:pload_articles, :eload_articles ].each do |method|
|
158
|
+
it "should respond to #{method}" do
|
159
|
+
expect(Author.respond_to?(method)).to be true
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should not have articles preloaded" do
|
164
|
+
author = Author.first
|
165
|
+
expect(author.articles.loaded?).to be false
|
166
|
+
end
|
167
|
+
|
168
|
+
it "should have articles included" do
|
169
|
+
author = Author.include_articles.first
|
170
|
+
|
171
|
+
expect(author.articles.loaded?).to be true
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should have articles preloaded" do
|
175
|
+
author = Author.pload_articles.first
|
176
|
+
|
177
|
+
expect(author.articles.loaded?).to be true
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should have articles eager loaded" do
|
181
|
+
author = Author.eload_articles.first
|
182
|
+
|
183
|
+
expect(author.articles.loaded?).to be true
|
184
|
+
end
|
185
|
+
|
186
|
+
it "should join but not preload" do
|
187
|
+
author = Author.with_articles.first
|
188
|
+
|
189
|
+
expect(author.articles.loaded?).to be false
|
190
|
+
end
|
191
|
+
|
192
|
+
it "should inner join" do
|
193
|
+
expect(Author.and_articles.where(name: "articleless")).to be_empty
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should not inner join" do
|
197
|
+
expect(Author.pload_articles.where(name: "articleless")).not_to be_empty
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rails/all'
|
2
|
+
require 'active_record_batteries'
|
3
|
+
|
4
|
+
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
|
5
|
+
ActiveRecord::Schema.verbose = false
|
6
|
+
|
7
|
+
ActiveRecord::Schema.define do
|
8
|
+
self.verbose = false
|
9
|
+
|
10
|
+
create_table :authors do |t|
|
11
|
+
t.string :name
|
12
|
+
|
13
|
+
# Sluggable
|
14
|
+
t.string :slug
|
15
|
+
|
16
|
+
t.timestamps null: false
|
17
|
+
end
|
18
|
+
|
19
|
+
create_table :articles do |t|
|
20
|
+
t.string :title
|
21
|
+
t.text :body
|
22
|
+
t.references :author
|
23
|
+
|
24
|
+
# Sluggable
|
25
|
+
t.string :slug
|
26
|
+
|
27
|
+
# Deletable
|
28
|
+
t.datetime :deleted_at
|
29
|
+
|
30
|
+
t.timestamps null: false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Author < ActiveRecord::Base
|
35
|
+
batteries! :sluggable, :paginable, :filterable, :relationship_scopes
|
36
|
+
|
37
|
+
has_many :articles
|
38
|
+
|
39
|
+
filter_add :by_slug
|
40
|
+
|
41
|
+
relationship_scopes :articles
|
42
|
+
end
|
43
|
+
|
44
|
+
class Article < ActiveRecord::Base
|
45
|
+
batteries! :sluggable, :paginable, :filterable, :relationship_scopes, :deletable
|
46
|
+
|
47
|
+
belongs_to :author
|
48
|
+
|
49
|
+
slug_base_column :title
|
50
|
+
|
51
|
+
filter_add :by_slug
|
52
|
+
filter_add :by_title, ->(title) { where(title: title) }
|
53
|
+
|
54
|
+
page_items 5
|
55
|
+
end
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active_record_batteries
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Francisco Soto
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-05-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.2.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.2.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sqlite3
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec-rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Several small active record modules to empower models in a simple way.
|
56
|
+
email:
|
57
|
+
- ebobby@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- MIT-LICENSE
|
63
|
+
- Rakefile
|
64
|
+
- lib/active_record_batteries.rb
|
65
|
+
- lib/active_record_batteries/concerns.rb
|
66
|
+
- lib/active_record_batteries/concerns/deletable.rb
|
67
|
+
- lib/active_record_batteries/concerns/filterable.rb
|
68
|
+
- lib/active_record_batteries/concerns/paginable.rb
|
69
|
+
- lib/active_record_batteries/concerns/relationship_scopes.rb
|
70
|
+
- lib/active_record_batteries/concerns/sluggable.rb
|
71
|
+
- lib/active_record_batteries/engine.rb
|
72
|
+
- lib/active_record_batteries/loader.rb
|
73
|
+
- lib/active_record_batteries/version.rb
|
74
|
+
- lib/tasks/active_record_batteries_tasks.rake
|
75
|
+
- spec/active_record_batteries_spec.rb
|
76
|
+
- spec/spec_helper.rb
|
77
|
+
homepage: https://github.com/ebobby/active_record_batteries
|
78
|
+
licenses:
|
79
|
+
- MIT
|
80
|
+
metadata: {}
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 2.4.5
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: ActiveRecord with Batteries. Extensions to make life easier.
|
101
|
+
test_files:
|
102
|
+
- spec/active_record_batteries_spec.rb
|
103
|
+
- spec/spec_helper.rb
|