smooth 2.0.1

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 (95) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/Gemfile +10 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +24 -0
  7. data/app/assets/images/smooth/.keep +0 -0
  8. data/app/assets/javascripts/smooth/.keep +0 -0
  9. data/app/controllers/.keep +0 -0
  10. data/app/helpers/.keep +0 -0
  11. data/app/mailers/.keep +0 -0
  12. data/app/models/.keep +0 -0
  13. data/app/views/.keep +0 -0
  14. data/config/routes.rb +2 -0
  15. data/lib/smooth.rb +64 -0
  16. data/lib/smooth/api.rb +72 -0
  17. data/lib/smooth/api/policy.rb +18 -0
  18. data/lib/smooth/api/tracking.rb +31 -0
  19. data/lib/smooth/cache.rb +19 -0
  20. data/lib/smooth/command.rb +55 -0
  21. data/lib/smooth/command/instrumented.rb +51 -0
  22. data/lib/smooth/configuration.rb +25 -0
  23. data/lib/smooth/documentation.rb +31 -0
  24. data/lib/smooth/dsl.rb +36 -0
  25. data/lib/smooth/event.rb +27 -0
  26. data/lib/smooth/example.rb +6 -0
  27. data/lib/smooth/ext/core.rb +5 -0
  28. data/lib/smooth/ext/mutations.rb +1 -0
  29. data/lib/smooth/query.rb +62 -0
  30. data/lib/smooth/resource.rb +173 -0
  31. data/lib/smooth/resource/tracking.rb +17 -0
  32. data/lib/smooth/serializer.rb +94 -0
  33. data/lib/smooth/version.rb +3 -0
  34. data/smooth.gemspec +36 -0
  35. data/spec/dummy/README.rdoc +28 -0
  36. data/spec/dummy/Rakefile +6 -0
  37. data/spec/dummy/app/apis/application_api.rb +34 -0
  38. data/spec/dummy/app/assets/images/.keep +0 -0
  39. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  40. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  41. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  42. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  43. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  44. data/spec/dummy/app/mailers/.keep +0 -0
  45. data/spec/dummy/app/models/.keep +0 -0
  46. data/spec/dummy/app/models/author.rb +2 -0
  47. data/spec/dummy/app/models/book.rb +2 -0
  48. data/spec/dummy/app/models/concerns/.keep +0 -0
  49. data/spec/dummy/app/resources/books.rb +103 -0
  50. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  51. data/spec/dummy/bin/bundle +3 -0
  52. data/spec/dummy/bin/rails +4 -0
  53. data/spec/dummy/bin/rake +4 -0
  54. data/spec/dummy/config.ru +4 -0
  55. data/spec/dummy/config/application.rb +30 -0
  56. data/spec/dummy/config/boot.rb +5 -0
  57. data/spec/dummy/config/database.yml +25 -0
  58. data/spec/dummy/config/environment.rb +5 -0
  59. data/spec/dummy/config/environments/development.rb +37 -0
  60. data/spec/dummy/config/environments/production.rb +82 -0
  61. data/spec/dummy/config/environments/test.rb +39 -0
  62. data/spec/dummy/config/initializers/assets.rb +8 -0
  63. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  64. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  65. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  66. data/spec/dummy/config/initializers/inflections.rb +16 -0
  67. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  68. data/spec/dummy/config/initializers/session_store.rb +3 -0
  69. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  70. data/spec/dummy/config/locales/en.yml +23 -0
  71. data/spec/dummy/config/routes.rb +3 -0
  72. data/spec/dummy/config/secrets.yml +22 -0
  73. data/spec/dummy/db/development.sqlite3 +0 -0
  74. data/spec/dummy/db/migrate/20140822065900_create_books.rb +11 -0
  75. data/spec/dummy/db/migrate/20140822065916_create_authors.rb +9 -0
  76. data/spec/dummy/db/schema.rb +30 -0
  77. data/spec/dummy/db/test.sqlite3 +0 -0
  78. data/spec/dummy/lib/assets/.keep +0 -0
  79. data/spec/dummy/log/.keep +0 -0
  80. data/spec/dummy/public/404.html +67 -0
  81. data/spec/dummy/public/422.html +67 -0
  82. data/spec/dummy/public/500.html +66 -0
  83. data/spec/dummy/public/favicon.ico +0 -0
  84. data/spec/lib/smooth/api/policy_spec.rb +5 -0
  85. data/spec/lib/smooth/api_spec.rb +23 -0
  86. data/spec/lib/smooth/cache_spec.rb +8 -0
  87. data/spec/lib/smooth/command_spec.rb +36 -0
  88. data/spec/lib/smooth/configuration_spec.rb +16 -0
  89. data/spec/lib/smooth/event_spec.rb +20 -0
  90. data/spec/lib/smooth/example_spec.rb +5 -0
  91. data/spec/lib/smooth/query_spec.rb +5 -0
  92. data/spec/lib/smooth/resource_spec.rb +38 -0
  93. data/spec/lib/smooth/serializer_spec.rb +26 -0
  94. data/spec/spec_helper.rb +18 -0
  95. metadata +394 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4909a00991f205fc93b1ed479717c74635f3bef5
4
+ data.tar.gz: 3dbf7cda0d581469b22a297f6a0e8b9022e76583
5
+ SHA512:
6
+ metadata.gz: b8026b76b623987b8428fce674926a2b1a7e171d87eb86ec4c0321b481d6223205d0f9d9be5c393453534e61937446211ac1b59ddf3257c86985ff5b336d891c
7
+ data.tar.gz: ade1e5f9874ea6e897ff152964d29ea4b1bea9837d8b313ad5adc66bd155ae90607a649c7a9b6debf6c892a12740a934bdbbe2d18e7868d4b293db344249f911
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ log/*.log
19
+ spec/dummy/log/*.log
20
+ spec/dummy/tmp/**/*
21
+ .vimrc
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in smooth.gemspec
4
+ gemspec
5
+
6
+ group :test, :development do
7
+ gem 'pry'
8
+ gem 'pry-nav'
9
+ gem 'mutations', github: "datapimp/mutations", branch: "inline-documentation"
10
+ end
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Jonathan Soeder
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.
@@ -0,0 +1,29 @@
1
+ # Smooth
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'smooth'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install smooth
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,24 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ #!/usr/bin/env rake
4
+ begin
5
+ require 'bundler/setup'
6
+ rescue LoadError
7
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
8
+ end
9
+
10
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
11
+ load 'rails/tasks/engine.rake'
12
+
13
+ Bundler::GemHelper.install_tasks
14
+
15
+ Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each {|f| load f }
16
+
17
+ require 'rspec/core'
18
+ require 'rspec/core/rake_task'
19
+
20
+ desc "Run all specs in spec directory (excluding plugin specs)"
21
+
22
+ RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
23
+
24
+ task :default => :spec
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,2 @@
1
+ Rails.application.routes.draw do
2
+ end
@@ -0,0 +1,64 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ begin
4
+ require 'hashie'
5
+ require 'active_support/core_ext'
6
+ require 'active_support/notifications'
7
+ require 'active_model_serializers'
8
+ require 'mutations'
9
+ require 'pry'
10
+ rescue LoadError
11
+ require 'rubygems'
12
+ require 'hashie'
13
+ require 'active_support/core_ext'
14
+ require 'pry'
15
+ end
16
+
17
+
18
+ require "smooth/ext/core"
19
+ require "smooth/documentation"
20
+ require "smooth/event"
21
+
22
+ require "smooth/api"
23
+ require "smooth/cache"
24
+ require "smooth/command"
25
+ require "smooth/example"
26
+ require "smooth/query"
27
+ require "smooth/resource"
28
+ require "smooth/serializer"
29
+
30
+ require "smooth/configuration"
31
+ require "smooth/version"
32
+
33
+ module Smooth
34
+ extend Smooth::Api::Tracking
35
+ extend Smooth::Resource::Tracking
36
+ extend Smooth::Event::Adapter
37
+
38
+ def self.command
39
+ config.command_class
40
+ end
41
+
42
+ def self.query
43
+ config.query_class
44
+ end
45
+
46
+ def self.serializer
47
+ config.serializer_class
48
+ end
49
+
50
+ def self.config
51
+ Smooth::Configuration.instance
52
+ end
53
+
54
+ class Engine < ::Rails::Engine
55
+ initializer 'smooth.load_resources', :before => :build_middleware_stack do |app|
56
+ app_root = app.config.root.join("app")
57
+
58
+ %w{smooth apis resources}.each do |check_folder|
59
+ app_root.join(check_folder).children.each {|f| require(f) } if app_root.join(check_folder).exist?
60
+ end
61
+ end
62
+
63
+ end if defined?(::Rails)
64
+ end
@@ -0,0 +1,72 @@
1
+ require 'smooth/dsl'
2
+
3
+ module Smooth
4
+ class Api
5
+ include Smooth::Documentation
6
+
7
+ def self.default
8
+ @default ||= Smooth::Api.new
9
+ end
10
+
11
+ attr_accessor :name,
12
+ :_version_config,
13
+ :_resources,
14
+ :_policies
15
+
16
+ def initialize(name, options={})
17
+ @name = name
18
+ @options = options
19
+
20
+ @_resources = {}
21
+ @_policies = {}
22
+ end
23
+
24
+ def version config=nil
25
+ @_version_config = config if config
26
+ @_version_config
27
+ end
28
+
29
+ def policy policy_name, options={}, &block
30
+ if obj = _policies[policy_name.to_sym]
31
+ obj.apply_options(options) unless options.empty?
32
+ obj.instance_eval(&block) if block_given?
33
+ obj
34
+
35
+ elsif options.empty? && !block_given?
36
+ nil
37
+
38
+ elsif block_given?
39
+ obj = Smooth::Api::Policy.new(policy_name, options, &block)
40
+ _resources[policy_name.to_sym] = obj
41
+ end
42
+ end
43
+
44
+ def has_resource? resource_name
45
+ resources.has_key?(resource_name.to_sym)
46
+ end
47
+
48
+ def resource resource_name, options={}, &block
49
+ api_name = self.name
50
+
51
+ if existing = _resources[resource_name.to_sym]
52
+ existing.apply_options(options) unless options.empty?
53
+ existing.instance_eval(&block) if block_given?
54
+ existing
55
+
56
+ elsif options.empty? && !block_given?
57
+ existing = nil
58
+
59
+ elsif block_given?
60
+ created = Smooth::Resource.new(resource_name, options, &block).tap do |obj|
61
+ obj.api_name = api_name
62
+ end
63
+
64
+ _resources[resource_name.to_sym] = created
65
+ end
66
+ end
67
+
68
+ end
69
+ end
70
+
71
+ require 'smooth/api/tracking'
72
+ require 'smooth/api/policy'
@@ -0,0 +1,18 @@
1
+ module Smooth
2
+ class Api
3
+ class Policy
4
+ include Smooth::Documentation
5
+
6
+ attr_accessor :name
7
+
8
+ def initialize name, options={}
9
+ @name = name
10
+ @options = options
11
+ end
12
+
13
+ def apply_options *opts
14
+ @options.send(:merge!, *opts)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,31 @@
1
+ module Smooth
2
+ class Api
3
+ module Tracking
4
+ def apis
5
+ @@apis ||= {}
6
+ end
7
+
8
+ def fetch_api name, &block
9
+ existing = apis[name.to_sym]
10
+
11
+ if existing.nil? && block_given?
12
+ existing = apis[name.to_sym] = block.call(name.to_sym)
13
+ end
14
+
15
+ existing
16
+ end
17
+
18
+ def current_api
19
+ apis[current_api_name] ||= Smooth::Api.default()
20
+ end
21
+
22
+ def current_api_name= value
23
+ @@current_api_name = value
24
+ end
25
+
26
+ def current_api_name
27
+ (@@current_api_name || :default).to_sym
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ require 'singleton'
2
+
3
+ module Smooth
4
+ def self.cache
5
+ Smooth::Cache.instance
6
+ end
7
+
8
+ class Cache
9
+ include Singleton
10
+
11
+ def method_missing meth, *args, &block
12
+ if defined? ::Rails
13
+ return ::Rails.cache.send(meth, *args, &block)
14
+ end
15
+
16
+ super
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,55 @@
1
+ require 'smooth/ext/mutations'
2
+ require 'smooth/command/instrumented'
3
+
4
+ class Smooth::Command < Mutations::Command
5
+ include Instrumented
6
+
7
+ class_attribute :resource_name,
8
+ :command_action,
9
+ :event_namespace
10
+
11
+ def self.scope setting
12
+ @@scope = setting
13
+ end
14
+
15
+ def self.params *args, &block
16
+ send(:required, *args, &block)
17
+ end
18
+
19
+ def self.event_namespace
20
+ @event_namespace || "#{ command_action }.#{ resource_name.singularize.underscore }".downcase
21
+ end
22
+
23
+ def event_namespace; self.class.event_namespace; end
24
+
25
+ # DSL Hooks
26
+ #
27
+ #
28
+ def self.configure options, resource=nil
29
+ resource ||= Smooth.current_resource
30
+ klass = define_or_open(options, resource)
31
+
32
+ Array(options.blocks).each do |blk|
33
+ klass.class_eval(&blk)
34
+ end
35
+
36
+ klass
37
+ end
38
+
39
+ def self.define_or_open(options, resource)
40
+ resource_name = resource.name.to_s.singularize
41
+ base = Smooth.command
42
+
43
+ name = options.name.to_s.camelize
44
+ klass = "#{ name }#{ resource_name }"
45
+
46
+ if command_klass = Object.const_get(klass) rescue nil
47
+ return command_klass
48
+ end
49
+
50
+ Object.const_set(klass, Class.new(base)).tap do |k|
51
+ k.resource_name = resource.name.to_s
52
+ k.command_action = options.name.to_s
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,51 @@
1
+ module Smooth
2
+ class Command < Mutations::Command
3
+ module Instrumented
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ base.enable_event_tracking! # if Smooth.config.enable_event_tracking_by_default?
7
+ end
8
+
9
+ module Overrides
10
+ def run
11
+ run_with_instrumentation
12
+ end
13
+ end
14
+
15
+ module Restored
16
+ def run
17
+ run_with_outcome
18
+ end
19
+ end
20
+
21
+ module ClassMethods
22
+ def enable_event_tracking!
23
+ send(:include, Smooth::Event::Adapter)
24
+ send(:include, Overrides)
25
+ end
26
+
27
+ def disable_event_tracking!
28
+ send(:include, Restored)
29
+ end
30
+ end
31
+
32
+ def run_with_instrumentation
33
+ outcome = run_with_outcome
34
+
35
+ if outcome.success?
36
+ result = outcome.result
37
+ track_event("#{ event_namespace }", result: result, inputs: inputs)
38
+ result
39
+ else
40
+ track_event("errors/#{ event_namespace }", errors: outcome.errors, inputs: inputs)
41
+ outcome
42
+ end
43
+ end
44
+
45
+ def run_with_outcome
46
+ return validation_outcome if has_errors?
47
+ validation_outcome(execute)
48
+ end
49
+ end
50
+ end
51
+ end