smooth-io 0.0.5

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.
Files changed (65) hide show
  1. data/.gitignore +2 -0
  2. data/.rvmrc +1 -0
  3. data/.travis +6 -0
  4. data/CNAME +1 -0
  5. data/Gemfile +13 -0
  6. data/Gemfile.lock +147 -0
  7. data/Guardfile +5 -0
  8. data/LICENSE.md +22 -0
  9. data/README.md +33 -0
  10. data/Rakefile +10 -0
  11. data/bin/smooth +8 -0
  12. data/doc/presenters.md +47 -0
  13. data/lib/smooth.rb +56 -0
  14. data/lib/smooth/adapters/rails_cache.rb +19 -0
  15. data/lib/smooth/adapters/redis_cache.rb +36 -0
  16. data/lib/smooth/backends/active_record.rb +56 -0
  17. data/lib/smooth/backends/base.rb +84 -0
  18. data/lib/smooth/backends/file.rb +80 -0
  19. data/lib/smooth/backends/redis.rb +71 -0
  20. data/lib/smooth/backends/redis_namespace.rb +10 -0
  21. data/lib/smooth/backends/rest_client.rb +29 -0
  22. data/lib/smooth/collection.rb +236 -0
  23. data/lib/smooth/collection/cacheable.rb +12 -0
  24. data/lib/smooth/collection/query.rb +14 -0
  25. data/lib/smooth/endpoint.rb +23 -0
  26. data/lib/smooth/meta_data.rb +33 -0
  27. data/lib/smooth/meta_data/application.rb +29 -0
  28. data/lib/smooth/meta_data/inspector.rb +67 -0
  29. data/lib/smooth/model.rb +93 -0
  30. data/lib/smooth/presentable.rb +76 -0
  31. data/lib/smooth/presentable/api_endpoint.rb +49 -0
  32. data/lib/smooth/presentable/chain.rb +46 -0
  33. data/lib/smooth/presentable/controller.rb +39 -0
  34. data/lib/smooth/queryable.rb +35 -0
  35. data/lib/smooth/queryable/converter.rb +8 -0
  36. data/lib/smooth/queryable/settings.rb +23 -0
  37. data/lib/smooth/resource.rb +10 -0
  38. data/lib/smooth/version.rb +3 -0
  39. data/smooth-io.gemspec +35 -0
  40. data/spec/blueprints/people.rb +4 -0
  41. data/spec/environment.rb +17 -0
  42. data/spec/lib/backends/active_record_spec.rb +17 -0
  43. data/spec/lib/backends/base_spec.rb +77 -0
  44. data/spec/lib/backends/file_spec.rb +46 -0
  45. data/spec/lib/backends/multi_spec.rb +47 -0
  46. data/spec/lib/backends/redis_namespace_spec.rb +41 -0
  47. data/spec/lib/backends/redis_spec.rb +40 -0
  48. data/spec/lib/backends/rest_client_spec.rb +0 -0
  49. data/spec/lib/collection/query_spec.rb +9 -0
  50. data/spec/lib/collection_spec.rb +87 -0
  51. data/spec/lib/examples/cacheable_collection_spec.rb +27 -0
  52. data/spec/lib/examples/smooth_model_spec.rb +13 -0
  53. data/spec/lib/meta_data/application_spec.rb +43 -0
  54. data/spec/lib/meta_data_spec.rb +32 -0
  55. data/spec/lib/model_spec.rb +54 -0
  56. data/spec/lib/presentable/api_endpoint_spec.rb +54 -0
  57. data/spec/lib/presentable_spec.rb +80 -0
  58. data/spec/lib/queryable/converter_spec.rb +104 -0
  59. data/spec/lib/queryable_spec.rb +27 -0
  60. data/spec/lib/resource_spec.rb +17 -0
  61. data/spec/lib/smooth_spec.rb +13 -0
  62. data/spec/spec_helper.rb +23 -0
  63. data/spec/support/models.rb +28 -0
  64. data/spec/support/schema.rb +16 -0
  65. metadata +359 -0
@@ -0,0 +1,2 @@
1
+ tmp
2
+ site
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.3-p392@smooth --create
data/.travis ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ branches:
5
+ only:
6
+ - master
data/CNAME ADDED
@@ -0,0 +1 @@
1
+ smooth.io
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "https://rubygems.org"
2
+ gemspec
3
+
4
+ group :development, :test do
5
+ gem 'rspec'
6
+ gem "rake"
7
+ gem 'fakeredis'
8
+ gem 'guard'
9
+ gem 'rb-fsevent'
10
+ gem 'growl'
11
+ gem 'guard-bundler'
12
+ gem 'guard-rspec'
13
+ end
@@ -0,0 +1,147 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ smooth (0.0.5)
5
+ activerecord (>= 3.2.12)
6
+ activesupport (>= 3.2.12)
7
+ faye
8
+ redis
9
+ redis-namespace
10
+ sinatra
11
+ squeel
12
+ typhoeus
13
+ virtus (= 0.5.5)
14
+
15
+ GEM
16
+ remote: https://rubygems.org/
17
+ specs:
18
+ activemodel (3.2.13)
19
+ activesupport (= 3.2.13)
20
+ builder (~> 3.0.0)
21
+ activerecord (3.2.13)
22
+ activemodel (= 3.2.13)
23
+ activesupport (= 3.2.13)
24
+ arel (~> 3.0.2)
25
+ tzinfo (~> 0.3.29)
26
+ activesupport (3.2.13)
27
+ i18n (= 0.6.1)
28
+ multi_json (~> 1.0)
29
+ addressable (2.3.5)
30
+ arel (3.0.2)
31
+ backports (3.3.4)
32
+ builder (3.0.4)
33
+ coderay (1.0.9)
34
+ cookiejar (0.3.0)
35
+ descendants_tracker (0.0.1)
36
+ diff-lcs (1.2.1)
37
+ em-http-request (1.1.0)
38
+ addressable (>= 2.3.4)
39
+ cookiejar
40
+ em-socksify (>= 0.3)
41
+ eventmachine (>= 1.0.3)
42
+ http_parser.rb (>= 0.6.0.beta.2)
43
+ em-socksify (0.3.0)
44
+ eventmachine (>= 1.0.0.beta.4)
45
+ ethon (0.6.1)
46
+ ffi (>= 1.3.0)
47
+ mime-types (~> 1.18)
48
+ eventmachine (1.0.3)
49
+ faker (0.9.5)
50
+ i18n (~> 0.4)
51
+ fakeredis (0.4.1)
52
+ redis (~> 3.0.0)
53
+ faye (0.8.9)
54
+ cookiejar (>= 0.3.0)
55
+ em-http-request (>= 0.3.0)
56
+ eventmachine (>= 0.12.0)
57
+ faye-websocket (>= 0.4.0)
58
+ rack (>= 1.0.0)
59
+ yajl-ruby (>= 1.0.0)
60
+ faye-websocket (0.7.0)
61
+ eventmachine (>= 0.12.0)
62
+ websocket-driver (>= 0.3.0)
63
+ ffi (1.9.0)
64
+ growl (1.0.3)
65
+ guard (1.6.2)
66
+ listen (>= 0.6.0)
67
+ lumberjack (>= 1.0.2)
68
+ pry (>= 0.9.10)
69
+ terminal-table (>= 1.4.3)
70
+ thor (>= 0.14.6)
71
+ guard-bundler (1.0.0)
72
+ bundler (~> 1.0)
73
+ guard (~> 1.1)
74
+ guard-rspec (2.4.1)
75
+ guard (>= 1.1)
76
+ rspec (~> 2.11)
77
+ http_parser.rb (0.6.0.beta.2)
78
+ i18n (0.6.1)
79
+ listen (0.7.3)
80
+ lumberjack (1.0.2)
81
+ machinist (1.0.6)
82
+ method_source (0.8.1)
83
+ mime-types (1.25)
84
+ multi_json (1.8.0)
85
+ polyamorous (0.6.4)
86
+ activerecord (>= 3.0)
87
+ pry (0.9.12)
88
+ coderay (~> 1.0.5)
89
+ method_source (~> 0.8)
90
+ slop (~> 3.4)
91
+ rack (1.5.2)
92
+ rack-protection (1.5.0)
93
+ rack
94
+ rack-test (0.6.2)
95
+ rack (>= 1.0)
96
+ rake (10.0.3)
97
+ rb-fsevent (0.9.3)
98
+ redis (3.0.2)
99
+ redis-namespace (1.3.1)
100
+ redis (~> 3.0.0)
101
+ rspec (2.13.0)
102
+ rspec-core (~> 2.13.0)
103
+ rspec-expectations (~> 2.13.0)
104
+ rspec-mocks (~> 2.13.0)
105
+ rspec-core (2.13.0)
106
+ rspec-expectations (2.13.0)
107
+ diff-lcs (>= 1.1.3, < 2.0)
108
+ rspec-mocks (2.13.0)
109
+ sinatra (1.4.3)
110
+ rack (~> 1.4)
111
+ rack-protection (~> 1.4)
112
+ tilt (~> 1.3, >= 1.3.4)
113
+ slop (3.4.3)
114
+ sqlite3 (1.3.7)
115
+ squeel (1.1.1)
116
+ activerecord (>= 3.0)
117
+ activesupport (>= 3.0)
118
+ polyamorous (~> 0.6.0)
119
+ terminal-table (1.4.5)
120
+ thor (0.17.0)
121
+ tilt (1.4.1)
122
+ typhoeus (0.6.5)
123
+ ethon (~> 0.6.1)
124
+ tzinfo (0.3.37)
125
+ virtus (0.5.5)
126
+ backports (~> 3.3)
127
+ descendants_tracker (~> 0.0.1)
128
+ websocket-driver (0.3.0)
129
+ yajl-ruby (1.1.0)
130
+
131
+ PLATFORMS
132
+ ruby
133
+
134
+ DEPENDENCIES
135
+ faker (~> 0.9.5)
136
+ fakeredis
137
+ growl
138
+ guard
139
+ guard-bundler
140
+ guard-rspec
141
+ machinist (~> 1.0.6)
142
+ rack-test
143
+ rake
144
+ rb-fsevent
145
+ rspec
146
+ smooth!
147
+ sqlite3 (~> 1.3.3)
@@ -0,0 +1,5 @@
1
+ guard 'rspec' do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec/" }
5
+ end
@@ -0,0 +1,22 @@
1
+ MIT Copyright (c) 2010-2013 Jonathan Soeder
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,33 @@
1
+ # Smooth.io
2
+ [![Build Status](https://travis-ci.org/datapimp/smooth.png?branch=master)](https://travis-ci.org/datapimp/smooth)
3
+
4
+ ### Syncable Cross Platform Persistence
5
+
6
+ Smooth.io is provides a free JSON API out of the box, with a declarative syntax
7
+ to control who can query the API, and what they are able to see.
8
+
9
+ Smooth resources expose configuration data in their API endpoints that
10
+ allow for API clients to discover reource, configure themselves to the data schema.
11
+
12
+ Smooth resources have automatic caching with smart expiration, and built in HTTP cache control.
13
+
14
+ - Swappable Storage Backends
15
+ - [ ] Redis Backend
16
+ - [ ] File Backend
17
+ - [ ] ActiveRecord Backend
18
+
19
+ - Query Interfaces
20
+ - [ ] Squeel
21
+ - [ ] Backbone-Query
22
+
23
+ - REST Interfaces
24
+ - [ ] Rails Controller
25
+ - [ ] Restful Sinatra App
26
+ - [ ] Faye Pub/Sub fo Auto-Syncing
27
+
28
+ - Clients / Syncing
29
+ - [ ] Ruby
30
+ - [ ] Coffeescript
31
+ - [ ] iOS
32
+ - [ ] Android
33
+
@@ -0,0 +1,10 @@
1
+ require 'bundler/setup'
2
+ require 'rspec/core/rake_task'
3
+
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |rspec|
7
+ rspec.rspec_opts = ['--backtrace']
8
+ end
9
+
10
+ task :default => :spec
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require 'smooth'
5
+ rescue
6
+ require 'rubygems'
7
+ require 'smooth'
8
+ end
@@ -0,0 +1,47 @@
1
+ ## Presenters
2
+
3
+ Smooth::Resource classes expose an API for querying data, presenting it
4
+ it as a desired view, and customizing that presentation for the role of
5
+ the user querying the API.
6
+
7
+ Given the following model configuration:
8
+
9
+ ```ruby
10
+ class Person < ActiveRecord::Base
11
+ include Smooth::Resource
12
+ end
13
+
14
+ class PersonPresenter
15
+ def self.default
16
+ [:name, :public_profile_attributes]
17
+ end
18
+
19
+ def self.admin_default
20
+ default + [:coolness_rating, :black_listed?]
21
+ end
22
+ end
23
+ ```
24
+
25
+ We will eventually query this resource through the Smooth::Presentable::Controller
26
+ and will end up making our call to the Query API via the following
27
+ chain:
28
+
29
+ If we are an admin:
30
+
31
+ ```
32
+ # uses the admin_default presenter
33
+ Person.present(query).as(:default).to(:admin)
34
+ ```
35
+
36
+ If we are something else, that is not defined, it defaults:
37
+
38
+ ```
39
+ # uses the default presenter
40
+ Person.present(query).as(:default).to(:something_else)
41
+ ```
42
+
43
+
44
+
45
+
46
+
47
+
@@ -0,0 +1,56 @@
1
+ require 'active_support/core_ext'
2
+ require 'active_record'
3
+ require 'typhoeus'
4
+ require 'redis'
5
+ require 'redis-namespace'
6
+ require 'squeel'
7
+ require 'virtus'
8
+
9
+ module Smooth
10
+ mattr_accessor :data_directory, :namespace
11
+
12
+ def self.namespace
13
+ @@namespace || "smooth"
14
+ end
15
+
16
+ def self.project
17
+ if defined?(::Rails)
18
+ Rails.application.class.to_s
19
+ end
20
+ end
21
+
22
+ def self.environment
23
+ ENV['RAILS_ENV'] || ENV['SMOOTH_ENV'] || "development"
24
+ end
25
+
26
+ def self.data_directory
27
+ @@data_directory || File.join(ENV['HOME'],'.smooth',environment)
28
+ end
29
+
30
+ require 'smooth/version'
31
+ require 'smooth/meta_data'
32
+ require 'smooth/meta_data/application'
33
+
34
+ require 'smooth/queryable'
35
+
36
+ require 'smooth/presentable/chain'
37
+ require 'smooth/presentable/controller'
38
+ require 'smooth/presentable/api_endpoint'
39
+ require 'smooth/presentable'
40
+
41
+ require 'smooth/backends/base'
42
+ require 'smooth/backends/active_record'
43
+ require 'smooth/backends/file'
44
+ require 'smooth/backends/redis'
45
+ require 'smooth/backends/redis_namespace'
46
+ require 'smooth/backends/rest_client'
47
+
48
+ require 'smooth/adapters/redis_cache.rb'
49
+
50
+ require 'smooth/model'
51
+ require 'smooth/collection/cacheable'
52
+ require 'smooth/collection/query'
53
+
54
+ require 'smooth/collection'
55
+ require "smooth/resource"
56
+ end
@@ -0,0 +1,19 @@
1
+ module Smooth
2
+ module Adapters
3
+ class RailsCache
4
+
5
+ def get key
6
+ Rails.cache.get(key)
7
+ end
8
+
9
+ def write key, value
10
+ Rails.cache.write(key, value)
11
+ value
12
+ end
13
+
14
+ def fetch key, &block
15
+ Rails.cache.fetch key, &block
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,36 @@
1
+ module Smooth
2
+ module Adapters
3
+ class RedisCache
4
+ attr_accessor :redis
5
+
6
+ def initialize redis, options={}
7
+ if redis.is_a?(Hash)
8
+ options = redis
9
+ redis = nil
10
+ end
11
+
12
+ @redis = redis || Redis.new(options)
13
+ end
14
+
15
+ def get key
16
+ redis.get(key)
17
+ end
18
+
19
+ def write key, value
20
+ redis.set(key, value)
21
+ value
22
+ end
23
+
24
+ def fetch key
25
+ result = get(key)
26
+
27
+ if result.nil? and block_given?
28
+ fallback = yield
29
+ result = write(key, fallback)
30
+ end
31
+
32
+ result
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,56 @@
1
+ module Smooth
2
+ module Backends
3
+ class ActiveRecord < Base
4
+
5
+ attr_accessor :model
6
+
7
+ def initialize options={}
8
+ super
9
+ if @model = options[:model]
10
+ model.send(:include, Smooth::Backends::ActiveRecord::QueryAdapter)
11
+ end
12
+ end
13
+
14
+ def query params={}
15
+ model.respond_to?(:query) ? model.query(params) : model.smooth_query(params)
16
+ end
17
+
18
+ def index
19
+ model.scoped
20
+ end
21
+
22
+ def show id
23
+ model.find(id)
24
+ end
25
+
26
+ def update attributes
27
+ record = model.find(attributes[:id])
28
+ record.update_attributes(attributes)
29
+ record
30
+ end
31
+
32
+ def destroy id
33
+ !!(model = model.find(id) && model.destroy)
34
+ end
35
+
36
+ def create attributes
37
+ record = model.create(attributes)
38
+ end
39
+ end
40
+
41
+ module ActiveRecord::QueryAdapter
42
+
43
+ module ClassMethods
44
+ def smooth_query params={}
45
+ scoped
46
+ end
47
+ end
48
+
49
+ def self.included(receiver)
50
+ receiver.extend ClassMethods
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+ end