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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bd4210b6d42edbbc3b345887b2a15918d452fdd2
4
- data.tar.gz: c5c73ddb836c84ceaaf9290e829f7b7d31ae6e20
3
+ metadata.gz: ab5ed84f9328d3e424d8a8d15a29c00f080b78b3
4
+ data.tar.gz: 2f35779eacb19dc155d895b4a526d988f3eafc7f
5
5
  SHA512:
6
- metadata.gz: c56f0f03af33458ed3a8d0e0d8b8d4795187df9197a71c95625a688f47636b1898c4ce03450142bc4baaedf615c70b34ca075e018e038cdb2731a05e94254f07
7
- data.tar.gz: 18e488e25f0ad1a0ca791920160bd0fc7f4c3fb49987f1801fa5f1485aa93dd8463ca5cf8be723ae966a5b43544c69c15aa7ea640335aba4342f4dc6780c1f07
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.
@@ -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?(Identifier)
34
- find_by_id(conditions)
35
- elsif conditions.is_a?(Array) && conditions.all? { |c| c.is_a?(Identifier) }
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=", Identifier.generate(self))
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(_id)
79
- key = instances_by_id.keys.detect { |id,_| id == _id }
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.count+1)
5
- # TODO maybe config to activate SecureRandom.uuid?
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, &blk)
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, &blk)
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.map do |assn|
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 = instance_variables_hash.map do |k,v|
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
- private
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
@@ -1,4 +1,4 @@
1
1
  module PassiveRecord
2
2
  # passive_record version
3
- VERSION = "0.1.7"
3
+ VERSION = "0.1.8"
4
4
  end
@@ -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
- lib_dir = File.join(File.dirname(__FILE__),'lib')
11
- $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
10
+ lib_dir = File.join(File.dirname(__FILE__),'lib')
11
+ $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
12
12
 
13
- require 'passive_record/version'
14
- PassiveRecord::VERSION
15
- end
13
+ require 'passive_record/version'
14
+ PassiveRecord::VERSION
15
+ end
16
16
 
17
17
  gem.summary = gemspec['summary']
18
18
  gem.description = gemspec['description']
@@ -16,82 +16,95 @@ describe PassiveRecord do
16
16
  end
17
17
  end
18
18
 
19
- describe Model do
20
- describe "with a simple model including PR" do
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 "#inspect" do
25
- it 'should report attribute details' do
26
- expect(model.inspect).to eq("SimpleModel (id: 1, foo: \"foo_value\")")
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
- describe "#id" do
31
- it 'should be retrievable by id' do
32
- expect(SimpleModel.find_by(model.id)).to eq(model)
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
- context 'should be enumerable over models' do
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
- describe "#create" do
45
- it 'should assign attributes' do
46
- expect(model.foo).to eq('foo_value')
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
- describe "#destroy_all" do
51
- before {
52
- SimpleModel.create(foo: 'val1')
53
- SimpleModel.create(foo: 'val2')
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
- context 'querying by id' do
62
- describe "#find" do
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
- it 'should lookup records based on primary key value' do
70
- expect(SimpleModel.find(model.id.value)).to eq(model)
71
- end
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
- it 'should lookup records based on ids' do
74
- model_b = SimpleModel.create
75
- expect(SimpleModel.find([model.id, model_b.id])).to eq([model, model_b])
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
- describe "#where" do
80
- it 'should return a query obj' do
81
- expect(SimpleModel.where(id: 'fake_id')).to be_a(PassiveRecord::Core::Query)
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
- context "queries" do
85
- describe "#create" do
86
- it 'should create objects' do
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
- describe "#first_or_create" do
92
- it 'should create the object or return matching' do
93
- expect{SimpleModel.where(id: 'another_id').first_or_create }.to change{SimpleModel.count}.by(1)
94
- expect{SimpleModel.where(id: 'another_id').first_or_create }.not_to change{SimpleModel.count}
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.7
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-22 00:00:00.000000000 Z
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.4.5.1
173
+ rubygems_version: 2.5.1
174
174
  signing_key:
175
175
  specification_version: 4
176
176
  summary: no-persistence relational algebra