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.
@@ -2,7 +2,8 @@ module Findable
2
2
  class Configuration
3
3
  VALID_OPTIONS = [
4
4
  :redis_options,
5
- :seed_file
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
 
@@ -1,10 +1,16 @@
1
1
  module Findable
2
2
  class FindableError < StandardError; end
3
- class RecordNotFound < FindableError; end
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
+
@@ -2,7 +2,7 @@ module Findable
2
2
  class Railtie < ::Rails::Railtie
3
3
  initializer "findable" do
4
4
  ActiveSupport.on_load(:active_record) do
5
- ::ActiveRecord::Base.send(:extend, Findable::Association)
5
+ require "findable/associations/active_record_ext"
6
6
  end
7
7
  end
8
8
 
data/lib/findable/seed.rb CHANGED
@@ -1,61 +1,57 @@
1
1
  module Findable
2
2
  class Seed
3
- attr_reader :full_path, :namespaced, :ext
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
- def initialize(path, seed_dir)
6
- @_seed_dir = seed_dir
7
- self.full_path = path
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=(path)
11
- @full_path = path
12
- _path = path.gsub(@_seed_dir, "")
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 base_name
18
- @_base ||= @namespaced.sub(@ext, "")
28
+ def basename
29
+ @_basename ||= @_full_path.basename(".*").to_s
19
30
  end
20
31
 
21
32
  def model
22
- base_name.split("/").reverse.map.with_index {|n,i|
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
- records = load_file.map {|data| model.new(data) }
40
- model.import records
39
+ model.query.import YAML.load_file(@_full_path).values
41
40
  end
42
41
  end
43
42
 
44
- class << self
45
- def target_files(seed_dir, tables = nil)
46
- Dir.glob(patterns(seed_dir)).map {|full_path|
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 patterns(seed_dir)
54
- %w(yml).map {|format|
55
- Rails.root.join("#{seed_dir}/**/*.#{format}").to_s
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
 
@@ -1,4 +1,4 @@
1
1
  module Findable
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
4
4
 
@@ -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
- # Seed file of Findable
6
- # config.seed_file = Rails.root.join("db", "findable_seeds.rb")
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(seed_dir, seed_files).each {|seed| seed.bootstrap! }
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 "simplecov"
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|
@@ -0,0 +1,2 @@
1
+ Redis.current.flushdb
2
+
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.3
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-01-14 00:00:00.000000000 Z
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: simplecov
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/association.rb
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/namespace.rb
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.2.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