passive_record 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
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