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