ssdb-attr 0.1.3 → 0.1.4

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: 42862ff9c47b1a76de97dad8d083f9f600f59899
4
- data.tar.gz: 29d3a85d0b87e99d2b392d571a705c8c0bf31b9b
3
+ metadata.gz: 3d0a8577ee7cc342983ced7c743a36fb4bf06a99
4
+ data.tar.gz: c202f59301160470540f18f6fd8bfb7a6c346d97
5
5
  SHA512:
6
- metadata.gz: 015184c70c5f94521c89f9e25f7a6d3c1d4c695b96ffbc70d239b8a706ccd87b968cf7f0240af359066eed9c86983fae5d5c3db20c7f6a0b8d86e605cf3bea65
7
- data.tar.gz: bcf2ca89d68a6fe73ff897b8300e825ac2de3973c08a85a270e64a89ea8d22239304167004ce0398a3471d6a014df15bc3f96056641cf4abccc97a113fcd73e2
6
+ metadata.gz: 0ab615231b7df6dc1bc6e9a9db48c1120150636c474961ba9d0653c7634e4bbe9580cf360fa4951d9f8257ab7f48b7ff98fee9f19b3c4478275ecb9cfe294110
7
+ data.tar.gz: 18e23b76f1d825bc3dd5bfb26be2756c976d06f58e31aaade8bb89393d6dbcd29c2380c2dca7dd3d13abac32352179813e3f3846fb36acda64daf1eab2ab14f9
data/README.md CHANGED
@@ -6,6 +6,10 @@ This gem provides an intuitive interface to define attributes on your ActiveMode
6
6
 
7
7
  # Changelog
8
8
 
9
+ ### 0.1.4
10
+
11
+ - Add `SSDBAttr.load_attrs(objects, *fields)` to load multiple attrs for multiple same objects at one time.
12
+
9
13
  ### 0.1.3
10
14
 
11
15
  - Add `load_ssdb_attrs` to get multiple values from SSDB once to avoid multiple SSDB calls.
@@ -93,5 +93,44 @@ module SSDBAttr
93
93
  end
94
94
  end
95
95
 
96
+ #
97
+ # 获取多个 AR 对象的多个 SSDB 字段
98
+ #
99
+ # 例如:
100
+ #
101
+ # notes = Note.where("<some where>").limit(15)
102
+ # SSDBAttr.load_attrs(notes, :public_title, :public_content)
103
+ #
104
+ # @param [Array] objects
105
+ # @param [Array] fields
106
+ #
107
+ # @return [ActiveRecord::Relation|Array]
108
+ #
109
+ def load_attrs(objects, *fields)
110
+ fields.map!(&:to_s)
111
+
112
+ keys = objects.flat_map do |object|
113
+ fields.map { |name| object.ssdb_attr_key(name) }
114
+ end
115
+ values = SSDBAttr.pool.with { |conn| conn.mget(keys) }
116
+ key_values = keys.zip(values).to_h
117
+
118
+ objects.each do |object|
119
+ fields.each do |name|
120
+ next unless object.class.ssdb_attr_names.include?(name.to_s)
121
+
122
+ value =
123
+ if (raw_value = key_values[object.ssdb_attr_key(name)]).present?
124
+ object.typecaster(raw_value, object.class.ssdb_attr_definition[name])
125
+ else
126
+ object.public_send("#{name}_default_value")
127
+ end
128
+
129
+ object.instance_variable_set("@#{name}", value)
130
+ end
131
+ end
132
+
133
+ objects
134
+ end
96
135
  end
97
136
  end
@@ -1,3 +1,3 @@
1
1
  module SSDBAttr
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4"
3
3
  end
@@ -69,6 +69,10 @@ module SSDB
69
69
  instance_variable_set("@#{name}", val)
70
70
  end
71
71
 
72
+ define_method("#{name}_default_value") do
73
+ typecaster(options[:default], type)
74
+ end
75
+
72
76
  define_method("#{name}_was") { attribute_was(name) }
73
77
 
74
78
  define_method("#{name}_change") { attribute_change(name) }
@@ -113,16 +117,15 @@ module SSDB
113
117
  end
114
118
  end
115
119
 
116
- private
117
-
118
120
  #
119
- # Return the ConnectionPool used by current Class.
121
+ # Return the SSDB key for a attribute
120
122
  #
123
+ # @param [String] name Attribute name.
121
124
  #
122
- # @return [ConnectionPool]
125
+ # @return [String]
123
126
  #
124
- def ssdb_attr_pool
125
- SSDBAttr.pool(self.class.ssdb_attr_pool_name)
127
+ def ssdb_attr_key(name)
128
+ "#{self.class.name.tableize}:#{ssdb_attr_id}:#{name}"
126
129
  end
127
130
 
128
131
  #
@@ -142,20 +145,20 @@ module SSDB
142
145
  end
143
146
  end
144
147
 
145
- def ssdb_attr_id
146
- send(self.class.ssdb_attr_id_field || :id)
147
- end
148
-
148
+ private
149
149
 
150
150
  #
151
- # Return the SSDB key for a attribute
151
+ # Return the ConnectionPool used by current Class.
152
152
  #
153
- # @param [String] name Attribute name.
154
153
  #
155
- # @return [String]
154
+ # @return [ConnectionPool]
156
155
  #
157
- def ssdb_attr_key(name)
158
- "#{self.class.name.tableize}:#{ssdb_attr_id}:#{name}"
156
+ def ssdb_attr_pool
157
+ SSDBAttr.pool(self.class.ssdb_attr_pool_name)
158
+ end
159
+
160
+ def ssdb_attr_id
161
+ send(self.class.ssdb_attr_id_field || :id)
159
162
  end
160
163
 
161
164
  #
@@ -6,6 +6,24 @@ require "ssdb-attr"
6
6
  ActiveRecord::Base.raise_in_transactional_callbacks = true if ActiveRecord::VERSION::STRING >= "4.2"
7
7
  ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
8
8
 
9
+ RSpec.configure do |config|
10
+ config.expect_with :rspec do |expectations|
11
+ expectations.syntax = :expect
12
+ end
13
+
14
+ config.before(:all) do
15
+ # Connect to test SSDB server
16
+ SSDBAttr.setup(:url => "redis://localhost:8888")
17
+
18
+ # Clean up SSDB
19
+ system('printf "7\nflushdb\n\n4\nping\n\n" | nc 127.0.0.1 8888 -i 1 > /dev/null')
20
+
21
+ ActiveRecord::Base.connection.tables.each do |table|
22
+ ActiveRecord::Base.connection.execute "DELETE FROM #{table}"
23
+ end
24
+ end
25
+ end
26
+
9
27
  # Setup tables for test
10
28
  tbls = [
11
29
  { "posts" => "updated_at DATETIME, saved_at DATETIME, changed_at DATETIME" },
@@ -18,3 +36,40 @@ tbls.each do |tbl|
18
36
  ActiveRecord::Base.connection.execute "CREATE TABLE #{tbl_name} (id INTEGER NOT NULL PRIMARY KEY, #{sql})"
19
37
  end
20
38
  end
39
+
40
+ # ActiveRecord definition
41
+ class Post < ActiveRecord::Base
42
+ include SSDB::Attr
43
+
44
+ ssdb_attr :name, :string
45
+ ssdb_attr :int_version, :integer
46
+ ssdb_attr :default_title, :string, default: "Untitled"
47
+ ssdb_attr :title, :string
48
+ ssdb_attr :content, :string
49
+ ssdb_attr :version, :integer, default: 1
50
+ ssdb_attr :default_version, :integer, :default => 100
51
+ ssdb_attr :field_with_validation, :string
52
+
53
+ validate :validate_field
54
+
55
+ def validate_field
56
+ if field_with_validation == "foobar"
57
+ errors.add(:field_with_validation, "foobar error")
58
+ end
59
+ end
60
+ end
61
+
62
+ class CustomIdField < ActiveRecord::Base
63
+ include SSDB::Attr
64
+
65
+ ssdb_attr_id :uuid
66
+ ssdb_attr :content, :string
67
+ end
68
+
69
+ class CustomPoolName < ActiveRecord::Base
70
+ include SSDB::Attr
71
+
72
+ ssdb_attr_pool :foo_pool
73
+
74
+ ssdb_attr :foo_id, :integer
75
+ end
@@ -1,5 +1,4 @@
1
- # require 'spec_helper'
2
- require "ssdb-attr"
1
+ require "spec_helper"
3
2
 
4
3
  describe SSDBAttr do
5
4
 
@@ -128,4 +127,64 @@ describe SSDBAttr do
128
127
  end
129
128
  end
130
129
  end
130
+
131
+ describe ".load_attrs" do
132
+ it "returns the values correctly" do
133
+ post1 = Post.create(:name => "lol", :version => 2)
134
+ post2 = Post.create(:name => "dota", :version => 3)
135
+
136
+ posts = Post.where(:id => [post1.id, post2.id])
137
+
138
+ posts.each do |post|
139
+ expect(post.instance_variable_get(:@name)).to be(nil)
140
+ expect(post.instance_variable_get(:@version)).to be(nil)
141
+ end
142
+
143
+ SSDBAttr.load_attrs(posts, :name, :version)
144
+
145
+ expect(posts[0].instance_variable_get(:@name)).to eq("lol")
146
+ expect(posts[0].instance_variable_get(:@version)).to eq(2)
147
+
148
+ expect(posts[1].instance_variable_get(:@name)).to eq("dota")
149
+ expect(posts[1].instance_variable_get(:@version)).to eq(3)
150
+ end
151
+
152
+ it "returns default value correctly if no value in ssdb" do
153
+ post1 = Post.create(:name => "lol")
154
+ post2 = Post.create(:name => "dota")
155
+
156
+ posts = Post.where(:id => [post1.id, post2.id])
157
+
158
+ posts.each do |post|
159
+ expect(post.instance_variable_get(:@name)).to be(nil)
160
+ expect(post.instance_variable_get(:@version)).to be(nil)
161
+ end
162
+
163
+ SSDBAttr.load_attrs(posts, :name, :version)
164
+
165
+ expect(posts[0].instance_variable_get(:@name)).to eq("lol")
166
+ expect(posts[0].instance_variable_get(:@version)).to eq(1)
167
+
168
+ expect(posts[1].instance_variable_get(:@name)).to eq("dota")
169
+ expect(posts[1].instance_variable_get(:@version)).to eq(1)
170
+ end
171
+
172
+ it "doesn't define instance variables for undefined ssdb atts" do
173
+ post1 = Post.create(:name => "lol")
174
+ post2 = Post.create(:name => "dota")
175
+
176
+ posts = Post.where(:id => [post1.id, post2.id])
177
+
178
+ posts.each do |post|
179
+ expect(post.instance_variable_get(:@name)).to be(nil)
180
+ expect(post.instance_variable_get(:@version)).to be(nil)
181
+ end
182
+
183
+ SSDBAttr.load_attrs(posts, :undefined_field)
184
+
185
+ posts.each do |post|
186
+ expect(post.instance_variable_defined?(:@undefined_field)).to be(false)
187
+ end
188
+ end
189
+ end
131
190
  end
@@ -1,55 +1,6 @@
1
1
  require "spec_helper"
2
2
 
3
- class Post < ActiveRecord::Base
4
- include SSDB::Attr
5
-
6
- ssdb_attr :name, :string
7
- ssdb_attr :int_version, :integer
8
- ssdb_attr :default_title, :string, default: "Untitled"
9
- ssdb_attr :title, :string
10
- ssdb_attr :content, :string
11
- ssdb_attr :version, :integer, default: 1
12
- ssdb_attr :default_version, :integer, :default => 100
13
- ssdb_attr :field_with_validation, :string
14
-
15
- validate :validate_field
16
-
17
- def validate_field
18
- if field_with_validation == "foobar"
19
- errors.add(:field_with_validation, "foobar error")
20
- end
21
- end
22
- end
23
-
24
- class CustomIdField < ActiveRecord::Base
25
- include SSDB::Attr
26
-
27
- ssdb_attr_id :uuid
28
- ssdb_attr :content, :string
29
- end
30
-
31
- class CustomPoolName < ActiveRecord::Base
32
- include SSDB::Attr
33
-
34
- ssdb_attr_pool :foo_pool
35
-
36
- ssdb_attr :foo_id, :integer
37
- end
38
-
39
3
  describe SSDB::Attr do
40
-
41
- before(:all) do
42
- # Connect to test SSDB server
43
- SSDBAttr.setup(:url => "redis://localhost:8888")
44
-
45
- # Clean up SSDB
46
- system('printf "7\nflushdb\n\n4\nping\n\n" | nc 127.0.0.1 8888 -i 1 > /dev/null')
47
-
48
- ActiveRecord::Base.connection.tables.each do |table|
49
- ActiveRecord::Base.connection.execute "DELETE FROM #{table}"
50
- end
51
- end
52
-
53
4
  context "Post" do
54
5
  let(:post) { Post.create(updated_at: 1.day.ago, saved_at: 1.day.ago, changed_at: 1.day.ago) }
55
6
  let(:redis) { Redis.new(:url => 'redis://localhost:8888') }
@@ -72,6 +23,7 @@ describe SSDB::Attr do
72
23
  it "should respond to methods" do
73
24
  expect(post.respond_to?(:name)).to be true
74
25
  expect(post.respond_to?(:name=)).to be true
26
+ expect(post.respond_to?(:name_default_value)).to be true
75
27
  expect(post.respond_to?(:name_was)).to be true
76
28
  expect(post.respond_to?(:name_change)).to be true
77
29
  expect(post.respond_to?(:name_changed?)).to be true
@@ -101,6 +53,16 @@ describe SSDB::Attr do
101
53
  end
102
54
  end
103
55
 
56
+ describe "#attirbute_default_value" do
57
+ it "returns correct default value" do
58
+ post.default_title = "changed"
59
+ post.default_version = 99
60
+
61
+ expect(post.default_title_default_value).to eq("Untitled")
62
+ expect(post.default_version_default_value).to eq(100)
63
+ end
64
+ end
65
+
104
66
  describe "#reload_ssdb_attrs" do
105
67
  it "should reload attribute values from SSDB" do
106
68
  post = Post.create(title: "foobar", version: 4)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ssdb-attr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Larry Zhao
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-29 00:00:00.000000000 Z
11
+ date: 2017-08-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis