findable 0.0.3 → 0.1.0
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/.travis.yml +4 -8
- data/Gemfile +1 -1
- data/README.md +66 -14
- data/Rakefile +6 -1
- data/findable.gemspec +3 -2
- data/lib/findable.rb +2 -3
- data/lib/findable/associations.rb +52 -0
- data/lib/findable/associations/active_record_ext.rb +87 -0
- data/lib/findable/associations/utils.rb +25 -0
- data/lib/findable/base.rb +140 -80
- data/lib/findable/configuration.rb +3 -1
- data/lib/findable/errors.rb +8 -2
- data/lib/findable/query.rb +91 -0
- data/lib/findable/query/connection.rb +26 -0
- data/lib/findable/query/namespace.rb +34 -0
- data/lib/findable/railtie.rb +1 -1
- data/lib/findable/seed.rb +34 -38
- data/lib/findable/version.rb +1 -1
- data/lib/generators/findable/install_generator.rb +5 -0
- data/lib/generators/findable/templates/findable.rb +5 -2
- data/lib/generators/findable/templates/seeds.rb +1 -4
- data/spec/spec_helper.rb +1 -13
- data/spec/support/initialize_redis.rb +2 -0
- metadata +13 -10
- data/lib/findable/association.rb +0 -71
- data/lib/findable/connection.rb +0 -25
- data/lib/findable/namespace.rb +0 -23
- data/lib/findable/recordable.rb +0 -93
- data/lib/findable/serializer.rb +0 -12
@@ -2,7 +2,8 @@ module Findable
|
|
2
2
|
class Configuration
|
3
3
|
VALID_OPTIONS = [
|
4
4
|
:redis_options,
|
5
|
-
:
|
5
|
+
:seed_dir,
|
6
|
+
:seed_file,
|
6
7
|
].freeze
|
7
8
|
|
8
9
|
attr_accessor *VALID_OPTIONS
|
@@ -26,6 +27,7 @@ module Findable
|
|
26
27
|
|
27
28
|
def reset
|
28
29
|
self.redis_options = nil
|
30
|
+
self.seed_dir = defined?(Rails) ? Rails.root.join("db", "findable_seeds") : nil
|
29
31
|
self.seed_file = defined?(Rails) ? Rails.root.join("db", "findable_seeds.rb") : nil
|
30
32
|
end
|
31
33
|
|
data/lib/findable/errors.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
module Findable
|
2
2
|
class FindableError < StandardError; end
|
3
|
-
|
3
|
+
|
4
|
+
class RecordNotFound < FindableError
|
5
|
+
def initialize(model, params)
|
6
|
+
params.symbolize_keys! if params.is_a?(Hash)
|
7
|
+
super("Couldn't find #{model.model_name.name} with #{params.inspect}")
|
8
|
+
end
|
9
|
+
end
|
4
10
|
|
5
11
|
class ModelNotFound < FindableError
|
6
12
|
def initialize(model_name)
|
7
|
-
super("#{model_name} not found
|
13
|
+
super("#{model_name} not found.")
|
8
14
|
end
|
9
15
|
end
|
10
16
|
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require "findable/query/connection"
|
2
|
+
require "findable/query/namespace"
|
3
|
+
|
4
|
+
module Findable
|
5
|
+
class Query
|
6
|
+
include Connection
|
7
|
+
include Namespace
|
8
|
+
|
9
|
+
def data
|
10
|
+
redis.hvals(data_key)
|
11
|
+
end
|
12
|
+
|
13
|
+
def ids
|
14
|
+
redis.hkeys(data_key).map(&:to_i)
|
15
|
+
end
|
16
|
+
|
17
|
+
def count
|
18
|
+
redis.hlen(data_key)
|
19
|
+
end
|
20
|
+
|
21
|
+
def find_by_ids(ids)
|
22
|
+
redis.hmget(data_key, *Array(ids))
|
23
|
+
end
|
24
|
+
|
25
|
+
def exists?(id)
|
26
|
+
redis.hexists(data_key, id)
|
27
|
+
end
|
28
|
+
|
29
|
+
def insert(hash)
|
30
|
+
transaction do
|
31
|
+
hash[:id] = auto_incremented_id(hash[:id])
|
32
|
+
redis.hset(data_key, hash[:id], Oj.dump(hash))
|
33
|
+
end
|
34
|
+
hash
|
35
|
+
end
|
36
|
+
|
37
|
+
def import(hashes)
|
38
|
+
transaction do
|
39
|
+
auto_incremented = hashes.each_with_object([]) do |hash, obj|
|
40
|
+
hash["id"] = auto_incremented_id(hash["id"])
|
41
|
+
obj << hash["id"]
|
42
|
+
obj << Oj.dump(hash)
|
43
|
+
end
|
44
|
+
redis.hmset(data_key, *auto_incremented)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def delete(id)
|
49
|
+
redis.hdel data_key, id
|
50
|
+
end
|
51
|
+
|
52
|
+
def delete_all
|
53
|
+
redis.multi do
|
54
|
+
[data_key, info_key].each {|key| redis.del(key) }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def transaction
|
59
|
+
raise ArgumentError, "Require block" unless block_given?
|
60
|
+
if Thread.current[thread_key]
|
61
|
+
yield
|
62
|
+
else
|
63
|
+
begin
|
64
|
+
Thread.current[thread_key] = true
|
65
|
+
Redis::Lock.new(lock_key).lock do
|
66
|
+
yield
|
67
|
+
end
|
68
|
+
rescue Redis::Lock::LockTimeout
|
69
|
+
raise
|
70
|
+
ensure
|
71
|
+
Thread.current[thread_key] = nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
def auto_incremented_id(id)
|
78
|
+
if id.present?
|
79
|
+
current = redis.hget(info_key, AUTO_INCREMENT_KEY).to_i
|
80
|
+
id = id.to_i
|
81
|
+
if id > current
|
82
|
+
redis.hset(info_key, AUTO_INCREMENT_KEY, id)
|
83
|
+
end
|
84
|
+
id
|
85
|
+
else
|
86
|
+
redis.hincrby(info_key, AUTO_INCREMENT_KEY, 1)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Findable
|
2
|
+
class Query
|
3
|
+
module Connection
|
4
|
+
# Returns current connection or generate connection.
|
5
|
+
# @return [Redis] Redis connection
|
6
|
+
def redis
|
7
|
+
@_redis ||= generate_redis_connection!
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
# Generate connection with redis options or default connection.
|
12
|
+
# @return [Redis] Redis connection
|
13
|
+
def generate_redis_connection!
|
14
|
+
redis_options ? Redis.new(*redis_options) : Redis.current
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns redis options from configuration.
|
18
|
+
# @return [Hash] Redis options
|
19
|
+
# @return [nil] No Redis options
|
20
|
+
def redis_options
|
21
|
+
Findable.config.redis_options.presence
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Findable
|
2
|
+
class Query
|
3
|
+
module Namespace
|
4
|
+
PREFIX = "findable".freeze
|
5
|
+
KEY_NAMES = %i(info data lock index).freeze
|
6
|
+
AUTO_INCREMENT_KEY = :auto_increment
|
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] }
|
14
|
+
end
|
15
|
+
|
16
|
+
def thread_key
|
17
|
+
[PREFIX, basename].join("_")
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def basename
|
22
|
+
@_model.model_name.plural
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Hash] namespaces
|
26
|
+
def namespaces
|
27
|
+
@_namespaces ||= KEY_NAMES.each_with_object({}) {|key, obj|
|
28
|
+
obj[key] = [PREFIX, basename, key].join(":")
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
data/lib/findable/railtie.rb
CHANGED
data/lib/findable/seed.rb
CHANGED
@@ -1,61 +1,57 @@
|
|
1
1
|
module Findable
|
2
2
|
class Seed
|
3
|
-
|
3
|
+
class << self
|
4
|
+
def target_files(seed_dir: nil, seed_files: nil)
|
5
|
+
target_dir = pathname(seed_dir) || Findable.config.seed_dir
|
6
|
+
raise ArgumentError unless target_dir
|
7
|
+
Pathname.glob(target_dir.join("**", "*")).map {|full_path|
|
8
|
+
new(full_path, target_dir)
|
9
|
+
}.select {|seed|
|
10
|
+
seed_files.present? ? seed_files.include?(seed.basename) : true
|
11
|
+
}
|
12
|
+
end
|
4
13
|
|
5
|
-
|
6
|
-
|
7
|
-
|
14
|
+
def pathname(path)
|
15
|
+
case path
|
16
|
+
when Pathname then path
|
17
|
+
when String then Pathname.new(path)
|
18
|
+
else nil
|
19
|
+
end
|
20
|
+
end
|
8
21
|
end
|
9
22
|
|
10
|
-
def full_path
|
11
|
-
@
|
12
|
-
|
13
|
-
@namespaced = /^\// =~ _path ? _path.from(1) : _path
|
14
|
-
@ext = @namespaced[/^.*(?<ext>\.[^\.]+)$/, :ext] || (raise ArgumentError)
|
23
|
+
def initialize(full_path, seed_dir)
|
24
|
+
@_full_path = full_path
|
25
|
+
@_seed_dir = seed_dir
|
15
26
|
end
|
16
27
|
|
17
|
-
def
|
18
|
-
@
|
28
|
+
def basename
|
29
|
+
@_basename ||= @_full_path.basename(".*").to_s
|
19
30
|
end
|
20
31
|
|
21
32
|
def model
|
22
|
-
|
23
|
-
i.zero? ? n.singularize : n
|
24
|
-
}.reverse.map(&:camelize).join("::").constantize
|
25
|
-
end
|
26
|
-
|
27
|
-
def load_file
|
28
|
-
case @ext
|
29
|
-
when ".yml"
|
30
|
-
YAML.load_file(@full_path).values
|
31
|
-
else
|
32
|
-
raise UnexpectedFormat
|
33
|
-
end
|
33
|
+
@_model ||= from_seed_dir(without_ext(@_full_path)).to_s.classify.constantize
|
34
34
|
end
|
35
35
|
|
36
36
|
def bootstrap!
|
37
|
-
model.transaction do
|
37
|
+
model.query.transaction do
|
38
38
|
model.delete_all
|
39
|
-
|
40
|
-
model.import records
|
39
|
+
model.query.import YAML.load_file(@_full_path).values
|
41
40
|
end
|
42
41
|
end
|
43
42
|
|
44
|
-
|
45
|
-
def
|
46
|
-
|
47
|
-
Seed.new(full_path, seed_dir)
|
48
|
-
}.select {|seed|
|
49
|
-
tables ? tables.include?(seed.base_name) : true
|
50
|
-
}
|
43
|
+
private
|
44
|
+
def pathname(path)
|
45
|
+
self.class.pathname(path)
|
51
46
|
end
|
52
47
|
|
53
|
-
def
|
54
|
-
|
55
|
-
|
56
|
-
|
48
|
+
def without_ext(path)
|
49
|
+
pathname(path).dirname.join(pathname(path).basename(".*"))
|
50
|
+
end
|
51
|
+
|
52
|
+
def from_seed_dir(path)
|
53
|
+
pathname(path).relative_path_from(@_seed_dir)
|
57
54
|
end
|
58
|
-
end
|
59
55
|
end
|
60
56
|
end
|
61
57
|
|
data/lib/findable/version.rb
CHANGED
@@ -3,6 +3,11 @@ module Findable
|
|
3
3
|
class InstallGenerator < ::Rails::Generators::Base
|
4
4
|
source_root File.expand_path(File.join(File.dirname(__FILE__), "templates"))
|
5
5
|
|
6
|
+
desc "Create seed_dir of Findable."
|
7
|
+
def create_seed_dir
|
8
|
+
create_file File.join("db", "findable_seeds", ".keep")
|
9
|
+
end
|
10
|
+
|
6
11
|
desc "Install Findable files"
|
7
12
|
def install_findable_files
|
8
13
|
template "seeds.rb", "db/findable_seeds.rb"
|
@@ -2,7 +2,10 @@ Findable.configure do |config|
|
|
2
2
|
# Redis connection setting. (default: `Redis.current`)
|
3
3
|
# config.redis_options = {host: "localhost", port: 6379, db: 2}
|
4
4
|
|
5
|
-
#
|
6
|
-
|
5
|
+
# Directory of stored seed files.
|
6
|
+
config.seed_dir = Rails.root.join("db", "findable_seeds")
|
7
|
+
|
8
|
+
# Seed file of Findable.
|
9
|
+
config.seed_file = Rails.root.join("db", "findable_seeds.rb")
|
7
10
|
end
|
8
11
|
|
@@ -3,9 +3,6 @@
|
|
3
3
|
# Require seed support module
|
4
4
|
require "findable/seed"
|
5
5
|
|
6
|
-
# Path to the reading of the seed.
|
7
|
-
seed_dir = File.expand_path("../findable_seeds", __FILE__)
|
8
|
-
|
9
6
|
# Target seed files.
|
10
7
|
# Run all in the case of `nil`.
|
11
8
|
# Example of if you want to run some only.
|
@@ -13,5 +10,5 @@ seed_dir = File.expand_path("../findable_seeds", __FILE__)
|
|
13
10
|
seed_files = nil
|
14
11
|
|
15
12
|
# Execute
|
16
|
-
Findable::Seed.target_files(
|
13
|
+
Findable::Seed.target_files(seed_files: seed_files).each {|seed| seed.bootstrap! }
|
17
14
|
|
data/spec/spec_helper.rb
CHANGED
@@ -1,19 +1,7 @@
|
|
1
|
-
require "
|
1
|
+
require "findable"
|
2
2
|
require "coveralls"
|
3
3
|
Coveralls.wear!
|
4
4
|
|
5
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
6
|
-
SimpleCov::Formatter::HTMLFormatter,
|
7
|
-
Coveralls::SimpleCov::Formatter
|
8
|
-
]
|
9
|
-
|
10
|
-
SimpleCov.start do
|
11
|
-
add_filter "spec"
|
12
|
-
add_filter ".bundle"
|
13
|
-
end
|
14
|
-
|
15
|
-
require "findable"
|
16
|
-
|
17
5
|
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
18
6
|
|
19
7
|
RSpec.configure do |config|
|
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.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- i2bskn
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: redis
|
42
|
+
name: redis-objects
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: pry
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - ">="
|
@@ -152,16 +152,17 @@ files:
|
|
152
152
|
- Rakefile
|
153
153
|
- findable.gemspec
|
154
154
|
- lib/findable.rb
|
155
|
-
- lib/findable/
|
155
|
+
- lib/findable/associations.rb
|
156
|
+
- lib/findable/associations/active_record_ext.rb
|
157
|
+
- lib/findable/associations/utils.rb
|
156
158
|
- lib/findable/base.rb
|
157
159
|
- lib/findable/configuration.rb
|
158
|
-
- lib/findable/connection.rb
|
159
160
|
- lib/findable/errors.rb
|
160
|
-
- lib/findable/
|
161
|
+
- lib/findable/query.rb
|
162
|
+
- lib/findable/query/connection.rb
|
163
|
+
- lib/findable/query/namespace.rb
|
161
164
|
- lib/findable/railtie.rb
|
162
|
-
- lib/findable/recordable.rb
|
163
165
|
- lib/findable/seed.rb
|
164
|
-
- lib/findable/serializer.rb
|
165
166
|
- lib/findable/version.rb
|
166
167
|
- lib/generators/findable/install_generator.rb
|
167
168
|
- lib/generators/findable/templates/findable.rb
|
@@ -172,6 +173,7 @@ files:
|
|
172
173
|
- spec/findable/configuration_spec.rb
|
173
174
|
- spec/spec_helper.rb
|
174
175
|
- spec/support/.keep
|
176
|
+
- spec/support/initialize_redis.rb
|
175
177
|
homepage: https://github.com/i2bskn/findable
|
176
178
|
licenses:
|
177
179
|
- MIT
|
@@ -192,7 +194,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
192
194
|
version: '0'
|
193
195
|
requirements: []
|
194
196
|
rubyforge_project:
|
195
|
-
rubygems_version: 2.
|
197
|
+
rubygems_version: 2.4.5
|
196
198
|
signing_key:
|
197
199
|
specification_version: 4
|
198
200
|
summary: Redis wrapper with API like ActiveRecord.
|
@@ -202,3 +204,4 @@ test_files:
|
|
202
204
|
- spec/findable/configuration_spec.rb
|
203
205
|
- spec/spec_helper.rb
|
204
206
|
- spec/support/.keep
|
207
|
+
- spec/support/initialize_redis.rb
|