knuckles 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bb83d5d1b1dd47e62ea44595951f957304215bc2
4
+ data.tar.gz: a7ca90254ffad1b2a5c7d901ffb00bd18a0cce07
5
+ SHA512:
6
+ metadata.gz: 3f705fab0c4141190600d8c7179cb0f5ef9db0fd408fa978377ec0fb8c8e01bcb6d9b266049ba7c86bc30753eb6d4afa4586fa099396792609375122be967e4b
7
+ data.tar.gz: df014c860e15f578d98c9cdb5f6a5ab264da0451923b3647f17eca26d6ebe440f7d88f1b51c8ca61fb4a32936fbd7a2b55821f176d4d583549f87f322b8277a1
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ TODO.md
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,33 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'bench/**/*'
4
+ - 'bin/*'
5
+ - 'tmp/**/*'
6
+ - 'vendor/**/*'
7
+
8
+ Style/IfUnlessModifier:
9
+ Enabled: false
10
+
11
+ # Documentation is coming
12
+ Style/Documentation:
13
+ Enabled: false
14
+
15
+ # Extend self preserves private methods
16
+ Style/ModuleFunction:
17
+ Enabled: false
18
+
19
+ Style/PredicateName:
20
+ NamePrefix:
21
+ - is_
22
+ NamePrefixBlacklist:
23
+ - is_
24
+
25
+ Style/StringLiterals:
26
+ EnforcedStyle: double_quotes
27
+
28
+ Style/SpaceInsideHashLiteralBraces:
29
+ EnforcedStyle: no_space
30
+ EnforcedStyleForEmptyBraces: no_space
31
+
32
+ Style/IndentArray:
33
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.4
5
+ - 2.3.0
6
+ - ruby-head
7
+ matrix:
8
+ allow_failures:
9
+ - rvm: ruby-head
10
+ bundler_args: --without benchmarking
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## v0.1.0 - 2016-03-21
2
+
3
+ * Initial release (third time's the charm).
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem "rubocop", require: false
6
+ gem "coveralls", require: false
7
+
8
+ group :benchmarking do
9
+ gem "benchmark-ips"
10
+ gem "stackprof"
11
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Parker Selbert
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,77 @@
1
+ [![Build Status](https://travis-ci.org/sorentwo/knuckles.svg?branch=master)](https://travis-ci.org/sorentwo/knuckles)
2
+ [![Coverage Status](https://coveralls.io/repos/github/sorentwo/knuckles/badge.svg?branch=master)](https://coveralls.io/github/sorentwo/knuckles?branch=master)
3
+ [![Code Climate](https://codeclimate.com/github/sorentwo/knuckles/badges/gpa.svg)](https://codeclimate.com/github/sorentwo/knuckles)
4
+
5
+ # Knuckles (Because Sonic was Taken)
6
+
7
+ What's it all about?
8
+
9
+ * Emphasis on caching as a composable operation
10
+ * Reduced object instantiation
11
+ * Complete instrumentation of every discrete operation
12
+ * Entirely agnostic, can be dropped into any project and integrated over time
13
+ * Minimal runtime dependencies
14
+ * Explicit serializer view API with as little overhead and no DSL
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ ```ruby
21
+ gem "knuckles"
22
+ ```
23
+
24
+ ## Configuration
25
+
26
+ There isn't a hard dependency on `Oj` or `Readthis`, but you'll find they are
27
+ drastically more performant.
28
+
29
+ ```ruby
30
+ require "activesupport"
31
+ require "oj"
32
+ require "readthis"
33
+
34
+ Knuckles.configure do |config|
35
+ config.cache = Readthis::Cache.new(
36
+ marshal: Oj,
37
+ compress: true,
38
+ driver: :hiredis
39
+ )
40
+
41
+ config.keygen = Readthis::Expanders
42
+ config.serializer = Oj
43
+ end
44
+ ```
45
+
46
+ With the top level module configured it is simple to jump right into rendering,
47
+ but we'll look at configuring the pipeline first.
48
+
49
+ ## Defining Views
50
+
51
+ The interface for defining serializers is largely based on Active Model
52
+ Serializers, but with a few key differences.
53
+
54
+ ```ruby
55
+ class ScoutSerializer
56
+ include Knuckles::Serializer
57
+
58
+ root 'scout'
59
+
60
+ attributes :id, :email, :display_name
61
+
62
+ has_one :thing, serializer: ThingSerializer
63
+ has_many :other, serializer: OtherThingSerializer
64
+
65
+ def display_name(object, options)
66
+ "#{object.first_name} #{object.last_name}"
67
+ end
68
+ end
69
+ ```
70
+
71
+ ## Contributing
72
+
73
+ 1. Fork it ( https://github.com/sorentwo/knuckles/fork )
74
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
75
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
76
+ 4. Push to the branch (`git push origin my-new-feature`)
77
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/setup"
2
+ require "bundler/gem_tasks"
3
+ require "rubocop/rake_task"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+ RuboCop::RakeTask.new
8
+
9
+ task default: [:spec, :rubocop]
@@ -0,0 +1,48 @@
1
+ require "bundler"
2
+
3
+ Bundler.setup
4
+
5
+ require "active_support/cache"
6
+ require "benchmark/ips"
7
+ require "json"
8
+ require "knuckles"
9
+ require_relative "fixtures/serializers"
10
+
11
+ class BenchModel
12
+ attr_reader :key
13
+
14
+ def initialize(key, attributes)
15
+ attributes.each do |key, value|
16
+ self.class.send(:define_method, key) { value }
17
+ end
18
+ end
19
+
20
+ def cache_key
21
+ "#{key}/#{id}/#{updated_at}"
22
+ end
23
+ end
24
+
25
+ module BenchHelper
26
+ extend self
27
+
28
+ def submissions
29
+ mapping = %w[scout responses tags]
30
+ loaded = JSON.load(IO.read("bench/fixtures/submissions.json"))
31
+
32
+ loaded.map do |object|
33
+ mapping.each do |key|
34
+ object[key] = structify(key, object[key])
35
+ end
36
+
37
+ structify('submissions', object)
38
+ end
39
+ end
40
+
41
+ def structify(key, object)
42
+ if object.is_a?(Array)
43
+ object.map { |obj| BenchModel.new(key, obj) }
44
+ else
45
+ BenchModel.new(key, object)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,93 @@
1
+ module ScoutView
2
+ extend Knuckles::View
3
+
4
+ def self.root
5
+ :scouts
6
+ end
7
+
8
+ def self.data(object, _)
9
+ { id: object.id,
10
+ first_name: object.first_name,
11
+ gender: object.gender,
12
+ city: object.city,
13
+ state: object.state,
14
+ country: object.country,
15
+ education: object.education,
16
+ employment_status: object.employment_status,
17
+ ethnicity: object.ethnicity,
18
+ household_composition: object.household_composition,
19
+ household_income: object.household_income,
20
+ industry: object.industry,
21
+ created_at: object.created_at,
22
+ updated_at: object.updated_at }
23
+ end
24
+ end
25
+
26
+ module ResponseView
27
+ extend Knuckles::View
28
+
29
+ def self.root
30
+ :responses
31
+ end
32
+
33
+ def self.data(object, _)
34
+ { id: object.id,
35
+ answers: object.answers,
36
+ question_id: object.question_id,
37
+ respondable_id: object.respondable_id,
38
+ longitude: object.longitude,
39
+ latitude: object.latitude,
40
+ time_zone: object.time_zone,
41
+ answered_at: object.answered_at,
42
+ created_at: object.created_at,
43
+ updated_at: object.updated_at }
44
+ end
45
+ end
46
+
47
+ module TagView
48
+ extend Knuckles::View
49
+
50
+ def self.root
51
+ :tags
52
+ end
53
+
54
+ def self.data(object, _)
55
+ { id: object.id,
56
+ parent_id: object.parent_id,
57
+ name: object.name,
58
+ group: object.group,
59
+ auto_tag: object.auto_tag,
60
+ keywords: object.keywords,
61
+ created_at: object.created_at,
62
+ updated_at: object.updated_at }
63
+ end
64
+ end
65
+
66
+ module SubmissionView
67
+ extend Knuckles::View
68
+
69
+ def self.root
70
+ :submissions
71
+ end
72
+
73
+ def self.data(object, _)
74
+ { id: object.id,
75
+ screener_id: object.screener_id,
76
+ rating: object.rating,
77
+ latitude: object.latitude,
78
+ longitude: object.longitude,
79
+ source: object.source,
80
+ time_zone: object.time_zone,
81
+ bookmarks_count: object.bookmarks_count,
82
+ notes_count: object.notes_count,
83
+ finished_at: object.finished_at,
84
+ created_at: object.created_at,
85
+ updated_at: object.updated_at }
86
+ end
87
+
88
+ def self.relations(object, _)
89
+ { scouts: has_one(object.scout, ScoutView),
90
+ responses: has_many(object.responses, ResponseView),
91
+ tags: has_many(object.tags, TagView) }
92
+ end
93
+ end