passive_record 0.1.7 → 0.1.8
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/README.md +0 -13
- data/lib/passive_record.rb +16 -0
- data/lib/passive_record/associations.rb +10 -0
- data/lib/passive_record/class_methods.rb +13 -10
- data/lib/passive_record/core/identifier.rb +11 -2
- data/lib/passive_record/instance_methods.rb +29 -4
- data/lib/passive_record/pretty_printing.rb +2 -24
- data/lib/passive_record/version.rb +1 -1
- data/passive_record.gemspec +5 -5
- data/spec/passive_record_spec.rb +85 -51
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab5ed84f9328d3e424d8a8d15a29c00f080b78b3
|
4
|
+
data.tar.gz: 2f35779eacb19dc155d895b4a526d988f3eafc7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf7b97feb259d40a4bf9599854c5bbb297aba5cd7c9534547e0d45ee32a4ca80df652667d026786dd12cfad84545745ebd819aa0e9364c5bb59239a44ac07b5d
|
7
|
+
data.tar.gz: 7150fe4460f64351692f83e163b785d36df33eedbcbedb7e0e3c114f43c6c7a836a4ae2f7dbe6c7d818f970d3a8cabfbaaabc957bd4704e3b7e449823c807138
|
data/README.md
CHANGED
@@ -82,19 +82,6 @@ PassiveRecord may be right for you!
|
|
82
82
|
=> [Dog (id: 1)]
|
83
83
|
````
|
84
84
|
|
85
|
-
## Requirements
|
86
|
-
|
87
|
-
## Install
|
88
|
-
|
89
|
-
$ gem install passive_record
|
90
|
-
|
91
|
-
|
92
|
-
## Synopsis
|
93
|
-
|
94
|
-
$ passive_record
|
95
|
-
|
96
85
|
## Copyright
|
97
86
|
|
98
87
|
Copyright (c) 2016 Joseph Weissman
|
99
|
-
|
100
|
-
See {file:LICENSE.txt} for details.
|
data/lib/passive_record.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
1
3
|
require 'active_support'
|
2
4
|
require 'active_support/core_ext/string/inflections'
|
3
5
|
|
@@ -36,4 +38,18 @@ module PassiveRecord
|
|
36
38
|
def self.drop_all
|
37
39
|
(model_classes + model_classes.flat_map(&:descendants)).each(&:destroy_all)
|
38
40
|
end
|
41
|
+
|
42
|
+
def self.configure
|
43
|
+
yield configuration
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.configuration
|
47
|
+
@config ||= default_configuration
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.default_configuration
|
51
|
+
OpenStruct.new(
|
52
|
+
:identify_using => Identifier
|
53
|
+
)
|
54
|
+
end
|
39
55
|
end
|
@@ -10,6 +10,16 @@ module PassiveRecord
|
|
10
10
|
@associations += [assn]
|
11
11
|
end
|
12
12
|
|
13
|
+
def associations_id_syms
|
14
|
+
@associations&.map do |assn|
|
15
|
+
if assn.is_a?(HasOneAssociation) || assn.is_a?(BelongsToAssociation)
|
16
|
+
(assn.target_name_symbol.to_s + "_id").to_sym
|
17
|
+
else # plural ids
|
18
|
+
(assn.target_name_symbol.to_s + "_ids").to_sym
|
19
|
+
end
|
20
|
+
end || []
|
21
|
+
end
|
22
|
+
|
13
23
|
def belongs_to(parent_name_sym, opts={})
|
14
24
|
target_class_name = opts.delete(:class_name) { (parent_name_sym.to_s).split('_').map(&:capitalize).join }
|
15
25
|
association = BelongsToAssociation.new(self, target_class_name, parent_name_sym)
|
@@ -30,12 +30,13 @@ module PassiveRecord
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def find_by(conditions)
|
33
|
-
if conditions.is_a?(
|
34
|
-
|
35
|
-
|
36
|
-
find_by_ids(conditions)
|
37
|
-
else
|
33
|
+
#if conditions.is_a?(Array)
|
34
|
+
# find_by_ids(conditions)
|
35
|
+
if conditions.is_a?(Hash)
|
38
36
|
where(conditions).first
|
37
|
+
else # assume we have an identifier/identifiers
|
38
|
+
find(conditions)
|
39
|
+
# find_by_id(conditions)
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
@@ -55,7 +56,7 @@ module PassiveRecord
|
|
55
56
|
instance = new
|
56
57
|
|
57
58
|
instance.singleton_class.class_eval { attr_accessor :id }
|
58
|
-
instance.send(:"id=",
|
59
|
+
instance.send(:"id=", id_factory.generate(self))
|
59
60
|
|
60
61
|
register(instance)
|
61
62
|
|
@@ -75,9 +76,8 @@ module PassiveRecord
|
|
75
76
|
end
|
76
77
|
|
77
78
|
protected
|
78
|
-
def find_by_id(
|
79
|
-
|
80
|
-
instances_by_id[key] if key
|
79
|
+
def find_by_id(id_to_find)
|
80
|
+
find_by(id: id_to_find)
|
81
81
|
end
|
82
82
|
|
83
83
|
def find_by_ids(ids)
|
@@ -93,6 +93,9 @@ module PassiveRecord
|
|
93
93
|
instances_by_id[model.id] = model
|
94
94
|
self
|
95
95
|
end
|
96
|
-
end
|
97
96
|
|
97
|
+
def id_factory
|
98
|
+
PassiveRecord.configuration.identify_using
|
99
|
+
end
|
100
|
+
end
|
98
101
|
end
|
@@ -1,8 +1,11 @@
|
|
1
1
|
module PassiveRecord
|
2
2
|
class Identifier < Struct.new(:value)
|
3
3
|
def self.generate(klass)
|
4
|
-
new(klass
|
5
|
-
|
4
|
+
new(generate_id_value_for(klass))
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.generate_id_value_for(klass)
|
8
|
+
klass.count+1
|
6
9
|
end
|
7
10
|
|
8
11
|
def ==(other_id)
|
@@ -13,4 +16,10 @@ module PassiveRecord
|
|
13
16
|
value
|
14
17
|
end
|
15
18
|
end
|
19
|
+
|
20
|
+
class SecureRandomIdentifier < Identifier
|
21
|
+
def self.generate_id_value_for(*)
|
22
|
+
SecureRandom.uuid
|
23
|
+
end
|
24
|
+
end
|
16
25
|
end
|
@@ -2,6 +2,31 @@ module PassiveRecord
|
|
2
2
|
module InstanceMethods
|
3
3
|
include PrettyPrinting
|
4
4
|
|
5
|
+
def attribute_names
|
6
|
+
attr_names = instance_variables
|
7
|
+
attr_names += self.class.associations_id_syms
|
8
|
+
attr_names += members rescue []
|
9
|
+
attr_names.reject! { |name| name.to_s.start_with?("@_") }
|
10
|
+
attr_names - blacklisted_attribute_names
|
11
|
+
end
|
12
|
+
|
13
|
+
def blacklisted_attribute_names
|
14
|
+
[]
|
15
|
+
end
|
16
|
+
|
17
|
+
# from http://stackoverflow.com/a/8417341/90042
|
18
|
+
def to_h
|
19
|
+
Hash[
|
20
|
+
attribute_names.
|
21
|
+
map do |name| [
|
22
|
+
name.to_s.gsub("@","").to_sym, # key
|
23
|
+
(instance_variable_get(name) rescue send(name))] # val
|
24
|
+
end
|
25
|
+
]
|
26
|
+
end
|
27
|
+
|
28
|
+
###
|
29
|
+
|
5
30
|
def respond_to?(meth,*args,&blk)
|
6
31
|
if find_relation_by_target_name_symbol(meth)
|
7
32
|
true
|
@@ -12,7 +37,7 @@ module PassiveRecord
|
|
12
37
|
|
13
38
|
def method_missing(meth, *args, &blk)
|
14
39
|
if (matching_relation = find_relation_by_target_name_symbol(meth))
|
15
|
-
send_relation(matching_relation, meth, *args
|
40
|
+
send_relation(matching_relation, meth, *args)
|
16
41
|
else
|
17
42
|
super(meth,*args,&blk)
|
18
43
|
end
|
@@ -20,7 +45,7 @@ module PassiveRecord
|
|
20
45
|
|
21
46
|
protected
|
22
47
|
|
23
|
-
def send_relation(matching_relation, meth, *args
|
48
|
+
def send_relation(matching_relation, meth, *args)
|
24
49
|
target_name = matching_relation.association.target_name_symbol.to_s
|
25
50
|
|
26
51
|
case meth.to_s
|
@@ -40,9 +65,9 @@ module PassiveRecord
|
|
40
65
|
end
|
41
66
|
|
42
67
|
def relata
|
43
|
-
@_relata ||= self.class.associations
|
68
|
+
@_relata ||= self.class.associations&.map do |assn|
|
44
69
|
assn.to_relation(self)
|
45
|
-
end
|
70
|
+
end || []
|
46
71
|
end
|
47
72
|
|
48
73
|
private
|
@@ -1,33 +1,11 @@
|
|
1
1
|
module PassiveRecord
|
2
2
|
module PrettyPrinting
|
3
3
|
def inspect
|
4
|
-
pretty_vars =
|
4
|
+
pretty_vars = to_h.map do |k,v|
|
5
5
|
"#{k.to_s.gsub(/^\@/,'')}: #{v.inspect}"
|
6
6
|
end.join(', ')
|
7
|
-
"#{self.class.name} (#{pretty_vars})"
|
8
|
-
end
|
9
|
-
|
10
|
-
protected
|
11
|
-
|
12
|
-
def uninspectable_instance_variables
|
13
|
-
[]
|
14
|
-
end
|
15
7
|
|
16
|
-
|
17
|
-
|
18
|
-
def inspectable_instance_variables
|
19
|
-
vars = instance_variables
|
20
|
-
vars += members rescue []
|
21
|
-
vars - uninspectable_instance_variables
|
22
|
-
end
|
23
|
-
|
24
|
-
# from http://stackoverflow.com/a/8417341/90042
|
25
|
-
def instance_variables_hash
|
26
|
-
Hash[
|
27
|
-
inspectable_instance_variables.
|
28
|
-
reject { |sym| sym.to_s.start_with?("@_") }.
|
29
|
-
map { |name| [name, (instance_variable_get(name) rescue send(name))] }
|
30
|
-
]
|
8
|
+
"#{self.class.name} (#{pretty_vars})"
|
31
9
|
end
|
32
10
|
end
|
33
11
|
end
|
data/passive_record.gemspec
CHANGED
@@ -7,12 +7,12 @@ Gem::Specification.new do |gem|
|
|
7
7
|
|
8
8
|
gem.name = gemspec.fetch('name')
|
9
9
|
gem.version = gemspec.fetch('version') do
|
10
|
-
|
11
|
-
|
10
|
+
lib_dir = File.join(File.dirname(__FILE__),'lib')
|
11
|
+
$LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
require 'passive_record/version'
|
14
|
+
PassiveRecord::VERSION
|
15
|
+
end
|
16
16
|
|
17
17
|
gem.summary = gemspec['summary']
|
18
18
|
gem.description = gemspec['description']
|
data/spec/passive_record_spec.rb
CHANGED
@@ -16,82 +16,95 @@ describe PassiveRecord do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
describe
|
20
|
-
|
19
|
+
describe "passive record models" do
|
20
|
+
context "with a simple model including PR" do
|
21
21
|
let!(:model) { SimpleModel.create(foo: value) }
|
22
22
|
let(:value) { 'foo_value' }
|
23
23
|
|
24
|
-
describe "
|
25
|
-
|
26
|
-
|
24
|
+
describe "instance methods" do
|
25
|
+
describe "#inspect" do
|
26
|
+
it 'should report attribute details' do
|
27
|
+
expect(model.inspect).to eq("SimpleModel (id: #{model.id.inspect}, foo: \"foo_value\")")
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should report relations' do
|
31
|
+
dog = Dog.create
|
32
|
+
expect(dog.inspect).to eq("Dog (id: #{dog.id.inspect}, created_at: #{dog.created_at}, sound: \"bark\", child_id: nil)")
|
33
|
+
end
|
27
34
|
end
|
28
|
-
end
|
29
35
|
|
30
|
-
|
31
|
-
|
32
|
-
|
36
|
+
describe "#id" do
|
37
|
+
it 'should be retrievable by id' do
|
38
|
+
expect(SimpleModel.find_by(model.id)).to eq(model)
|
39
|
+
end
|
33
40
|
end
|
34
41
|
end
|
35
42
|
|
36
|
-
|
43
|
+
describe "class methods" do
|
44
|
+
describe "#first" do
|
45
|
+
it 'should find the first model' do
|
46
|
+
expect(Model.first).to eq(Model.find(1))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
37
50
|
describe "#count" do
|
38
51
|
it 'should indicate the size of the models list' do
|
39
52
|
expect { SimpleModel.create }.to change { SimpleModel.count }.by(1)
|
40
53
|
end
|
41
54
|
end
|
42
|
-
end
|
43
55
|
|
44
|
-
|
45
|
-
|
46
|
-
|
56
|
+
describe "#create" do
|
57
|
+
it 'should assign attributes' do
|
58
|
+
expect(model.foo).to eq('foo_value')
|
59
|
+
end
|
47
60
|
end
|
48
|
-
end
|
49
61
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
it 'should remove all models' do
|
57
|
-
expect { SimpleModel.destroy_all }.to change { SimpleModel.count }.by(-SimpleModel.count)
|
58
|
-
end
|
59
|
-
end
|
62
|
+
describe "#destroy_all" do
|
63
|
+
before {
|
64
|
+
SimpleModel.create(foo: 'val1')
|
65
|
+
SimpleModel.create(foo: 'val2')
|
66
|
+
}
|
60
67
|
|
61
|
-
|
62
|
-
|
63
|
-
subject(:model) { SimpleModel.create }
|
64
|
-
it 'should lookup a record based on an identifier' do
|
65
|
-
expect(SimpleModel.find(-1)).to eq(nil)
|
66
|
-
expect(SimpleModel.find(model.id)).to eq(model)
|
68
|
+
it 'should remove all models' do
|
69
|
+
expect { SimpleModel.destroy_all }.to change { SimpleModel.count }.by(-SimpleModel.count)
|
67
70
|
end
|
71
|
+
end
|
68
72
|
|
69
|
-
|
70
|
-
|
71
|
-
|
73
|
+
context 'querying by id' do
|
74
|
+
describe "#find" do
|
75
|
+
subject(:model) { SimpleModel.create }
|
76
|
+
it 'should lookup a record based on an identifier' do
|
77
|
+
expect(SimpleModel.find(-1)).to eq(nil)
|
78
|
+
expect(SimpleModel.find(model.id)).to eq(model)
|
79
|
+
end
|
72
80
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
end
|
77
|
-
end
|
81
|
+
it 'should lookup records based on primary key value' do
|
82
|
+
expect(SimpleModel.find(model.id.value)).to eq(model)
|
83
|
+
end
|
78
84
|
|
79
|
-
|
80
|
-
|
81
|
-
|
85
|
+
it 'should lookup records based on ids' do
|
86
|
+
model_b = SimpleModel.create
|
87
|
+
expect(SimpleModel.find([model.id, model_b.id])).to eq([model, model_b])
|
88
|
+
end
|
82
89
|
end
|
83
90
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
expect{SimpleModel.where(id: 'new_id').create }.to change{SimpleModel.count}.by(1)
|
88
|
-
end
|
91
|
+
describe "#where" do
|
92
|
+
it 'should return a query obj' do
|
93
|
+
expect(SimpleModel.where(id: 'fake_id')).to be_a(PassiveRecord::Core::Query)
|
89
94
|
end
|
90
95
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
96
|
+
context "queries" do
|
97
|
+
describe "#create" do
|
98
|
+
it 'should create objects' do
|
99
|
+
expect{SimpleModel.where(id: 'new_id').create }.to change{SimpleModel.count}.by(1)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "#first_or_create" do
|
104
|
+
it 'should create the object or return matching' do
|
105
|
+
expect{SimpleModel.where(id: 'another_id').first_or_create }.to change{SimpleModel.count}.by(1)
|
106
|
+
expect{SimpleModel.where(id: 'another_id').first_or_create }.not_to change{SimpleModel.count}
|
107
|
+
end
|
95
108
|
end
|
96
109
|
end
|
97
110
|
end
|
@@ -257,5 +270,26 @@ describe Model do
|
|
257
270
|
end
|
258
271
|
end
|
259
272
|
end
|
273
|
+
end
|
260
274
|
|
275
|
+
describe "configuration" do
|
276
|
+
describe 'configuring id factory' do
|
277
|
+
context 'with default config' do
|
278
|
+
it 'should generate simple identifiers' do
|
279
|
+
expect(Model.create.id).to be_a(PassiveRecord::Identifier)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
context 'with a new id factory configured' do
|
284
|
+
before do
|
285
|
+
PassiveRecord.configure do |passive_records|
|
286
|
+
passive_records.identify_using = PassiveRecord::SecureRandomIdentifier
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
it 'should generate uuids' do
|
291
|
+
expect(Model.create.id).to be_a(PassiveRecord::SecureRandomIdentifier)
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
261
295
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: passive_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joseph Weissman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-02-
|
11
|
+
date: 2016-02-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -170,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
170
|
version: '0'
|
171
171
|
requirements: []
|
172
172
|
rubyforge_project:
|
173
|
-
rubygems_version: 2.
|
173
|
+
rubygems_version: 2.5.1
|
174
174
|
signing_key:
|
175
175
|
specification_version: 4
|
176
176
|
summary: no-persistence relational algebra
|