looksist 0.0.1 → 0.0.2

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: 71664ddcb9ae9f2c46b91072a8483ccc450b5570
4
- data.tar.gz: 5ccb029a61016e3885c2b4b728c8e6d0b2a5a781
3
+ metadata.gz: 453912d57be9e4fc38f6616ffdce38e38f0385bb
4
+ data.tar.gz: 8f43edb7bf0cfd70addeabfc8fd999045d253599
5
5
  SHA512:
6
- metadata.gz: 2a926878fba12379bbbdddef54c6547e816338d5105cb03e3c64f75ce69e4a29ac503ebb8dfa8ecf8dd988b937cd3a8ac75ceb83f162340056d7464f163f0269
7
- data.tar.gz: 113af2b37ef8237d31d491a9f898144f6adb5ce1d4dd8b52acbef52d0c4dd7ece390e43d17747513d2a305a6386cf5be36bcfaa4137cf2ad6bfd9f85a595ac26
6
+ metadata.gz: 6b7044cc4641fa67c4842a4c0a534a9182a6a3518764927aec3087041fbbdc8916597af8b98b018e480f2ef01daf07211bbe34e974c8affaf7e850ea22377d10
7
+ data.tar.gz: fb977003fff907b27036af080f3a870b0b5a798f6ca668a63fa75b3441251bdbb9d2d93d4488543d0786b8ea351e324cd27776b8a114c0e66b4560fc08bcec60
data/README.md CHANGED
@@ -1,14 +1,16 @@
1
- # Herdis
1
+ # Looksist
2
2
 
3
3
  [![Build Status](https://travis-ci.org/jpsimonroy/herdis.png?branch=master)](https://travis-ci.org/jpsimonroy/herdis)
4
4
 
5
- TODO: Write a gem description
5
+ looksist (adj) - forming positive prejudices based on appearances
6
+
7
+ Use this gem when you have to lookup attributes from a key-value store based on another attribute as key. This supports redis out-of-the-box and it's blazing fast!
6
8
 
7
9
  ## Installation
8
10
 
9
11
  Add this line to your application's Gemfile:
10
12
 
11
- gem 'herdis'
13
+ gem 'looksist'
12
14
 
13
15
  And then execute:
14
16
 
@@ -16,16 +18,47 @@ And then execute:
16
18
 
17
19
  Or install it yourself as:
18
20
 
19
- $ gem install herdis
21
+ $ gem install looksist
20
22
 
21
23
  ## Usage
22
24
 
23
- TODO: Write usage instructions here
25
+ * Add an initializer to configure looksist
26
+
27
+ ``` ruby
28
+ Looksist.lookup_store_client ||= Redis.new(:url => (ENV['REDIS_URL'], :driver => :hiredis)
29
+ Looksist.driver = Looksist::Serializers::Her
30
+ ```
31
+ You need to specify the driver to manage the attributes. In this case, we use [HER](https://github.com/remiprev/her). You can add support for ActiveResource or ActiveRecord as needed (also refer to specs for free form usage without a driver).
32
+
33
+ * Please find the sample rspec to understand the usage and internals
34
+
35
+ ``` ruby
36
+ it 'should generate declarative attributes on the model with simple lookup value' do
37
+ module SimpleLookup
38
+ class Employee
39
+ include Looksist
40
+ attr_accessor :id
41
+ lookup :name, using= :id
42
+
43
+ def initialize(id)
44
+ @id = id
45
+ end
46
+ end
47
+ end
48
+
49
+ expect(Looksist.lookup_store_client).to receive(:get).with('ids/1').and_return('Employee Name')
50
+ e = SimpleLookup::Employee.new(1)
51
+ expect(e.name).to eq('Employee Name')
52
+ end
53
+ ```
54
+ lookup takes the following form:
55
+
56
+ ``` ruby
57
+ lookup :name, using = :employee_id # will lookup "employees/#{employee_id}" from the store
58
+
59
+ lookup :name, using = :employee_id, bucket_name="stars" # will lookup "stars/#{employee_id}" from the store
60
+
61
+ lookup [:name, :location], using = :employee_id # will lookup "stars/#{employee_id}" from the store for an object with two attributes (name, location)
24
62
 
25
- ## Contributing
63
+ ```
26
64
 
27
- 1. Fork it ( https://github.com/[my-github-username]/herdis/fork )
28
- 2. Create your feature branch (`git checkout -b my-new-feature`)
29
- 3. Commit your changes (`git commit -am 'Add some feature'`)
30
- 4. Push to the branch (`git push origin my-new-feature`)
31
- 5. Create a new Pull Request
data/lib/looksist.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require 'looksist/version'
2
+ require 'looksist/redis_service'
3
+ require 'looksist/hashed'
2
4
 
3
5
  module Looksist
4
6
  extend ActiveSupport::Concern
@@ -19,7 +21,7 @@ module Looksist
19
21
  what.each do |method_name|
20
22
  define_method(method_name) do
21
23
  key = [bucket, '/', self.send(using).try(:to_s)].join('')
22
- JSON.parse(send(:memoized, key))[method_name.to_s]
24
+ JSON.parse(send(:memoized, key) || '{}')[method_name.to_s]
23
25
  end
24
26
  self.lookup_attributes << method_name
25
27
  end
@@ -0,0 +1,42 @@
1
+ module Looksist
2
+ module Hashed
3
+ extend ActiveSupport::Concern
4
+
5
+ # inject after: :assortment, at: 'table', using: :supplier_id, populate: :supplier_name, bucket_name: 'suppliers'
6
+
7
+ class << self;
8
+ attr_accessor :redis_service
9
+ end
10
+
11
+ module ClassMethods
12
+ def inject(opts)
13
+ raise 'Incorrect usage' unless [:after, :using, :populate].all? { |e| opts.keys.include? e }
14
+ @rules ||= {}
15
+ @rules[opts[:after]] ||= []
16
+ @rules[opts[:after]] << opts
17
+ return if @rules[opts[:after]].length > 1
18
+
19
+ define_method("#{opts[:after]}_with_inject") do
20
+ hash = send("#{opts[:after]}_without_inject".to_sym)
21
+ self.class.instance_variable_get(:@rules)[opts[:after]].each do |opts|
22
+ keys = hash[opts[:at]][opts[:using]]
23
+ entity_name = entity(opts[:using])
24
+ values = Hashed.redis_service.send("#{entity_name}_for", keys)
25
+ hash[opts[:at]][opts[:populate]] = values
26
+ end
27
+ hash
28
+ end
29
+
30
+ alias_method_chain opts[:after], :inject
31
+ end
32
+ end
33
+
34
+ included do |base|
35
+ base.class_attribute :rules
36
+ end
37
+
38
+ def entity(entity_id)
39
+ entity = entity_id.to_s.gsub('_id', '')
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,54 @@
1
+ module Looksist
2
+ class RedisService
3
+ attr_accessor :client, :buffer_size, :cache
4
+
5
+ def self.instance
6
+ @_instance_ ||= new
7
+ @_instance_.cache ||= {}
8
+ yield @_instance_ if block_given?
9
+ @_instance_.buffer_size ||= 50000
10
+ @_instance_
11
+ end
12
+
13
+ def method_missing(m, *args, &block)
14
+ if m.to_s.ends_with?("_for")
15
+ entity = m.to_s.gsub('_for', '')
16
+ args.first.is_a?(Array) ? find_all(entity, args.first) : find(entity, args.first)
17
+ else
18
+ super(m, args)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def find(entity, id)
25
+ key = redis_key(entity, id)
26
+ hit_or_miss(key) do
27
+ @client.get(key)
28
+ end
29
+ end
30
+
31
+
32
+ def find_all(entity, ids)
33
+ @client.pipelined do
34
+ ids.uniq.each do |id|
35
+ find(entity, id)
36
+ end
37
+ end
38
+ ids.each_with_object([]) { |k, acc| acc << cache[redis_key(entity, k)] }
39
+ end
40
+
41
+ def hit_or_miss(key, &block)
42
+ @cache[key] ||= lru(&block)
43
+ end
44
+
45
+ def lru
46
+ @cache.shift if @cache.length >= @buffer_size
47
+ yield
48
+ end
49
+
50
+ def redis_key(entity, id)
51
+ "#{entity.pluralize}/#{id}"
52
+ end
53
+ end
54
+ end
@@ -1,3 +1,3 @@
1
1
  module Lookist
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.2'
3
3
  end
@@ -0,0 +1,120 @@
1
+ require 'spec_helper'
2
+
3
+ describe Looksist::Hashed do
4
+ before(:each) do
5
+ class MockRedis
6
+ def pipelined
7
+ yield
8
+ end
9
+ end
10
+
11
+ @mock = MockRedis.new
12
+ Looksist::Hashed.redis_service = Looksist::RedisService.instance do |lookup|
13
+ lookup.client = @mock
14
+ end
15
+ end
16
+
17
+
18
+ context 'inject ' do
19
+ it 'should inject single attribute to an existing hash' do
20
+ class HashService1
21
+ include Looksist::Hashed
22
+
23
+ def metrics
24
+ {
25
+ table: {
26
+ employee_id: [1, 2]
27
+ }
28
+ }
29
+ end
30
+
31
+ inject after: :metrics, at: :table, using: :employee_id, populate: :employee_name
32
+ end
33
+
34
+ expect(@mock).to receive(:get).with('employees/1').and_return('emp 1')
35
+ expect(@mock).to receive(:get).with('employees/2').and_return('emp 2')
36
+
37
+ HashService1.new.metrics.should eq({table: {
38
+ employee_id: [1, 2],
39
+ employee_name: ['emp 1', 'emp 2']
40
+ }})
41
+ end
42
+
43
+ it 'should inject multiple attribute to an existing hash' do
44
+ class HashService
45
+ include Looksist::Hashed
46
+
47
+ def metrics
48
+ {
49
+ table: {
50
+ employee_id: [5, 6],
51
+ employer_id: [3, 4]
52
+ }
53
+ }
54
+ end
55
+
56
+ inject after: :metrics, at: :table, using: :employee_id, populate: :employee_name
57
+ inject after: :metrics, at: :table, using: :employer_id, populate: :employer_name
58
+ end
59
+
60
+ expect(@mock).to receive(:get).with('employees/5').and_return('emp 5')
61
+ expect(@mock).to receive(:get).with('employees/6').and_return('emp 6')
62
+
63
+ expect(@mock).to receive(:get).with('employers/3').and_return('empr 3')
64
+ expect(@mock).to receive(:get).with('employers/4').and_return('empr 4')
65
+
66
+ HashService.new.metrics.should eq({table: {
67
+ employee_id: [5, 6],
68
+ employer_id: [3, 4],
69
+ employee_name: ['emp 5', 'emp 6'],
70
+ employer_name: ['empr 3', 'empr 4']
71
+ }})
72
+ end
73
+ end
74
+
75
+
76
+ context 'multiple methods and injections' do
77
+ it 'should inject multiple attribute to an existing hash' do
78
+ class HashServiceSuper
79
+ include Looksist::Hashed
80
+
81
+ def shrinkage
82
+ {
83
+ table: {
84
+ shrink_id: [1, 2]
85
+ }
86
+ }
87
+ end
88
+
89
+ def stock
90
+ {
91
+ table: {
92
+ dc_id: [7, 8]
93
+ }
94
+ }
95
+ end
96
+
97
+ inject after: :shrinkage, at: :table, using: :shrink_id, populate: :shrink_name
98
+ inject after: :stock, at: :table, using: :dc_id, populate: :dc_name
99
+ end
100
+
101
+ expect(@mock).to receive(:get).with('shrinks/1').and_return('shrink 1')
102
+ expect(@mock).to receive(:get).with('shrinks/2').and_return('shrink 2')
103
+
104
+ expect(@mock).to receive(:get).with('dcs/7').and_return('dc 7')
105
+ expect(@mock).to receive(:get).with('dcs/8').and_return('dc 8')
106
+
107
+ hash_service_super = HashServiceSuper.new
108
+ hash_service_super.shrinkage.should eq({table: {
109
+ shrink_id: [1, 2],
110
+ shrink_name: ['shrink 1', 'shrink 2']
111
+ }})
112
+
113
+ hash_service_super.stock.should eq({table: {
114
+ dc_id: [7, 8],
115
+ dc_name: ['dc 7', 'dc 8']
116
+ }})
117
+ end
118
+
119
+ end
120
+ end
@@ -71,39 +71,49 @@ describe Looksist do
71
71
  module SimpleLookup
72
72
  class Employee
73
73
  include Looksist
74
- attr_accessor :id
74
+ attr_accessor :id, :employee_id
75
75
  lookup :name, using= :id
76
+ lookup :unavailable, using= :employee_id
76
77
 
77
78
  def initialize(id)
78
- @id = id
79
+ @id = @employee_id = id
79
80
  end
80
81
  end
81
82
  end
82
83
 
83
84
  expect(Looksist.lookup_store_client).to receive(:get).with('ids/1').and_return('Employee Name')
85
+ expect(Looksist.lookup_store_client).to receive(:get).with('employees/1').and_return(nil)
84
86
  e = SimpleLookup::Employee.new(1)
85
87
  expect(e.name).to eq('Employee Name')
88
+ expect(e.unavailable).to be(nil)
86
89
  end
87
90
 
88
91
  it 'should generate declarative attributes on the model with object based lookup value' do
89
92
  module CompositeLookup
90
93
  class Employee
91
94
  include Looksist
92
- attr_accessor :id
95
+ attr_accessor :id, :employee_id
93
96
 
94
97
  lookup [:name, :location], using=:id
98
+ lookup [:age, :sex], using=:employee_id
95
99
 
96
100
  def initialize(id)
97
- @id = id
101
+ @id = @employee_id = id
98
102
  end
99
103
  end
100
104
  end
101
105
 
102
106
  expect(Looksist.lookup_store_client).to receive(:get).with('ids/1')
103
107
  .and_return({name: 'Employee Name', location: 'Chennai'}.to_json)
108
+ expect(Looksist.lookup_store_client).to receive(:get).twice.with('employees/1')
109
+ .and_return(nil)
104
110
  e = CompositeLookup::Employee.new(1)
111
+
105
112
  expect(e.name).to eq('Employee Name')
106
113
  expect(e.location).to eq('Chennai')
114
+
115
+ expect(e.age).to be(nil)
116
+ expect(e.sex).to be(nil)
107
117
  end
108
118
  end
109
119
  end
data/spec/spec_helper.rb CHANGED
@@ -2,6 +2,8 @@ require 'active_support/all'
2
2
  require 'faraday_middleware'
3
3
  require 'her'
4
4
  require 'looksist'
5
+ require 'looksist/redis_service'
6
+ require 'looksist/hashed'
5
7
  require 'pry'
6
8
 
7
9
  module Her
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: looksist
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - RC
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-10-15 00:00:00.000000000 Z
12
+ date: 2014-10-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -155,8 +155,11 @@ files:
155
155
  - README.md
156
156
  - Rakefile
157
157
  - lib/looksist.rb
158
+ - lib/looksist/hashed.rb
159
+ - lib/looksist/redis_service.rb
158
160
  - lib/looksist/version.rb
159
161
  - looksist.gemspec
162
+ - spec/hashed_spec.rb
160
163
  - spec/looksist_spec.rb
161
164
  - spec/spec_helper.rb
162
165
  homepage: https://github.com/jpsimonroy/herdis
@@ -184,5 +187,6 @@ signing_key:
184
187
  specification_version: 4
185
188
  summary: Redis backed lookup for your her models
186
189
  test_files:
190
+ - spec/hashed_spec.rb
187
191
  - spec/looksist_spec.rb
188
192
  - spec/spec_helper.rb