findable 0.1.4 → 0.1.5

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: 33cc41223d03de05c7983ae227f66bb4ee36d833
4
- data.tar.gz: 2908c96f0a953f76a78d65bd9f12c8c0fb252c6a
3
+ metadata.gz: 0c5762db6fcb9200dd984f87ec167f1091ecfe26
4
+ data.tar.gz: 8c2386ee142b72c7bfd4814b45783f48a0a12367
5
5
  SHA512:
6
- metadata.gz: b1260e9d9d210ef7ebfc40401c4d85b4cc7315407b76b53fc36e7dc73b34af976449a40222c428c96c52f7c2ecb5bd5ff10ebed629024dcb64be38fe1cb820f3
7
- data.tar.gz: d1740da9cb2b9b14e2ed18b150814502d3c275c253cd2970d6db478a7d74944d25a3bc53a4c4b8cd8060843d046fcda5fea71655d80b0110bc6d77e29464b8af
6
+ metadata.gz: 107b796739e028571c553dee7aa04fb31d6ef6b374c38a1dd44c2225d7fbd735d124488a5c76d6b136007b729cb4808668c56a6ca4ef1fff81869d1782a9b2a2
7
+ data.tar.gz: f42800de1d903c60cb478b8c5981ddfebd27ec3d1542586f61f286bfb7d6ffbf6bbcd3fd459ba8793e8f385c1be56bda08b8e7c55823726058554667d7081695
data/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # Findable
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/findable.svg)](http://badge.fury.io/rb/findable)
4
- [![Build Status](https://travis-ci.org/i2bskn/findable.svg)](https://travis-ci.org/i2bskn/findable)
5
- [![Coverage Status](https://img.shields.io/coveralls/i2bskn/findable.svg)](https://coveralls.io/r/i2bskn/findable)
4
+ [![Build Status](https://travis-ci.org/i2bskn/findable.svg?branch=master)](https://travis-ci.org/i2bskn/findable)
5
+ [![Coverage Status](https://coveralls.io/repos/i2bskn/findable/badge.svg?branch=master)](https://coveralls.io/r/i2bskn/findable?branch=master)
6
6
  [![Code Climate](https://codeclimate.com/github/i2bskn/findable/badges/gpa.svg)](https://codeclimate.com/github/i2bskn/findable)
7
7
 
8
8
  Redis wrapper with API like ActiveRecord.
9
9
 
10
10
  ## Requirements
11
11
 
12
- - Redis
12
+ - Redis 2.8 or later
13
13
 
14
14
  ## Installation
15
15
 
@@ -64,7 +64,7 @@ end
64
64
  Execute seed script if you create seed files.
65
65
 
66
66
  ```
67
- $ rake findable:seeds
67
+ $ rake findable:seed
68
68
  ```
69
69
 
70
70
  Manipulate data with API like ActiveRecord.
@@ -72,13 +72,13 @@ Manipulate data with API like ActiveRecord.
72
72
  ```
73
73
  $ rails console
74
74
  pry(main)> Tag.find(1)
75
- => #<Tag:0x00000108068430 @_attributes={:id=>1, :name=>"Ruby"}>
75
+ => #<Tag id: 1, name: "Ruby">
76
76
  pry(main)> golang = Tag.create(name: "Go")
77
- => #<Tag:0x00000107ff6420 @_attributes={:name=>"Go", :id=>2}>
77
+ => #<Tag id: 2, name: "Go">
78
78
  pry(main)> Tag.all.each {|tag| p tag.name }
79
79
  "Ruby"
80
80
  "Go"
81
- => [#<Tag:0x00000107f49568 @_attributes={:id=>1, :name=>"Ruby"}>, #<Tag:0x00000107f492e8 @_attributes={:name=>"Go", :id=>2}>]
81
+ => [#<Tag id: 1, name: "Ruby">, #<Tag id: 2, name: "Go">]
82
82
  ```
83
83
 
84
84
  ## Associations
data/Rakefile CHANGED
@@ -7,8 +7,3 @@ desc "Run all specs"
7
7
  RSpec::Core::RakeTask.new(:spec) do |spec|
8
8
  spec.pattern = FileList['spec/**/*_spec.rb']
9
9
  end
10
-
11
- desc "Console with library"
12
- task :console do
13
- sh "pry -I lib -r bundler/setup -r findable"
14
- end
@@ -21,7 +21,6 @@ Gem::Specification.new do |spec|
21
21
  spec.add_dependency "activesupport"
22
22
  spec.add_dependency "activemodel"
23
23
  spec.add_dependency "redis"
24
- spec.add_dependency "oj"
25
24
 
26
25
  spec.add_development_dependency "bundler"
27
26
  spec.add_development_dependency "rake"
@@ -1,8 +1,9 @@
1
+ require "json"
2
+
1
3
  require "active_support"
2
4
  require "active_support/core_ext"
3
5
  require "active_model"
4
6
  require "redis"
5
- require "oj"
6
7
 
7
8
  require "findable/version"
8
9
  require "findable/errors"
@@ -5,7 +5,6 @@ module Findable
5
5
  class Base
6
6
  include ActiveModel::Model
7
7
  include ActiveModel::AttributeMethods
8
-
9
8
  include Associations
10
9
  include Inspection
11
10
 
@@ -18,13 +17,15 @@ module Findable
18
17
  def define_field(attr)
19
18
  unless public_method_defined?(attr)
20
19
  define_attribute_methods attr
21
- define_method(attr) { attributes[attr.to_sym] }
20
+ define_method(attr) { attributes[attr] }
22
21
  column_names << attr.to_sym
23
22
  end
24
23
  end
25
24
 
26
25
  ## ActiveRecord like APIs
27
26
 
27
+ delegate :all, to: :query
28
+
28
29
  def primary_key
29
30
  "id"
30
31
  end
@@ -33,13 +34,9 @@ module Findable
33
34
  @_column_names ||= [:id]
34
35
  end
35
36
 
36
- def all
37
- data.map {|val| new(val) }
38
- end
39
-
40
37
  def find(ids)
41
- if values = find_by_ids(ids).compact.presence
42
- ids.is_a?(Array) ? values.map {|val| new(val) } : new(values.first)
38
+ if records = find_by_ids(ids).presence
39
+ ids.is_a?(Array) ? records : records.first
43
40
  else
44
41
  raise RecordNotFound.new(self, id: ids)
45
42
  end
@@ -49,25 +46,22 @@ module Findable
49
46
  if conditions.is_a?(Hash)
50
47
  conditions.symbolize_keys!
51
48
  if id = conditions.delete(:id)
52
- values = find_by_ids(id).compact
49
+ records = find_by_ids(id)
53
50
  case
54
- when values.empty? then nil
55
- when conditions.empty? then new(values.first)
51
+ when records.empty? then nil
52
+ when conditions.empty? then records.first
56
53
  else
57
- value = values.detect {|val|
58
- record = new(val)
54
+ records.detect {|record|
59
55
  conditions.all? {|k, v| record.public_send(k) == v }
60
56
  }
61
- value ? new(value) : nil
62
57
  end
63
58
  else
64
- all.detect {|r|
65
- conditions.all? {|k, v| r.public_send(k) == v }
59
+ all.detect {|record|
60
+ conditions.all? {|k, v| record.public_send(k) == v }
66
61
  }
67
62
  end
68
63
  else
69
- values = find_by_ids(conditions).compact
70
- values.empty? ? nil : new(values.first)
64
+ find_by_ids(conditions).first
71
65
  end
72
66
  end
73
67
 
@@ -76,19 +70,19 @@ module Findable
76
70
  end
77
71
 
78
72
  def where(conditions)
73
+ conditions.symbolize_keys!
79
74
  if id = conditions.delete(:id)
80
- values = find_by_ids(id).compact
75
+ records = find_by_ids(id)
81
76
  if conditions.empty?
82
- values.map {|val| new(val) }
77
+ records
83
78
  else
84
- values.map {|val|
85
- record = new(val)
86
- conditions.all? {|k, v| record.public_send(k) == v } ? record : nil
87
- }.compact
79
+ records.select {|record|
80
+ conditions.all? {|k, v| record.public_send(k) == v }
81
+ }
88
82
  end
89
83
  else
90
- all.select {|r|
91
- conditions.all? {|k, v| r.public_send(k) == v }
84
+ all.select {|record|
85
+ conditions.all? {|k, v| record.public_send(k) == v }
92
86
  }
93
87
  end
94
88
  end
@@ -102,14 +96,13 @@ module Findable
102
96
 
103
97
  [:first, :last].each do |m|
104
98
  define_method(m) do
105
- value = self.data.public_send(m)
106
- value ? new(value) : nil
99
+ self.all.public_send(m)
107
100
  end
108
101
  end
109
102
 
110
103
  ## Query APIs
111
104
 
112
- delegate :find_by_ids, :data, to: :query
105
+ delegate :find_by_ids, :insert, to: :query
113
106
  delegate :count, :ids, :delete_all, to: :query
114
107
  alias_method :destroy_all, :delete_all
115
108
 
@@ -121,10 +114,6 @@ module Findable
121
114
  end
122
115
  end
123
116
 
124
- def insert(obj)
125
- query.insert(obj.attributes)
126
- end
127
-
128
117
  def delete(obj)
129
118
  if _id = id_from(obj)
130
119
  query.delete(_id)
@@ -142,8 +131,7 @@ module Findable
142
131
  end
143
132
 
144
133
  def initialize(params = {})
145
- params = Oj.load(params) if params.is_a?(String)
146
- params.symbolize_keys!
134
+ params = params.with_indifferent_access
147
135
  params.keys.each {|attr| self.class.define_field(attr) }
148
136
  @_attributes = params
149
137
  end
@@ -169,8 +157,7 @@ module Findable
169
157
  end
170
158
 
171
159
  def save
172
- @_attributes = self.class.insert(self)
173
- self
160
+ self.class.insert(self)
174
161
  end
175
162
  alias_method :save!, :save
176
163
 
@@ -180,16 +167,15 @@ module Findable
180
167
  alias_method :destroy, :delete
181
168
 
182
169
  def attributes
183
- @_attributes ||= {}
170
+ @_attributes ||= ActiveSupport::HashWithIndifferentAccess.new
184
171
  end
185
172
 
186
- private
187
- def attribute=(attr, value)
188
- attributes[attr.to_sym] = value
189
- end
173
+ def attribute=(attr, value)
174
+ attributes[attr.to_sym] = value
175
+ end
190
176
 
191
- def attribute?(attr)
192
- attributes[attr.to_sym].present?
193
- end
177
+ def attribute?(attr)
178
+ attributes[attr.to_sym].present?
179
+ end
194
180
  end
195
181
  end
@@ -2,6 +2,7 @@ module Findable
2
2
  class Configuration
3
3
  VALID_OPTIONS = [
4
4
  :redis_options,
5
+ :serializer,
5
6
  :seed_dir,
6
7
  :seed_file,
7
8
  ].freeze
@@ -27,6 +28,7 @@ module Findable
27
28
 
28
29
  def reset
29
30
  self.redis_options = nil
31
+ self.serializer = JSON
30
32
  self.seed_dir = defined?(Rails) ? Rails.root.join("db", "findable_seeds") : nil
31
33
  self.seed_file = defined?(Rails) ? Rails.root.join("db", "findable_seeds.rb") : nil
32
34
  end
@@ -4,7 +4,12 @@ module Findable
4
4
 
5
5
  module ClassMethods
6
6
  def inspect
7
- "#{self}(#{column_names.map(&:inspect).join(', ')})"
7
+ case
8
+ when self == Findable::Base
9
+ super
10
+ else
11
+ "#{self}(#{column_names.map(&:inspect).join(', ')})"
12
+ end
8
13
  end
9
14
  end
10
15
 
@@ -1,14 +1,22 @@
1
1
  require "findable/query/connection"
2
2
  require "findable/query/namespace"
3
3
  require "findable/query/lock"
4
+ require "findable/query/serializer"
4
5
 
5
6
  module Findable
6
7
  class Query
7
8
  include Connection
8
9
  include Namespace
9
10
 
10
- def data
11
- redis.hvals(data_key)
11
+ attr_reader :model
12
+
13
+ def initialize(model, serializer = nil)
14
+ @model = model
15
+ @serializer = serializer || Serializer.new
16
+ end
17
+
18
+ def all
19
+ @serializer.deserialize(redis.hvals(data_key), model)
12
20
  end
13
21
 
14
22
  def ids
@@ -20,19 +28,23 @@ module Findable
20
28
  end
21
29
 
22
30
  def find_by_ids(ids)
23
- redis.hmget(data_key, *Array(ids))
31
+ @serializer.deserialize(redis.hmget(data_key, *Array(ids)), model)
24
32
  end
25
33
 
26
34
  def exists?(id)
27
35
  redis.hexists(data_key, id)
28
36
  end
29
37
 
30
- def insert(hash)
38
+ def insert(object)
31
39
  lock do
32
- hash[:id] = auto_incremented_id(hash[:id])
33
- redis.hset(data_key, hash[:id], Oj.dump(hash))
40
+ object.id = auto_incremented_id(object.id)
41
+ redis.hset(
42
+ data_key,
43
+ object.id,
44
+ @serializer.serialize(object.attributes)
45
+ )
34
46
  end
35
- hash
47
+ object
36
48
  end
37
49
 
38
50
  def import(hashes)
@@ -40,14 +52,14 @@ module Findable
40
52
  auto_incremented = hashes.each_with_object([]) do |hash, obj|
41
53
  hash["id"] = auto_incremented_id(hash["id"])
42
54
  obj << hash["id"]
43
- obj << Oj.dump(hash)
55
+ obj << @serializer.serialize(hash)
44
56
  end
45
57
  redis.hmset(data_key, *auto_incremented)
46
58
  end
47
59
  end
48
60
 
49
61
  def delete(id)
50
- redis.hdel data_key, id
62
+ redis.hdel(data_key, id)
51
63
  end
52
64
 
53
65
  def delete_all
@@ -5,12 +5,8 @@ module Findable
5
5
  KEY_NAMES = %i(info data lock index).freeze
6
6
  AUTO_INCREMENT_KEY = :auto_increment
7
7
 
8
- def initialize(model)
9
- @_model = model
10
- end
11
-
12
- KEY_NAMES.each do |key|
13
- define_method([key, "key"].join("_")) { namespaces[key] }
8
+ KEY_NAMES.each do |name|
9
+ define_method([name, "key"].join("_")) { namespaces[name] }
14
10
  end
15
11
 
16
12
  def thread_key
@@ -19,7 +15,7 @@ module Findable
19
15
 
20
16
  private
21
17
  def basename
22
- @_model.model_name.plural
18
+ model.model_name.plural
23
19
  end
24
20
 
25
21
  # @return [Hash] namespaces
@@ -0,0 +1,26 @@
1
+ module Findable
2
+ class Query
3
+ class Serializer
4
+ def initialize(serializer = nil)
5
+ @serializer = serializer || Findable.config.serializer
6
+ end
7
+
8
+ def serialize(object)
9
+ @serializer.dump(object)
10
+ end
11
+
12
+ # @params raw_data [String] Serialized string
13
+ # @params raw_data [Array<String>] Array of serialized string
14
+ # @return [ActiveSupport::HashWithIndifferentAccess]
15
+ # @return [Array<ActiveSupport::HashWithIndifferentAccess>]
16
+ def deserialize(raw_data, klass = nil)
17
+ objects = Array(raw_data).compact.map {|data|
18
+ object = @serializer.load(data)
19
+ object = object.with_indifferent_access if object.is_a?(Hash)
20
+ klass ? klass.new(object) : object
21
+ }
22
+ raw_data.is_a?(String) ? objects.first : objects
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,3 +1,3 @@
1
1
  module Findable
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
3
3
  end
@@ -1,7 +1,13 @@
1
1
  Findable.configure do |config|
2
- # Redis connection setting. (default: `Redis.current`)
2
+ # Redis connection setting. Default is `Redis.current`.
3
3
  # config.redis_options = {host: "localhost", port: 6379, db: 2}
4
4
 
5
+ # Serializer setting. Default is JSON.
6
+ # It can be specify an object with the following methods.
7
+ # * dump - To string from an object.
8
+ # * load - To object from a string.
9
+ # config.serializer = Oj
10
+
5
11
  # Directory of stored seed files.
6
12
  config.seed_dir = Rails.root.join("db", "findable_seeds")
7
13
 
@@ -1,6 +1,6 @@
1
1
  namespace :findable do
2
2
  desc "Load seed file of findable."
3
- task :seeds => :environment do
3
+ task :seed => :environment do
4
4
  if Findable.config.seed_file
5
5
  load Findable.config.seed_file
6
6
  end
@@ -4,7 +4,7 @@ describe Findable::Query::Namespace do
4
4
  include_context "TemporaryModel"
5
5
 
6
6
  before do
7
- QueryEx = Class.new
7
+ QueryEx = Struct.new(:model)
8
8
  QueryEx.include Findable::Query::Namespace
9
9
  end
10
10
 
@@ -22,10 +22,6 @@ describe Findable::Query::Namespace do
22
22
  }
23
23
  end
24
24
 
25
- describe "#initialize" do
26
- it { expect(query.instance_eval { @_model }).to eq(model) }
27
- end
28
-
29
25
  describe "#thread_key" do
30
26
  it { expect(query.thread_key).to be_kind_of(String) }
31
27
  it { expect(query.thread_key).to start_with(namespace::PREFIX) }
@@ -7,8 +7,8 @@ describe Findable::Query do
7
7
  let(:auto_increment_key) { Findable::Query::Namespace::AUTO_INCREMENT_KEY }
8
8
 
9
9
  describe "#data" do
10
- it { expect(read_model.query.data).to be_kind_of(Array) }
11
- it { expect(read_model.query.data.size).to eq(1) }
10
+ it { expect(read_model.query.all).to be_kind_of(Array) }
11
+ it { expect(read_model.query.all.size).to eq(1) }
12
12
  end
13
13
 
14
14
  describe "#ids" do
@@ -21,12 +21,11 @@ describe Findable::Query do
21
21
  end
22
22
 
23
23
  describe "#find_by_ids" do
24
- let(:raw_value) { read_model.query.find_by_ids(1) }
25
- let(:loaded_value) { Oj.load(raw_value.first) }
24
+ let(:data) { read_model.query.find_by_ids(1) }
26
25
 
27
- it { expect(raw_value).to be_kind_of(Array) }
28
- it { expect(raw_value.first).to be_kind_of(String) }
29
- it { expect(loaded_value[:id]).to eq(1) }
26
+ it { expect(data).to be_kind_of(Array) }
27
+ it { expect(data.first).to be_kind_of(read_model) }
28
+ it { expect(data.first.id).to eq(1) }
30
29
  end
31
30
 
32
31
  describe "#exists?" do
@@ -35,12 +34,12 @@ describe Findable::Query do
35
34
  end
36
35
 
37
36
  describe "#insert" do
38
- it { expect(model.query.insert(name: name)).to be_kind_of(Hash) }
39
- it { expect(model.query.insert(name: name)[:id]).not_to be_nil }
40
- it { expect(model.query.insert(name: name)[:name]).to eq(name) }
37
+ it { expect(model.create(name: name)).to be_kind_of(model) }
38
+ it { expect(model.create(name: name).id).not_to be_nil }
39
+ it { expect(model.create(name: name).name).to eq(name) }
41
40
  it {
42
41
  expect {
43
- model.query.insert(name: name)
42
+ model.create(name: name)
44
43
  }.to change { model.query.count }.by(1)
45
44
  }
46
45
  end
@@ -49,18 +48,18 @@ describe Findable::Query do
49
48
  end
50
49
 
51
50
  describe "#delete" do
52
- let!(:params) { model.query.insert(name: name) }
51
+ let!(:persisted_object) { model.create(name: name) }
53
52
 
54
53
  it {
55
54
  expect {
56
- model.query.delete(params[:id])
55
+ model.query.delete(persisted_object.id)
57
56
  }.to change { model.query.count }.by(-1)
58
57
  }
59
58
  end
60
59
 
61
60
  describe "#delete_all" do
62
61
  before {
63
- model.query.insert(name: name)
62
+ model.create(name: name)
64
63
  model.query.delete_all
65
64
  }
66
65
 
@@ -10,7 +10,6 @@ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
10
10
  SimpleCov.start do
11
11
  add_filter "spec"
12
12
  add_filter ".bundle"
13
- add_filter "example"
14
13
  end
15
14
 
16
15
  require "bundler/setup"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: findable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - i2bskn
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-04 00:00:00.000000000 Z
11
+ date: 2015-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: oj
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: bundler
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -206,6 +192,7 @@ files:
206
192
  - lib/findable/query/connection.rb
207
193
  - lib/findable/query/lock.rb
208
194
  - lib/findable/query/namespace.rb
195
+ - lib/findable/query/serializer.rb
209
196
  - lib/findable/railtie.rb
210
197
  - lib/findable/seed.rb
211
198
  - lib/findable/version.rb