kashmir 0.1 → 0.1.1

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: c5780c967e6ff6ba5b26f80137d30266d1d55554
4
- data.tar.gz: e4b5a243cfaa28a516c9637457a34f880612d766
3
+ metadata.gz: e10560235dc4ce72083facd7ea74c69b3bedb255
4
+ data.tar.gz: b418df0a0a818e6f00683e5c0115b2c619c0134d
5
5
  SHA512:
6
- metadata.gz: 88b891a003b3a760036888515d56b6dfbc2bab338103c3f2a146d10dd61b5ed887ab438e40e10b8f786bb3db9e8388114852d952821e3685aea3ef6df6507c9f
7
- data.tar.gz: d1ee5652b5359b418efebe856de46738322eb6213575c9a49e0b71753064313cd2c3e62a7e7dab3bfc64920266ad614857e9e92b35bd02075502e1d4e1ad5709
6
+ metadata.gz: a63bfb22aad18c97ed7a477a35a752fbe82c8d90bb09caf1d9b3651312dae3fe9430e2cc7770423454a98776475279fa12b031406721f2c3dac7461c66e08847
7
+ data.tar.gz: c4723de817322bea9e4ab0069424a3d8144f3c2ec6bb314ea8c6d62688b143b4483b10bcad8dfe591e36c9f078b19bb636afd10da9c171bf3d6c3d54c37e8708
@@ -1,4 +1,4 @@
1
- Copyright (c) 2015 Netto Farah
1
+ Copyright (c) 2015 IFTTT
2
2
 
3
3
  MIT License
4
4
 
data/README.md CHANGED
@@ -1,18 +1,20 @@
1
- # Kashmir
1
+ [![Open Source at IFTTT](http://ifttt.github.io/images/open-source-ifttt.svg)](http://ifttt.github.io)
2
2
 
3
- Kashmir is a DSL built to allow developers to describe representations of their ruby objects.
4
- Kashmir will turn these ruby objects into `Hash`es that represent the dependency tree you just described.
3
+ ![Kashmir](https://raw.githubusercontent.com/IFTTT/kashmir/images/images/kashmirbanner.jpg?token=AAIf5wn0aFvxx1oNOO6GVw7SO4vENFW4ks5VuSaLwA%3D%3D "Kashmir")
5
4
 
6
- `Kashmir::ActiveRecord` will also optimize and try to balance `ActiveRecord` queries, so your application hits the database as little as possible.
5
+ Kashmir is a DSL built to allow developers to describe representations of Ruby objects.
6
+ Kashmir will turn these Ruby objects into hashes that represent the dependency tree you just described.
7
7
 
8
- `Kashmir::Caching` builds a dependency tree for complex object representations and caches each level of this tree separately. Kashmir will do so by creating cache views of each one of these layers, but also caching a complete tree.
9
- The caching engine is smart enough to fill out holes in the cache tree with fresh data from your database or another sort of data store.
8
+ `Kashmir::ActiveRecord` will also optimize and try to balance `ActiveRecord` queries so your application hits the database as little as possible.
9
+
10
+ `Kashmir::Caching` builds a dependency tree for complex object representations and caches each level of this tree separately. Kashmir will do so by creating cache views of each level as well as caching a complete tree.
11
+ The caching engine is smart enough to fill holes in the cache tree with fresh data from your data store.
10
12
 
11
13
  Combine `Kashmir::Caching` + `Kashmir::ActiveRecord` for extra awesomeness.
12
14
 
13
15
  ### Example:
14
16
 
15
- For example, a `Person` with a `name` and `age`:
17
+ For example, a `Person` with `name` and `age` attributes:
16
18
  ```ruby
17
19
  class Person
18
20
  include Kashmir
@@ -34,18 +36,21 @@ could be represented as:
34
36
  ```
35
37
 
36
38
  Representing an object is as simple as:
37
- 1. add `include Kashmir` to the target class
38
- 2. whitelist all the fields you may want in a representation.
39
+
40
+ 1. Add `include Kashmir` to the target class.
41
+ 2. Whitelist all the fields you want to include in a representation.
42
+
39
43
  ```ruby
40
- # add all the fields, methods you want to be visible to Kashmir
44
+ # Add fields and methods you want to be visible to Kashmir
41
45
  representations do
42
- rep(:name) # this exposes the property name to Kashmir
46
+ rep(:name)
43
47
  rep(:age)
44
48
  end
45
49
  ```
50
+
46
51
  3. Instantiate an object and `#represent` it.
47
52
  ```ruby
48
- # you can pass in an array with all the fields you want to be represented
53
+ # Pass in an array with all the fields you want included
49
54
  Person.new('Netto Farah', 26).represent([:name, :age])
50
55
  => {:name=>"Netto Farah", :age=>"26"}
51
56
  ```
@@ -65,11 +70,11 @@ And then execute:
65
70
  ## Usage
66
71
  Kashmir is better described with examples.
67
72
 
68
- ### Basic representations
73
+ ### Basic Representations
69
74
 
70
- #### Describing an object
75
+ #### Describing an Object
71
76
  Only whitelisted fields can be represented by Kashmir.
72
- This is done so secret fields don't get exposed to clients, such as passwords and salts.
77
+ This is done so sensitive fields (like passwords) cannot be accidentally exposed to clients.
73
78
 
74
79
  ``` ruby
75
80
  class Recipe < OpenStruct
@@ -84,17 +89,17 @@ end
84
89
 
85
90
  Instantiate a `Recipe`:
86
91
  ```ruby
87
- recipe = Recipe.new(title: 'Beef stew', preparation_time: 60)
92
+ recipe = Recipe.new(title: 'Beef Stew', preparation_time: 60)
88
93
  ```
89
94
 
90
- Kashmir automatically adds a `#represent` method to every instance of `Recipe` now.
91
- `#represent` will take an `Array` with all the fields you want as part of your representation.
95
+ Kashmir automatically adds a `#represent` method to every instance of `Recipe`.
96
+ `#represent` takes an `Array` with all the fields you want as part of your representation.
92
97
 
93
98
  ```ruby
94
99
  recipe.represent([:title, :preparation_time])
95
- => { title: 'Beef stew', preparation_time: 60 }
100
+ => { title: 'Beef Stew', preparation_time: 60 }
96
101
  ```
97
- #### Calculated fields
102
+ #### Calculated Fields
98
103
  You can represent any instance variable or method (basically anything that returns `true` for `respond_to?`).
99
104
  ``` ruby
100
105
  class Recipe < OpenStruct
@@ -112,11 +117,11 @@ end
112
117
  ```
113
118
 
114
119
  ```ruby
115
- Recipe.new(title: 'Beef stew', steps: ['chop', 'cook']).represent([:title, :num_steps])
116
- => { title: 'Beef stew', num_steps: 2 }
120
+ Recipe.new(title: 'Beef Stew', steps: ['chop', 'cook']).represent([:title, :num_steps])
121
+ => { title: 'Beef Stew', num_steps: 2 }
117
122
  ```
118
123
 
119
- ### Nested representations
124
+ ### Nested Representations
120
125
  You can nest Kashmir objects to represent complex relationships between your objects.
121
126
  ```ruby
122
127
  class Recipe < OpenStruct
@@ -137,8 +142,7 @@ class Chef < OpenStruct
137
142
  end
138
143
  ```
139
144
 
140
- Nested representations can be described as hashes inside your array of fields.
141
- You can then pass in another array with all the properties you want to present in the nested object.
145
+ When you create a representation, nest hashes to create nested representations.
142
146
  ```ruby
143
147
  netto = Chef.new(name: 'Netto Farah')
144
148
  beef_stew = Recipe.new(title: 'Beef Stew', chef: netto)
@@ -153,8 +157,8 @@ beef_stew.represent([:title, { :chef => [ :name ] }])
153
157
  ```
154
158
  Not happy with this syntax? Check out `Kashmir::DSL` or `Kashmir::InlineDSL` for prettier code.
155
159
 
156
- #### Base representations
157
- Tired of repeating the same fields over and over?
160
+ #### Base Representations
161
+ Are you tired of repeating the same fields over and over?
158
162
  You can create a base representation of your objects, so Kashmir returns basic fields automatically.
159
163
  ```ruby
160
164
  class Recipe
@@ -207,7 +211,7 @@ end
207
211
  ```
208
212
 
209
213
  ```ruby
210
- bbq_joint = Restaurant.new(name: "Netto's BBQ Joint", rating: '5 stars')
214
+ bbq_joint = Restaurant.new(name: "Netto's BBQ Joint", rating: '5 Stars')
211
215
  netto = Chef.new(name: 'Netto', restaurant: bbq_joint)
212
216
  brisket = Recipe.new(title: 'BBQ Brisket', chef: netto)
213
217
 
@@ -223,7 +227,7 @@ brisket.represent([
223
227
  name: 'Netto',
224
228
  restaurant: {
225
229
  name: "Netto's BBQ Joint",
226
- rating: '5 stars'
230
+ rating: '5 Stars'
227
231
  }
228
232
  }
229
233
  }
@@ -310,7 +314,7 @@ brisket.represent(RecipePresenter)
310
314
 
311
315
  => { title: 'BBQ Brisket', num_steps: 2 }
312
316
  ```
313
- #### Embed Representers
317
+ #### Embedded Representers
314
318
  It is also possible to define nested representers with `embed(:property_name, RepresenterClass)`.
315
319
 
316
320
  ```ruby
@@ -388,7 +392,7 @@ end
388
392
  => { title: 'BBQ Brisket', num_steps: 2 }
389
393
  ```
390
394
 
391
- #### Nested inline representations
395
+ #### Nested Inline Representations
392
396
  You can nest inline representations using `inline(:field, &block)` the same way we did with `Kashmir::Dsl`.
393
397
 
394
398
  ```ruby
@@ -512,7 +516,7 @@ For more examples, check out: https://github.com/IFTTT/kashmir/blob/master/test/
512
516
  Caching is the best feature in Kashmir.
513
517
  The `Kashmir::Caching` module will cache every level of the dependency tree Kashmir generates when representing an object.
514
518
 
515
- ![Dependency Tree](http://imageshack.com/a/img661/6152/LAGBwO.png "Dependency Tree")
519
+ ![Dependency Tree](https://raw.githubusercontent.com/IFTTT/kashmir/images/images/kashmir.png?token=AAIf57rtAVfFPENYmWfBJ9nhZOmbFs1qks5VuVFOwA%3D%3D "Dependency Tree")
516
520
 
517
521
  As you can see in the image above, Kashmir will build a dependency tree of the representation.
518
522
  If you have Caching on, Kashmir will:
@@ -527,7 +531,7 @@ Kashmir will also be able to fill in blanks in the dependency tree and fetch mis
527
531
  Caching is turned off by default, but you can use one of the two available implementations.
528
532
 
529
533
  - [In Memory Caching] https://github.com/IFTTT/kashmir/blob/master/lib/kashmir/plugins/memory_caching.rb
530
- - [Memcached] https://github.com/IFTTT/kashmir/blob/master/lib/kashmir/plugins/memcached_caching.rb (Currently used on ifttt.com).
534
+ - [Memcached] https://github.com/IFTTT/kashmir/blob/master/lib/kashmir/plugins/memcached_caching.rb
531
535
 
532
536
  You can also build your own custom caching engine by following the `NullCaching` protocol available at:
533
537
  https://github.com/IFTTT/kashmir/blob/master/lib/kashmir/plugins/null_caching.rb
@@ -542,6 +546,8 @@ Kashmir.init(
542
546
 
543
547
  ##### With Memcached
544
548
  ```ruby
549
+ require 'kashmir/plugins/memcached_caching'
550
+
545
551
  client = Dalli::Client.new(url, namespace: 'kashmir', compress: true)
546
552
  default_ttl = 5.minutes
547
553
 
@@ -21,8 +21,6 @@ Gem::Specification.new do |spec|
21
21
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
22
  spec.require_paths = ["lib"]
23
23
 
24
- spec.add_runtime_dependency "colorize", "~> 0.7"
25
-
26
24
  spec.add_development_dependency "bundler", "~> 1.7"
27
25
  spec.add_development_dependency "rake", "~> 10.0"
28
26
  spec.add_development_dependency "minitest", "~> 5.0"
@@ -30,6 +28,5 @@ Gem::Specification.new do |spec|
30
28
  spec.add_development_dependency "mocha", "~> 1.1"
31
29
  spec.add_development_dependency "sqlite3", "1.3.10"
32
30
 
33
- spec.add_development_dependency "dalli", "~> 2.7"
34
- spec.add_development_dependency "activerecord", "3.2.8"
31
+ spec.add_development_dependency "activerecord", "~> 4.2"
35
32
  end
@@ -5,6 +5,7 @@ require "kashmir/inline_dsl"
5
5
  require "kashmir/plugins/ar"
6
6
  require "kashmir/caching"
7
7
  require "kashmir/representable"
8
+ require 'logger'
8
9
 
9
10
  module Kashmir
10
11
 
@@ -1,39 +1,37 @@
1
1
  require 'kashmir/plugins/memory_caching'
2
2
  require 'kashmir/plugins/null_caching'
3
- require 'kashmir/plugins/memcached_caching'
4
- require 'colorize'
5
3
 
6
4
  module Kashmir
7
5
  module Caching
8
6
 
9
7
  def from_cache(representation_definition, object)
10
- log("#{"read".blue}: #{log_key(object, representation_definition)}", :debug)
8
+ log("read: #{log_key(object, representation_definition)}", :debug)
11
9
 
12
10
  cached_representation = Kashmir.caching.from_cache(representation_definition, object)
13
11
 
14
12
  if cached_representation
15
- log("#{"hit".green}: #{log_key(object, representation_definition)}")
13
+ log("hit: #{log_key(object, representation_definition)}")
16
14
  else
17
- log("#{"miss".red}: #{log_key(object, representation_definition)}")
15
+ log("miss: #{log_key(object, representation_definition)}")
18
16
  end
19
17
 
20
18
  cached_representation
21
19
  end
22
20
 
23
21
  def bulk_from_cache(representation_definition, objects)
24
- class_name = objects.size > 0 ? objects.first.class.to_s : ''
25
- log("#{"read_multi".blue}: [#{objects.size}]#{class_name} : #{representation_definition}", :debug)
22
+ class_name = objects.length > 0 ? objects.first.class.to_s : ''
23
+ log("read_multi: [#{objects.length}]#{class_name} : #{representation_definition}", :debug)
26
24
  Kashmir.caching.bulk_from_cache(representation_definition, objects)
27
25
  end
28
26
 
29
27
  def store_presenter(representation_definition, representation, object, ttl)
30
- log("#{"write".blue} TTL: #{ttl}: #{log_key(object, representation_definition)}", :debug)
28
+ log("write TTL: #{ttl}: #{log_key(object, representation_definition)}", :debug)
31
29
  Kashmir.caching.store_presenter(representation_definition, representation, object, ttl)
32
30
  end
33
31
 
34
32
  def bulk_write(representation_definition, representations, objects, ttl)
35
- class_name = objects.size > 0 ? objects.first.class.to_s : ''
36
- log("#{"write_multi".blue}: TTL: #{ttl}: [#{objects.size}]#{class_name} : #{representation_definition}", :debug)
33
+ class_name = objects.length > 0 ? objects.first.class.to_s : ''
34
+ log("write_multi: TTL: #{ttl}: [#{objects.length}]#{class_name} : #{representation_definition}", :debug)
37
35
  Kashmir.caching.bulk_write(representation_definition, representations, objects, ttl)
38
36
  end
39
37
 
@@ -42,7 +40,7 @@ module Kashmir
42
40
  end
43
41
 
44
42
  def log(message, level=:info)
45
- Kashmir.logger.send(level, ("\n#{"Kashmir::Caching".magenta} #{message}\n"))
43
+ Kashmir.logger.send(level, ("\nKashmir::Caching #{message}\n"))
46
44
  end
47
45
 
48
46
  module_function :from_cache, :bulk_from_cache, :bulk_write, :store_presenter, :log_key, :log
@@ -1,8 +1,8 @@
1
1
  # We have to reopen Preloader to allow for it
2
2
  # to accept any random attribute name as a preloadable association.
3
3
  #
4
- # This allows us to send any abirtrary Hash to Preloader.
5
- # Not only keys that we know are ActiveRecord relations in advance.
4
+ # This allows us to send any arbitrary Hash to Preloader, without
5
+ # requiring it to be an ActiveRecord relation in advance.
6
6
  #
7
7
 
8
8
  module ArV4Patch
@@ -26,6 +26,8 @@ module ArV4Patch
26
26
  klasses = h[assoc.reflection] ||= {}
27
27
  (klasses[assoc.klass] ||= []) << record
28
28
  end
29
+
30
+ h.delete(nil)
29
31
  h
30
32
  end
31
33
  end
@@ -12,7 +12,11 @@ module Kashmir
12
12
  end
13
13
 
14
14
  if to_load.any?
15
- ActiveRecord::Associations::Preloader.new(to_load, representation_definition).run
15
+ if ActiveRecord::VERSION::STRING >= "4.0.2"
16
+ ActiveRecord::Associations::Preloader.new.preload(to_load, representation_definition)
17
+ else
18
+ ActiveRecord::Associations::Preloader.new(to_load, representation_definition).run
19
+ end
16
20
  end
17
21
 
18
22
  to_load_representations = to_load.map do |subject|
@@ -1,3 +1,3 @@
1
1
  module Kashmir
2
- VERSION = "0.1"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -12,6 +12,12 @@ describe 'Caching' do
12
12
  @restaurant = AR::Restaurant.find_by_name('Chef Tom Belly Burgers')
13
13
  end
14
14
 
15
+ after(:all) do
16
+ Kashmir.init(
17
+ cache_client: Kashmir::Caching::Null.new
18
+ )
19
+ end
20
+
15
21
  before(:each) do
16
22
  Kashmir.caching.flush!
17
23
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kashmir
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.1'
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - IFTTT
@@ -9,22 +9,8 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-07-20 00:00:00.000000000 Z
12
+ date: 2015-07-23 00:00:00.000000000 Z
13
13
  dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: colorize
16
- requirement: !ruby/object:Gem::Requirement
17
- requirements:
18
- - - "~>"
19
- - !ruby/object:Gem::Version
20
- version: '0.7'
21
- type: :runtime
22
- prerelease: false
23
- version_requirements: !ruby/object:Gem::Requirement
24
- requirements:
25
- - - "~>"
26
- - !ruby/object:Gem::Version
27
- version: '0.7'
28
14
  - !ruby/object:Gem::Dependency
29
15
  name: bundler
30
16
  requirement: !ruby/object:Gem::Requirement
@@ -110,33 +96,19 @@ dependencies:
110
96
  - !ruby/object:Gem::Version
111
97
  version: 1.3.10
112
98
  - !ruby/object:Gem::Dependency
113
- name: dalli
99
+ name: activerecord
114
100
  requirement: !ruby/object:Gem::Requirement
115
101
  requirements:
116
102
  - - "~>"
117
103
  - !ruby/object:Gem::Version
118
- version: '2.7'
104
+ version: '4.2'
119
105
  type: :development
120
106
  prerelease: false
121
107
  version_requirements: !ruby/object:Gem::Requirement
122
108
  requirements:
123
109
  - - "~>"
124
110
  - !ruby/object:Gem::Version
125
- version: '2.7'
126
- - !ruby/object:Gem::Dependency
127
- name: activerecord
128
- requirement: !ruby/object:Gem::Requirement
129
- requirements:
130
- - - '='
131
- - !ruby/object:Gem::Version
132
- version: 3.2.8
133
- type: :development
134
- prerelease: false
135
- version_requirements: !ruby/object:Gem::Requirement
136
- requirements:
137
- - - '='
138
- - !ruby/object:Gem::Version
139
- version: 3.2.8
111
+ version: '4.2'
140
112
  description: "\n Kashmir helps you easily define decorators/representers/presenters
141
113
  for ruby objects.\n Optionally, Kashmir will also cache these views for faster
142
114
  lookups.\n "
@@ -148,8 +120,7 @@ extensions: []
148
120
  extra_rdoc_files: []
149
121
  files:
150
122
  - Gemfile
151
- - Gemfile.lock
152
- - LICENSE.txt
123
+ - LICENSE
153
124
  - README.md
154
125
  - Rakefile
155
126
  - kashmir.gemspec
@@ -1,49 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- kashmir (0.0.1)
5
- colorize (~> 0.7)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- activemodel (3.2.22)
11
- activesupport (= 3.2.22)
12
- builder (~> 3.0.0)
13
- activerecord (3.2.22)
14
- activemodel (= 3.2.22)
15
- activesupport (= 3.2.22)
16
- arel (~> 3.0.2)
17
- tzinfo (~> 0.3.29)
18
- activesupport (3.2.22)
19
- i18n (~> 0.6, >= 0.6.4)
20
- multi_json (~> 1.0)
21
- arel (3.0.3)
22
- builder (3.0.4)
23
- colorize (0.7.7)
24
- dalli (2.7.4)
25
- i18n (0.7.0)
26
- metaclass (0.0.4)
27
- minitest (5.5.1)
28
- minitest-around (0.3.2)
29
- minitest (~> 5.0)
30
- mocha (1.1.0)
31
- metaclass (~> 0.0.1)
32
- multi_json (1.11.1)
33
- rake (10.4.2)
34
- sqlite3 (1.3.10)
35
- tzinfo (0.3.44)
36
-
37
- PLATFORMS
38
- ruby
39
-
40
- DEPENDENCIES
41
- activerecord (~> 3.2.8)
42
- bundler (~> 1.7)
43
- dalli (~> 2.7)
44
- kashmir!
45
- minitest (~> 5.0)
46
- minitest-around (~> 0.3)
47
- mocha (~> 1.1.0)
48
- rake (~> 10.0)
49
- sqlite3 (= 1.3.10)