├── .gitignore ├── .ruby-version ├── .travis.yml ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── Procfile ├── README.md ├── Rakefile ├── bin ├── bundle ├── rails └── rake ├── build.sh ├── components ├── documentation │ ├── .rspec │ ├── Gemfile │ ├── Gemfile.lock │ ├── Rakefile │ ├── app │ │ ├── assets │ │ │ └── stylesheets │ │ │ │ └── documentation │ │ │ │ └── application.css │ │ ├── controllers │ │ │ └── documentation │ │ │ │ └── root_controller.rb │ │ └── views │ │ │ ├── documentation │ │ │ └── root │ │ │ │ └── index.html.erb │ │ │ └── layouts │ │ │ └── documentation │ │ │ └── application.html.erb │ ├── config │ │ └── routes.rb │ ├── documentation.gemspec │ ├── lib │ │ ├── documentation.rb │ │ └── documentation │ │ │ ├── engine.rb │ │ │ └── version.rb │ ├── spec │ │ ├── dummy │ │ │ ├── Rakefile │ │ │ ├── bin │ │ │ │ ├── bundle │ │ │ │ ├── rails │ │ │ │ ├── rake │ │ │ │ └── setup │ │ │ ├── config.ru │ │ │ ├── config │ │ │ │ ├── application.rb │ │ │ │ ├── boot.rb │ │ │ │ ├── database.yml │ │ │ │ ├── environment.rb │ │ │ │ ├── environments │ │ │ │ │ └── test.rb │ │ │ │ ├── routes.rb │ │ │ │ └── secrets.yml │ │ │ ├── db │ │ │ │ └── schema.rb │ │ │ └── log │ │ │ │ └── .keep │ │ ├── features │ │ │ └── root_page_spec.rb │ │ ├── rails_helper.rb │ │ ├── spec_helper.rb │ │ └── support │ │ │ └── capybara.rb │ └── test.sh └── movie_manager │ ├── .rspec │ ├── Gemfile │ ├── Gemfile.lock │ ├── Rakefile │ ├── app │ ├── controllers │ │ └── movie_manager │ │ │ └── movies_controller.rb │ └── models │ │ └── movie_manager │ │ ├── movie.rb │ │ ├── movie_repo.rb │ │ └── movie_serializer.rb │ ├── config │ └── routes.rb │ ├── db │ └── migrate │ │ ├── 20131215170206_create_movies.rb │ │ ├── 20140128061928_add_director_to_movies.rb │ │ └── 20141206230010_add_timestamps_to_movies.rb │ ├── lib │ ├── movie_manager.rb │ └── movie_manager │ │ ├── engine.rb │ │ └── version.rb │ ├── movie_manager.gemspec │ ├── spec │ ├── dummy │ │ ├── Rakefile │ │ ├── bin │ │ │ ├── bundle │ │ │ ├── rails │ │ │ ├── rake │ │ │ └── setup │ │ ├── config.ru │ │ ├── config │ │ │ ├── application.rb │ │ │ ├── boot.rb │ │ │ ├── database.yml │ │ │ ├── environment.rb │ │ │ ├── environments │ │ │ │ └── test.rb │ │ │ ├── routes.rb │ │ │ └── secrets.yml │ │ └── db │ │ │ └── schema.rb │ ├── models │ │ └── movie_manager │ │ │ └── movie_repo_spec.rb │ ├── rails_helper.rb │ ├── requests │ │ └── movies_api_spec.rb │ ├── spec_helper.rb │ └── support │ │ └── object_creation_methods.rb │ └── test.sh ├── config.ru ├── config ├── application.rb ├── boot.rb ├── database.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── secret_token.rb │ └── wrap_parameters.rb └── routes.rb ├── db ├── schema.rb └── seeds.rb └── deploy_app.sh /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle 2 | *.log 3 | tmp 4 | /.vagrant 5 | /public/assets 6 | /.env 7 | .idea 8 | 9 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.2.2 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | gemfile: 3 | - components/documentation/Gemfile 4 | - components/movie_manager/Gemfile 5 | script: 6 | - travis_retry ./test.sh 7 | before_install: 8 | - cd $(dirname $BUNDLE_GEMFILE) 9 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | ruby "2.2.2" 4 | 5 | gem "documentation", path: "components/documentation" 6 | gem "movie_manager", path: "components/movie_manager" 7 | 8 | gem "pg" 9 | gem "rack-cors", :require => "rack/cors" 10 | gem "pry-rails" 11 | 12 | group :production do 13 | gem "rails_12factor" 14 | end 15 | 16 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: components/documentation 3 | specs: 4 | documentation (0.0.1) 5 | rails (= 4.1.5) 6 | 7 | PATH 8 | remote: components/movie_manager 9 | specs: 10 | movie_manager (0.0.1) 11 | oj 12 | rails (= 4.1.5) 13 | thin 14 | 15 | GEM 16 | remote: https://rubygems.org/ 17 | specs: 18 | actionmailer (4.1.5) 19 | actionpack (= 4.1.5) 20 | actionview (= 4.1.5) 21 | mail (~> 2.5.4) 22 | actionpack (4.1.5) 23 | actionview (= 4.1.5) 24 | activesupport (= 4.1.5) 25 | rack (~> 1.5.2) 26 | rack-test (~> 0.6.2) 27 | actionview (4.1.5) 28 | activesupport (= 4.1.5) 29 | builder (~> 3.1) 30 | erubis (~> 2.7.0) 31 | activemodel (4.1.5) 32 | activesupport (= 4.1.5) 33 | builder (~> 3.1) 34 | activerecord (4.1.5) 35 | activemodel (= 4.1.5) 36 | activesupport (= 4.1.5) 37 | arel (~> 5.0.0) 38 | activesupport (4.1.5) 39 | i18n (~> 0.6, >= 0.6.9) 40 | json (~> 1.7, >= 1.7.7) 41 | minitest (~> 5.1) 42 | thread_safe (~> 0.1) 43 | tzinfo (~> 1.1) 44 | arel (5.0.1.20140414130214) 45 | builder (3.2.2) 46 | coderay (1.1.0) 47 | daemons (1.1.9) 48 | erubis (2.7.0) 49 | eventmachine (1.0.4) 50 | hike (1.2.3) 51 | i18n (0.7.0) 52 | json (1.8.1) 53 | mail (2.5.4) 54 | mime-types (~> 1.16) 55 | treetop (~> 1.4.8) 56 | method_source (0.8.2) 57 | mime-types (1.25.1) 58 | minitest (5.5.0) 59 | multi_json (1.10.1) 60 | oj (2.11.4) 61 | pg (0.17.1) 62 | polyglot (0.3.5) 63 | pry (0.10.1) 64 | coderay (~> 1.1.0) 65 | method_source (~> 0.8.1) 66 | slop (~> 3.4) 67 | pry-rails (0.3.3) 68 | pry (>= 0.9.10) 69 | rack (1.5.2) 70 | rack-cors (0.3.1) 71 | rack-test (0.6.2) 72 | rack (>= 1.0) 73 | rails (4.1.5) 74 | actionmailer (= 4.1.5) 75 | actionpack (= 4.1.5) 76 | actionview (= 4.1.5) 77 | activemodel (= 4.1.5) 78 | activerecord (= 4.1.5) 79 | activesupport (= 4.1.5) 80 | bundler (>= 1.3.0, < 2.0) 81 | railties (= 4.1.5) 82 | sprockets-rails (~> 2.0) 83 | rails_12factor (0.0.3) 84 | rails_serve_static_assets 85 | rails_stdout_logging 86 | rails_serve_static_assets (0.0.4) 87 | rails_stdout_logging (0.0.3) 88 | railties (4.1.5) 89 | actionpack (= 4.1.5) 90 | activesupport (= 4.1.5) 91 | rake (>= 0.8.7) 92 | thor (>= 0.18.1, < 2.0) 93 | rake (10.4.2) 94 | slop (3.6.0) 95 | sprockets (2.12.3) 96 | hike (~> 1.2) 97 | multi_json (~> 1.0) 98 | rack (~> 1.0) 99 | tilt (~> 1.1, != 1.3.0) 100 | sprockets-rails (2.2.2) 101 | actionpack (>= 3.0) 102 | activesupport (>= 3.0) 103 | sprockets (>= 2.8, < 4.0) 104 | thin (1.6.3) 105 | daemons (~> 1.0, >= 1.0.9) 106 | eventmachine (~> 1.0) 107 | rack (~> 1.0) 108 | thor (0.19.1) 109 | thread_safe (0.3.4) 110 | tilt (1.4.1) 111 | treetop (1.4.15) 112 | polyglot 113 | polyglot (>= 0.3.1) 114 | tzinfo (1.2.2) 115 | thread_safe (~> 0.1) 116 | 117 | PLATFORMS 118 | ruby 119 | 120 | DEPENDENCIES 121 | documentation! 122 | movie_manager! 123 | pg 124 | pry-rails 125 | rack-cors 126 | rails_12factor 127 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 Eno Compton 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of 5 | this software and associated documentation files (the "Software"), to deal in 6 | the Software without restriction, including without limitation the rights to 7 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 8 | of the Software, and to permit persons to whom the Software is furnished to do 9 | so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: bundle exec rails server -p $PORT 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Json-Api 2 | 3 | A simple set of JSON RESTful endpoints using the repository pattern and Rails engines. 4 | 5 | ## About 6 | 7 | This app lives at [json-api.herokuapp.com](http://json-api.herokuapp.com) and responds to requests at `/api/movies`. 8 | 9 | There are two things which make this otherwise plain app interesting: 10 | 11 | 1. Any interaction with ActiveRecord is hidden behind a repository interface. I have written about the rationale of doing this [here](http://commandercoriander.net/blog/2014/10/02/isolating-active-record/). 12 | 2. The app uses engines and has no `app` folder in the top level. For some context on why this is valuable, see the talk by Stephan Hagemann, [Component-based Architectures in Ruby and Rails](https://www.youtube.com/watch?v=-54SDanDC00). If you prefer reading about the topic, there is also [a book](https://leanpub.com/cbra). 13 | 14 | For an introduction to how this app's API was written, see the post [here](http://commandercoriander.net/blog/2014/01/04/test-driving-a-json-api-in-rails/). 15 | 16 | If you would like to practice using `curl` while interacting with the app, see the post [here](http://commandercoriander.net/blog/2014/01/11/curling-with-rails/). 17 | 18 | ## JavaScript Clients 19 | 20 | See [here](https://github.com/enocom/angular_client) for an AngularJS client. 21 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require File.expand_path('../config/application', __FILE__) 2 | 3 | JsonRails::Application.load_tasks 4 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../../config/application', __FILE__) 3 | require_relative '../config/boot' 4 | require 'rails/commands' 5 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | result=0 4 | 5 | for test_script in $(find . -name test.sh); do 6 | pushd `dirname $test_script` > /dev/null 7 | ./test.sh 8 | result+=$? 9 | popd > /dev/null 10 | done 11 | 12 | if [ $result -eq 0 ]; then 13 | echo "SUCCESS" 14 | else 15 | echo "FAILURE" 16 | fi 17 | 18 | exit $result 19 | -------------------------------------------------------------------------------- /components/documentation/.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | -------------------------------------------------------------------------------- /components/documentation/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec 4 | -------------------------------------------------------------------------------- /components/documentation/Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | documentation (0.0.1) 5 | rails (= 4.1.5) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionmailer (4.1.5) 11 | actionpack (= 4.1.5) 12 | actionview (= 4.1.5) 13 | mail (~> 2.5.4) 14 | actionpack (4.1.5) 15 | actionview (= 4.1.5) 16 | activesupport (= 4.1.5) 17 | rack (~> 1.5.2) 18 | rack-test (~> 0.6.2) 19 | actionview (4.1.5) 20 | activesupport (= 4.1.5) 21 | builder (~> 3.1) 22 | erubis (~> 2.7.0) 23 | activemodel (4.1.5) 24 | activesupport (= 4.1.5) 25 | builder (~> 3.1) 26 | activerecord (4.1.5) 27 | activemodel (= 4.1.5) 28 | activesupport (= 4.1.5) 29 | arel (~> 5.0.0) 30 | activesupport (4.1.5) 31 | i18n (~> 0.6, >= 0.6.9) 32 | json (~> 1.7, >= 1.7.7) 33 | minitest (~> 5.1) 34 | thread_safe (~> 0.1) 35 | tzinfo (~> 1.1) 36 | arel (5.0.1.20140414130214) 37 | builder (3.2.2) 38 | capybara (2.4.4) 39 | mime-types (>= 1.16) 40 | nokogiri (>= 1.3.3) 41 | rack (>= 1.0.0) 42 | rack-test (>= 0.5.4) 43 | xpath (~> 2.0) 44 | cliver (0.3.2) 45 | diff-lcs (1.2.5) 46 | erubis (2.7.0) 47 | i18n (0.7.0) 48 | json (1.8.2) 49 | mail (2.5.4) 50 | mime-types (~> 1.16) 51 | treetop (~> 1.4.8) 52 | mime-types (1.25.1) 53 | mini_portile (0.6.2) 54 | minitest (5.6.1) 55 | multi_json (1.10.1) 56 | nokogiri (1.6.6.2) 57 | mini_portile (~> 0.6.0) 58 | pg (0.18.1) 59 | poltergeist (1.5.1) 60 | capybara (~> 2.1) 61 | cliver (~> 0.3.1) 62 | multi_json (~> 1.0) 63 | websocket-driver (>= 0.2.0) 64 | polyglot (0.3.5) 65 | rack (1.5.3) 66 | rack-test (0.6.3) 67 | rack (>= 1.0) 68 | rails (4.1.5) 69 | actionmailer (= 4.1.5) 70 | actionpack (= 4.1.5) 71 | actionview (= 4.1.5) 72 | activemodel (= 4.1.5) 73 | activerecord (= 4.1.5) 74 | activesupport (= 4.1.5) 75 | bundler (>= 1.3.0, < 2.0) 76 | railties (= 4.1.5) 77 | sprockets-rails (~> 2.0) 78 | railties (4.1.5) 79 | actionpack (= 4.1.5) 80 | activesupport (= 4.1.5) 81 | rake (>= 0.8.7) 82 | thor (>= 0.18.1, < 2.0) 83 | rake (10.4.2) 84 | rspec-core (3.1.7) 85 | rspec-support (~> 3.1.0) 86 | rspec-expectations (3.1.2) 87 | diff-lcs (>= 1.2.0, < 2.0) 88 | rspec-support (~> 3.1.0) 89 | rspec-mocks (3.1.3) 90 | rspec-support (~> 3.1.0) 91 | rspec-rails (3.1.0) 92 | actionpack (>= 3.0) 93 | activesupport (>= 3.0) 94 | railties (>= 3.0) 95 | rspec-core (~> 3.1.0) 96 | rspec-expectations (~> 3.1.0) 97 | rspec-mocks (~> 3.1.0) 98 | rspec-support (~> 3.1.0) 99 | rspec-support (3.1.2) 100 | sprockets (3.1.0) 101 | rack (~> 1.0) 102 | sprockets-rails (2.3.1) 103 | actionpack (>= 3.0) 104 | activesupport (>= 3.0) 105 | sprockets (>= 2.8, < 4.0) 106 | thor (0.19.1) 107 | thread_safe (0.3.5) 108 | treetop (1.4.15) 109 | polyglot 110 | polyglot (>= 0.3.1) 111 | tzinfo (1.2.2) 112 | thread_safe (~> 0.1) 113 | websocket-driver (0.5.1) 114 | websocket-extensions (>= 0.1.0) 115 | websocket-extensions (0.1.1) 116 | xpath (2.0.0) 117 | nokogiri (~> 1.3) 118 | 119 | PLATFORMS 120 | ruby 121 | 122 | DEPENDENCIES 123 | capybara 124 | documentation! 125 | pg 126 | poltergeist 127 | rspec-rails 128 | -------------------------------------------------------------------------------- /components/documentation/Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | begin 3 | require "bundler/setup" 4 | rescue LoadError 5 | puts "You must `gem install bundler` and `bundle install` to run rake tasks" 6 | end 7 | 8 | APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__) 9 | load "rails/tasks/engine.rake" 10 | 11 | Bundler::GemHelper.install_tasks 12 | -------------------------------------------------------------------------------- /components/documentation/app/assets/stylesheets/documentation/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | *= require_self 3 | */ 4 | .page { 5 | text-align: center; 6 | border: 1px solid black; 7 | width: 400px; 8 | margin: 0 auto; 9 | background: white; 10 | } 11 | 12 | body { 13 | background: grey; 14 | width: 100%; 15 | } 16 | -------------------------------------------------------------------------------- /components/documentation/app/controllers/documentation/root_controller.rb: -------------------------------------------------------------------------------- 1 | module Documentation 2 | class RootController < ActionController::Base 3 | def index 4 | render layout: "documentation/application" 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /components/documentation/app/views/documentation/root/index.html.erb: -------------------------------------------------------------------------------- 1 |

json-api.rocks

2 | 3 |

JSON Endpoints

4 | 5 |
6 |
GET /api/movies
7 |
POST /api/movies
8 |
GET /api/movies/:id
9 |
PUT /api/movies/:id
10 |
DELETE /api/movies/:id
11 |
12 | 13 |
14 |

Psst...

15 |
Accept: application/json
16 |
Content-Type: application/json
17 |
18 | 19 |

Read about the API here.

20 | 21 | -------------------------------------------------------------------------------- /components/documentation/app/views/layouts/documentation/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | json-api.rocks 7 | <%= stylesheet_link_tag "documentation/application", media: "all" %> 8 | 9 | 10 | 11 |
12 | <%= yield %> 13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /components/documentation/config/routes.rb: -------------------------------------------------------------------------------- 1 | Documentation::Engine.routes.draw do 2 | root to: "root#index" 3 | end 4 | -------------------------------------------------------------------------------- /components/documentation/documentation.gemspec: -------------------------------------------------------------------------------- 1 | $:.push(File.expand_path("../lib", __FILE__)) 2 | 3 | require "documentation/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "documentation" 7 | s.version = Documentation::VERSION 8 | s.files = Dir["{app,config,lib}/**/*"] 9 | 10 | s.add_dependency "rails", "4.1.5" 11 | 12 | s.add_development_dependency "rspec-rails" 13 | s.add_development_dependency "capybara" 14 | s.add_development_dependency "poltergeist" 15 | s.add_development_dependency "pg" 16 | end 17 | 18 | -------------------------------------------------------------------------------- /components/documentation/lib/documentation.rb: -------------------------------------------------------------------------------- 1 | require "documentation/engine" 2 | 3 | module Documentation 4 | end 5 | -------------------------------------------------------------------------------- /components/documentation/lib/documentation/engine.rb: -------------------------------------------------------------------------------- 1 | module Documentation 2 | class Engine < ::Rails::Engine 3 | isolate_namespace Documentation 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /components/documentation/lib/documentation/version.rb: -------------------------------------------------------------------------------- 1 | module Documentation 2 | VERSION = "0.0.1" 3 | end 4 | -------------------------------------------------------------------------------- /components/documentation/spec/dummy/Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('../config/application', __FILE__) 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /components/documentation/spec/dummy/bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /components/documentation/spec/dummy/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../../config/application', __FILE__) 3 | require_relative '../config/boot' 4 | require 'rails/commands' 5 | -------------------------------------------------------------------------------- /components/documentation/spec/dummy/bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /components/documentation/spec/dummy/bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'pathname' 3 | 4 | # path to your application root. 5 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) 6 | 7 | Dir.chdir APP_ROOT do 8 | # This script is a starting point to setup your application. 9 | # Add necessary setup steps to this file: 10 | 11 | puts "== Installing dependencies ==" 12 | system "gem install bundler --conservative" 13 | system "bundle check || bundle install" 14 | 15 | # puts "\n== Copying sample files ==" 16 | # unless File.exist?("config/database.yml") 17 | # system "cp config/database.yml.sample config/database.yml" 18 | # end 19 | 20 | puts "\n== Preparing database ==" 21 | system "bin/rake db:setup" 22 | 23 | puts "\n== Removing old logs and tempfiles ==" 24 | system "rm -f log/*" 25 | system "rm -rf tmp/cache" 26 | 27 | puts "\n== Restarting application server ==" 28 | system "touch tmp/restart.txt" 29 | end 30 | -------------------------------------------------------------------------------- /components/documentation/spec/dummy/config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run Rails.application 5 | -------------------------------------------------------------------------------- /components/documentation/spec/dummy/config/application.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../boot', __FILE__) 2 | 3 | require "active_record/railtie" 4 | require "action_controller/railtie" 5 | require "action_mailer/railtie" 6 | require "action_view/railtie" 7 | require "sprockets/railtie" 8 | 9 | Bundler.require(*Rails.groups) 10 | require "documentation" 11 | 12 | module Dummy 13 | class Application < Rails::Application 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /components/documentation/spec/dummy/config/boot.rb: -------------------------------------------------------------------------------- 1 | # Set up gems listed in the Gemfile. 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__) 3 | 4 | require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) 5 | $LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__) 6 | -------------------------------------------------------------------------------- /components/documentation/spec/dummy/config/database.yml: -------------------------------------------------------------------------------- 1 | test: 2 | adapter: postgresql 3 | encoding: unicode 4 | pool: 5 5 | database: documentation_dummy_test 6 | -------------------------------------------------------------------------------- /components/documentation/spec/dummy/config/environment.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../application', __FILE__) 2 | 3 | Rails.application.initialize! 4 | -------------------------------------------------------------------------------- /components/documentation/spec/dummy/config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # The test environment is used exclusively to run your application's 5 | # test suite. You never need to work with it otherwise. Remember that 6 | # your test database is "scratch space" for the test suite and is wiped 7 | # and recreated between test runs. Don't rely on the data there! 8 | config.cache_classes = true 9 | 10 | # Do not eager load code on boot. This avoids loading your whole application 11 | # just for the purpose of running a single test. If you are using a tool that 12 | # preloads Rails for running tests, you may have to set it to true. 13 | config.eager_load = false 14 | 15 | # Configure static file server for tests with Cache-Control for performance. 16 | config.serve_static_files = true 17 | config.static_cache_control = 'public, max-age=3600' 18 | 19 | # Show full error reports and disable caching. 20 | config.consider_all_requests_local = true 21 | config.action_controller.perform_caching = false 22 | 23 | # Raise exceptions instead of rendering exception templates. 24 | config.action_dispatch.show_exceptions = false 25 | 26 | # Disable request forgery protection in test environment. 27 | config.action_controller.allow_forgery_protection = false 28 | 29 | # Tell Action Mailer not to deliver emails to the real world. 30 | # The :test delivery method accumulates sent emails in the 31 | # ActionMailer::Base.deliveries array. 32 | config.action_mailer.delivery_method = :test 33 | 34 | # Randomize the order test cases are executed. 35 | config.active_support.test_order = :random 36 | 37 | # Print deprecation notices to the stderr. 38 | config.active_support.deprecation = :stderr 39 | 40 | # Raises error for missing translations 41 | # config.action_view.raise_on_missing_translations = true 42 | end 43 | -------------------------------------------------------------------------------- /components/documentation/spec/dummy/config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | mount Documentation::Engine => "/" 3 | end 4 | -------------------------------------------------------------------------------- /components/documentation/spec/dummy/config/secrets.yml: -------------------------------------------------------------------------------- 1 | test: 2 | secret_key_base: d59ea66b1b8771507c639379f16ec1a9609faeddfc79489e38ac19a27c05d2902df5794d895736c88091b0741937075712eb43b197e048433342a5fda960bd7c 3 | -------------------------------------------------------------------------------- /components/documentation/spec/dummy/db/schema.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | # This file is auto-generated from the current state of the database. Instead 3 | # of editing this file, please use the migrations feature of Active Record to 4 | # incrementally modify your database, and then regenerate this schema definition. 5 | # 6 | # Note that this schema.rb definition is the authoritative source for your 7 | # database schema. If you need to create the application database on another 8 | # system, you should be using db:schema:load, not running all the migrations 9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations 10 | # you'll amass, the slower it'll run and the greater likelihood for issues). 11 | # 12 | # It's strongly recommended that you check this file into your version control system. 13 | 14 | ActiveRecord::Schema.define(version: 0) do 15 | 16 | # These are extensions that must be enabled in order to support this database 17 | enable_extension "plpgsql" 18 | 19 | end 20 | -------------------------------------------------------------------------------- /components/documentation/spec/dummy/log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/enocom/json-api/63a6477635d3e3caa2015de6931a0835ffe2cb58/components/documentation/spec/dummy/log/.keep -------------------------------------------------------------------------------- /components/documentation/spec/features/root_page_spec.rb: -------------------------------------------------------------------------------- 1 | require "rails_helper" 2 | 3 | RSpec.describe "Root Page", type: :feature do 4 | specify "visiting the root page" do 5 | visit "/" 6 | 7 | expect(page).to have_content "json-api.rocks" 8 | expect(page).to have_content "JSON Endpoints" 9 | expect(page).to have_content "GET /api/movies" 10 | expect(page).to have_content "POST /api/movies" 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /components/documentation/spec/rails_helper.rb: -------------------------------------------------------------------------------- 1 | ENV["RAILS_ENV"] ||= "test" 2 | 3 | require File.expand_path("../dummy/config/environment", __FILE__) 4 | 5 | require "rspec/rails" 6 | 7 | Dir[Documentation::Engine.root.join("spec/support/**/*.rb")].each { |f| require f } 8 | 9 | ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration) 10 | 11 | RSpec.configure do |config| 12 | config.use_transactional_fixtures = true 13 | end 14 | -------------------------------------------------------------------------------- /components/documentation/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | RSpec.configure do |config| 2 | config.order = :random 3 | 4 | Kernel.srand config.seed 5 | 6 | config.expect_with :rspec do |expectations| 7 | expectations.syntax = :expect 8 | end 9 | 10 | config.mock_with :rspec do |mocks| 11 | mocks.syntax = :expect 12 | mocks.verify_partial_doubles = true 13 | end 14 | 15 | config.disable_monkey_patching! 16 | end 17 | -------------------------------------------------------------------------------- /components/documentation/spec/support/capybara.rb: -------------------------------------------------------------------------------- 1 | require "capybara/rspec" 2 | require "capybara/poltergeist" 3 | 4 | Capybara.javascript_driver = :poltergeist 5 | Capybara.ignore_hidden_elements = true 6 | -------------------------------------------------------------------------------- /components/documentation/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exit_code=0 4 | 5 | echo "*** Running documentation engine specs" 6 | bundle install | grep Installing 7 | RAILS_ENV=test bundle exec rake db:create 8 | RAILS_ENV=test bundle exec rake db:migrate 9 | bundle exec rspec spec 10 | exit_code+=$? 11 | 12 | exit $exit_code 13 | -------------------------------------------------------------------------------- /components/movie_manager/.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | -------------------------------------------------------------------------------- /components/movie_manager/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec 4 | -------------------------------------------------------------------------------- /components/movie_manager/Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | movie_manager (0.0.1) 5 | oj 6 | rails (= 4.1.5) 7 | thin 8 | 9 | GEM 10 | remote: https://rubygems.org/ 11 | specs: 12 | actionmailer (4.1.5) 13 | actionpack (= 4.1.5) 14 | actionview (= 4.1.5) 15 | mail (~> 2.5.4) 16 | actionpack (4.1.5) 17 | actionview (= 4.1.5) 18 | activesupport (= 4.1.5) 19 | rack (~> 1.5.2) 20 | rack-test (~> 0.6.2) 21 | actionview (4.1.5) 22 | activesupport (= 4.1.5) 23 | builder (~> 3.1) 24 | erubis (~> 2.7.0) 25 | activemodel (4.1.5) 26 | activesupport (= 4.1.5) 27 | builder (~> 3.1) 28 | activerecord (4.1.5) 29 | activemodel (= 4.1.5) 30 | activesupport (= 4.1.5) 31 | arel (~> 5.0.0) 32 | activesupport (4.1.5) 33 | i18n (~> 0.6, >= 0.6.9) 34 | json (~> 1.7, >= 1.7.7) 35 | minitest (~> 5.1) 36 | thread_safe (~> 0.1) 37 | tzinfo (~> 1.1) 38 | arel (5.0.1.20140414130214) 39 | builder (3.2.2) 40 | coderay (1.1.0) 41 | daemons (1.1.9) 42 | diff-lcs (1.2.5) 43 | erubis (2.7.0) 44 | eventmachine (1.0.4) 45 | i18n (0.7.0) 46 | json (1.8.2) 47 | mail (2.5.4) 48 | mime-types (~> 1.16) 49 | treetop (~> 1.4.8) 50 | method_source (0.8.2) 51 | mime-types (1.25.1) 52 | minitest (5.6.1) 53 | oj (2.11.4) 54 | pg (0.18.1) 55 | polyglot (0.3.5) 56 | pry (0.10.1) 57 | coderay (~> 1.1.0) 58 | method_source (~> 0.8.1) 59 | slop (~> 3.4) 60 | pry-rails (0.3.3) 61 | pry (>= 0.9.10) 62 | rack (1.5.3) 63 | rack-test (0.6.3) 64 | rack (>= 1.0) 65 | rails (4.1.5) 66 | actionmailer (= 4.1.5) 67 | actionpack (= 4.1.5) 68 | actionview (= 4.1.5) 69 | activemodel (= 4.1.5) 70 | activerecord (= 4.1.5) 71 | activesupport (= 4.1.5) 72 | bundler (>= 1.3.0, < 2.0) 73 | railties (= 4.1.5) 74 | sprockets-rails (~> 2.0) 75 | railties (4.1.5) 76 | actionpack (= 4.1.5) 77 | activesupport (= 4.1.5) 78 | rake (>= 0.8.7) 79 | thor (>= 0.18.1, < 2.0) 80 | rake (10.4.2) 81 | rspec-core (3.1.7) 82 | rspec-support (~> 3.1.0) 83 | rspec-expectations (3.1.2) 84 | diff-lcs (>= 1.2.0, < 2.0) 85 | rspec-support (~> 3.1.0) 86 | rspec-mocks (3.1.3) 87 | rspec-support (~> 3.1.0) 88 | rspec-rails (3.1.0) 89 | actionpack (>= 3.0) 90 | activesupport (>= 3.0) 91 | railties (>= 3.0) 92 | rspec-core (~> 3.1.0) 93 | rspec-expectations (~> 3.1.0) 94 | rspec-mocks (~> 3.1.0) 95 | rspec-support (~> 3.1.0) 96 | rspec-support (3.1.2) 97 | slop (3.6.0) 98 | sprockets (3.1.0) 99 | rack (~> 1.0) 100 | sprockets-rails (2.3.1) 101 | actionpack (>= 3.0) 102 | activesupport (>= 3.0) 103 | sprockets (>= 2.8, < 4.0) 104 | thin (1.6.3) 105 | daemons (~> 1.0, >= 1.0.9) 106 | eventmachine (~> 1.0) 107 | rack (~> 1.0) 108 | thor (0.19.1) 109 | thread_safe (0.3.5) 110 | treetop (1.4.15) 111 | polyglot 112 | polyglot (>= 0.3.1) 113 | tzinfo (1.2.2) 114 | thread_safe (~> 0.1) 115 | 116 | PLATFORMS 117 | ruby 118 | 119 | DEPENDENCIES 120 | movie_manager! 121 | pg 122 | pry-rails 123 | rspec-rails 124 | -------------------------------------------------------------------------------- /components/movie_manager/Rakefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | begin 3 | require "bundler/setup" 4 | rescue LoadError 5 | puts "You must `gem install bundler` and `bundle install` to run rake tasks" 6 | end 7 | 8 | APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__) 9 | load "rails/tasks/engine.rake" 10 | 11 | Bundler::GemHelper.install_tasks 12 | -------------------------------------------------------------------------------- /components/movie_manager/app/controllers/movie_manager/movies_controller.rb: -------------------------------------------------------------------------------- 1 | module MovieManager 2 | class MoviesController < ActionController::Base 3 | protect_from_forgery with: :null_session 4 | 5 | def index 6 | all_movies = MovieRepo.all.map do |movie| 7 | MovieSerializer.new(movie).as_json 8 | end 9 | 10 | render json: all_movies 11 | end 12 | 13 | def show 14 | movie = MovieRepo.find(params[:id]) 15 | 16 | if movie.present? 17 | render json: MovieSerializer.new(movie).as_json 18 | else 19 | render json: { errors: ["Movie not found"] }, status: :not_found 20 | end 21 | end 22 | 23 | def update 24 | movie = MovieRepo.find(params[:id]) 25 | updated_movie = MovieRepo.update(movie, movie_params) 26 | 27 | render json: MovieSerializer.new(updated_movie).as_json 28 | end 29 | 30 | def create 31 | persisted_movie = MovieRepo.persist( 32 | title: movie_params[:title], 33 | director: movie_params[:director] 34 | ) 35 | 36 | render json: MovieSerializer.new(persisted_movie).as_json, 37 | location: movie_path(persisted_movie.id), 38 | status: :created 39 | end 40 | 41 | def destroy 42 | movie = MovieRepo.find(params[:id]) 43 | 44 | MovieRepo.delete(movie) 45 | 46 | head :no_content 47 | end 48 | 49 | private 50 | 51 | def movie_params 52 | params.permit(:title, :director) 53 | end 54 | 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /components/movie_manager/app/models/movie_manager/movie.rb: -------------------------------------------------------------------------------- 1 | module MovieManager 2 | class Movie 3 | attr_reader :id, :title, :director 4 | 5 | def initialize(id, title, director) 6 | @id = id 7 | @title = title 8 | @director = director 9 | end 10 | 11 | def attributes 12 | { 13 | id: id, 14 | title: title, 15 | director: director 16 | } 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /components/movie_manager/app/models/movie_manager/movie_repo.rb: -------------------------------------------------------------------------------- 1 | module MovieManager 2 | class MovieRepo 3 | class PersistFailedError < StandardError 4 | end 5 | 6 | def self.all 7 | Movie.all.map { |m| build_movie(m) } 8 | end 9 | 10 | def self.find(movie_id) 11 | movie = Movie.find(movie_id) 12 | 13 | build_movie(movie) 14 | rescue ActiveRecord::RecordNotFound 15 | nil 16 | end 17 | 18 | def self.persist(movie_attrs) 19 | m = Movie.create!(movie_attrs) 20 | 21 | build_movie(m) 22 | rescue 23 | raise PersistFailedError 24 | end 25 | 26 | def self.update(movie, attrs) 27 | m = Movie.find(movie.id) 28 | m.update_attributes(attrs) 29 | build_movie(m) 30 | end 31 | 32 | def self.delete(movie) 33 | delete_count = Movie.delete(movie.id) 34 | delete_count == 1 35 | end 36 | 37 | private 38 | 39 | def self.build_movie(m) 40 | MovieManager::Movie.new(id = m.id, title = m.title, director = m.director) 41 | end 42 | 43 | class Movie < ActiveRecord::Base 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /components/movie_manager/app/models/movie_manager/movie_serializer.rb: -------------------------------------------------------------------------------- 1 | module MovieManager 2 | class MovieSerializer 3 | def initialize(movie) 4 | @movie = movie 5 | end 6 | 7 | def as_json(options = {}) 8 | { 9 | "id" => movie.id, 10 | "title" => movie.title, 11 | "director" => movie.director 12 | } 13 | end 14 | 15 | private 16 | 17 | attr_reader :movie 18 | end 19 | end 20 | 21 | -------------------------------------------------------------------------------- /components/movie_manager/config/routes.rb: -------------------------------------------------------------------------------- 1 | MovieManager::Engine.routes.draw do 2 | resources :movies, only: [:index, :show, :update, :create, :destroy] 3 | end 4 | -------------------------------------------------------------------------------- /components/movie_manager/db/migrate/20131215170206_create_movies.rb: -------------------------------------------------------------------------------- 1 | class CreateMovies < ActiveRecord::Migration 2 | def change 3 | create_table :movie_manager_movies do |t| 4 | t.string :title, null: false, unique: true 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /components/movie_manager/db/migrate/20140128061928_add_director_to_movies.rb: -------------------------------------------------------------------------------- 1 | class AddDirectorToMovies < ActiveRecord::Migration 2 | def change 3 | add_column :movie_manager_movies, :director, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /components/movie_manager/db/migrate/20141206230010_add_timestamps_to_movies.rb: -------------------------------------------------------------------------------- 1 | class AddTimestampsToMovies < ActiveRecord::Migration 2 | def change 3 | change_table :movie_manager_movies do |t| 4 | t.timestamps 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /components/movie_manager/lib/movie_manager.rb: -------------------------------------------------------------------------------- 1 | require "movie_manager/engine" 2 | require "pg" 3 | require "yaml" 4 | 5 | module MovieManager 6 | end 7 | -------------------------------------------------------------------------------- /components/movie_manager/lib/movie_manager/engine.rb: -------------------------------------------------------------------------------- 1 | module MovieManager 2 | class Engine < ::Rails::Engine 3 | isolate_namespace MovieManager 4 | 5 | initializer :append_migrations do |app| 6 | unless app.root.to_s.match root.to_s + File::SEPARATOR 7 | config.paths["db/migrate"].expanded.each do |path| 8 | app.config.paths["db/migrate"] << path 9 | end 10 | end 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /components/movie_manager/lib/movie_manager/version.rb: -------------------------------------------------------------------------------- 1 | module MovieManager 2 | VERSION = "0.0.1" 3 | end 4 | -------------------------------------------------------------------------------- /components/movie_manager/movie_manager.gemspec: -------------------------------------------------------------------------------- 1 | $:.push(File.expand_path("../lib", __FILE__)) 2 | 3 | require "movie_manager/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "movie_manager" 7 | s.version = MovieManager::VERSION 8 | s.files = Dir["{app,config,db,lib}/**/*"] 9 | 10 | s.add_dependency "oj" 11 | s.add_dependency "rails", "4.1.5" 12 | s.add_dependency "thin" 13 | 14 | s.add_development_dependency "pg" 15 | s.add_development_dependency "pry-rails" 16 | s.add_development_dependency "rspec-rails" 17 | end 18 | -------------------------------------------------------------------------------- /components/movie_manager/spec/dummy/Rakefile: -------------------------------------------------------------------------------- 1 | require File.expand_path("../config/application", __FILE__) 2 | 3 | Rails.application.load_tasks 4 | -------------------------------------------------------------------------------- /components/movie_manager/spec/dummy/bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /components/movie_manager/spec/dummy/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../../config/application', __FILE__) 3 | require_relative '../config/boot' 4 | require 'rails/commands' 5 | -------------------------------------------------------------------------------- /components/movie_manager/spec/dummy/bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /components/movie_manager/spec/dummy/bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'pathname' 3 | 4 | # path to your application root. 5 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) 6 | 7 | Dir.chdir APP_ROOT do 8 | # This script is a starting point to setup your application. 9 | # Add necessary setup steps to this file: 10 | 11 | puts "== Installing dependencies ==" 12 | system "gem install bundler --conservative" 13 | system "bundle check || bundle install" 14 | 15 | # puts "\n== Copying sample files ==" 16 | # unless File.exist?("config/database.yml") 17 | # system "cp config/database.yml.sample config/database.yml" 18 | # end 19 | 20 | puts "\n== Preparing database ==" 21 | system "bin/rake db:setup" 22 | 23 | puts "\n== Removing old logs and tempfiles ==" 24 | system "rm -f log/*" 25 | system "rm -rf tmp/cache" 26 | 27 | puts "\n== Restarting application server ==" 28 | system "touch tmp/restart.txt" 29 | end 30 | -------------------------------------------------------------------------------- /components/movie_manager/spec/dummy/config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run Rails.application 5 | -------------------------------------------------------------------------------- /components/movie_manager/spec/dummy/config/application.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path("../boot", __FILE__) 2 | 3 | require "active_record/railtie" 4 | require "action_controller/railtie" 5 | 6 | Bundler.require(*Rails.groups) 7 | require "movie_manager" 8 | 9 | module Dummy 10 | class Application < Rails::Application 11 | end 12 | end 13 | 14 | -------------------------------------------------------------------------------- /components/movie_manager/spec/dummy/config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../../Gemfile", __FILE__) 2 | 3 | require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) 4 | $LOAD_PATH.unshift(File.expand_path("../../../../lib", __FILE__)) 5 | -------------------------------------------------------------------------------- /components/movie_manager/spec/dummy/config/database.yml: -------------------------------------------------------------------------------- 1 | test: 2 | adapter: postgresql 3 | encoding: unicode 4 | pool: 5 5 | database: movie_manager_dummy_test 6 | -------------------------------------------------------------------------------- /components/movie_manager/spec/dummy/config/environment.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path("../application", __FILE__) 2 | 3 | Rails.application.initialize! 4 | -------------------------------------------------------------------------------- /components/movie_manager/spec/dummy/config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # The test environment is used exclusively to run your application's 5 | # test suite. You never need to work with it otherwise. Remember that 6 | # your test database is "scratch space" for the test suite and is wiped 7 | # and recreated between test runs. Don't rely on the data there! 8 | config.cache_classes = true 9 | 10 | # Do not eager load code on boot. This avoids loading your whole application 11 | # just for the purpose of running a single test. If you are using a tool that 12 | # preloads Rails for running tests, you may have to set it to true. 13 | config.eager_load = false 14 | 15 | # Configure static file server for tests with Cache-Control for performance. 16 | config.serve_static_files = true 17 | config.static_cache_control = 'public, max-age=3600' 18 | 19 | # Show full error reports and disable caching. 20 | config.consider_all_requests_local = true 21 | config.action_controller.perform_caching = false 22 | 23 | # Raise exceptions instead of rendering exception templates. 24 | config.action_dispatch.show_exceptions = false 25 | 26 | # Disable request forgery protection in test environment. 27 | config.action_controller.allow_forgery_protection = false 28 | 29 | # Randomize the order test cases are executed. 30 | config.active_support.test_order = :random 31 | 32 | # Print deprecation notices to the stderr. 33 | config.active_support.deprecation = :stderr 34 | 35 | # Raises error for missing translations 36 | # config.action_view.raise_on_missing_translations = true 37 | end 38 | -------------------------------------------------------------------------------- /components/movie_manager/spec/dummy/config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | mount MovieManager::Engine => "/" 3 | end 4 | -------------------------------------------------------------------------------- /components/movie_manager/spec/dummy/config/secrets.yml: -------------------------------------------------------------------------------- 1 | test: 2 | secret_key_base: d59ea66b1b8771507c639379f16ec1a9609faeddfc79489e38ac19a27c05d2902df5794d895736c88091b0741937075712eb43b197e048433342a5fda960bd7c 3 | -------------------------------------------------------------------------------- /components/movie_manager/spec/dummy/db/schema.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | # This file is auto-generated from the current state of the database. Instead 3 | # of editing this file, please use the migrations feature of Active Record to 4 | # incrementally modify your database, and then regenerate this schema definition. 5 | # 6 | # Note that this schema.rb definition is the authoritative source for your 7 | # database schema. If you need to create the application database on another 8 | # system, you should be using db:schema:load, not running all the migrations 9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations 10 | # you'll amass, the slower it'll run and the greater likelihood for issues). 11 | # 12 | # It's strongly recommended that you check this file into your version control system. 13 | 14 | ActiveRecord::Schema.define(version: 20141206230010) do 15 | 16 | # These are extensions that must be enabled in order to support this database 17 | enable_extension "plpgsql" 18 | 19 | create_table "movie_manager_movies", force: true do |t| 20 | t.string "title", null: false 21 | t.string "director" 22 | t.datetime "created_at" 23 | t.datetime "updated_at" 24 | end 25 | 26 | end 27 | -------------------------------------------------------------------------------- /components/movie_manager/spec/models/movie_manager/movie_repo_spec.rb: -------------------------------------------------------------------------------- 1 | require "rails_helper" 2 | 3 | module MovieManager 4 | RSpec.describe MovieRepo do 5 | describe "all movies" do 6 | it "returns all the persisted movies" do 7 | create_movie(title: "Foo", director: "Bar") 8 | 9 | result = MovieRepo.all 10 | 11 | expect(result.count).to eq 1 12 | expect(result.first.id).not_to be_nil 13 | expect(result.first.title).to eq "Foo" 14 | expect(result.first.director).to eq "Bar" 15 | end 16 | 17 | it "returns an empty collection when no movies exist" do 18 | expect(MovieRepo.all).to eq [] 19 | end 20 | 21 | it "returns value objects instead of Active Record objects" do 22 | create_movie(title: "Foo", director: "Bar") 23 | 24 | result = MovieRepo.all 25 | 26 | expect(result.first.is_a?(Movie)).to eq true 27 | expect(result.first.id).to be_present 28 | expect(result.first.title).to eq "Foo" 29 | expect(result.first.director).to eq "Bar" 30 | end 31 | end 32 | 33 | describe "querying movies" do 34 | it "finds movies based on an ID" do 35 | movie = create_movie(title: "Foo", director: "Bar") 36 | 37 | found_movie = MovieRepo.find(movie.id) 38 | 39 | expect(found_movie.id).to eq movie.id 40 | expect(found_movie.title).to eq "Foo" 41 | expect(found_movie.director).to eq "Bar" 42 | end 43 | 44 | it "returns nil when a movie is not found" do 45 | expect(MovieRepo.find(bogus_id = 123)).to be_nil 46 | end 47 | end 48 | 49 | describe "persisting movies" do 50 | it "stores movies in the database" do 51 | persisted_movie = MovieRepo.persist(title: "The Shining", 52 | director: "Stanley Kubrick") 53 | 54 | expect(persisted_movie.id).to be_present 55 | end 56 | 57 | it "returns value objects after persisting movie data" do 58 | persisted_movie = MovieRepo.persist(title: "The Shining", 59 | director: "Stanley Kubrick") 60 | 61 | expect(persisted_movie.is_a?(Movie)).to eq true 62 | end 63 | 64 | it "raises an error when persiting data fails" do 65 | allow(MovieRepo::Movie).to receive(:create!).and_raise 66 | 67 | expect { 68 | MovieRepo.persist(garbage: :data) 69 | }.to raise_error(MovieRepo::PersistFailedError) 70 | end 71 | end 72 | 73 | describe "updating movies" do 74 | it "updates a movie" do 75 | movie = create_movie(title: "Foo", director: "Bar") 76 | 77 | updated = MovieRepo.update(movie, title: "Oof", director: "Rab") 78 | 79 | expect(updated.id).to eq movie.id 80 | expect(updated.title).to eq "Oof" 81 | expect(updated.director).to eq "Rab" 82 | 83 | sanity_check = MovieRepo.find(updated.id) 84 | expect(sanity_check.id).to eq movie.id 85 | expect(sanity_check.title).to eq "Oof" 86 | expect(sanity_check.director).to eq "Rab" 87 | end 88 | 89 | it "accepts partial updates" do 90 | movie = create_movie(title: "Foo", director: "Bar") 91 | 92 | updated = MovieRepo.update(movie, title: "Oof") 93 | 94 | expect(updated.id).to eq movie.id 95 | expect(updated.title).to eq "Oof" 96 | expect(updated.director).to eq "Bar" 97 | end 98 | end 99 | 100 | describe "deleting movies" do 101 | it "deletes movies from the database" do 102 | movie = create_movie 103 | 104 | result = MovieRepo.delete(movie) 105 | 106 | expect(result).to eq true 107 | expect(MovieRepo.all).to eq [] 108 | end 109 | 110 | it "returns false when the delete fails" do 111 | FakeMovie = Struct.new(:id) 112 | 113 | result = MovieRepo.delete(FakeMovie.new(123)) 114 | 115 | expect(result).to eq false 116 | end 117 | end 118 | end 119 | end 120 | -------------------------------------------------------------------------------- /components/movie_manager/spec/rails_helper.rb: -------------------------------------------------------------------------------- 1 | ENV["RAILS_ENV"] ||= "test" 2 | require File.expand_path("../dummy/config/environment", __FILE__) 3 | require "rspec/rails" 4 | 5 | Dir[MovieManager::Engine.root.join("spec/support/**/*.rb")].each { |f| require f } 6 | 7 | ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration) 8 | 9 | RSpec.configure do |config| 10 | config.use_transactional_fixtures = true 11 | 12 | config.include ObjectCreationMethods 13 | end 14 | -------------------------------------------------------------------------------- /components/movie_manager/spec/requests/movies_api_spec.rb: -------------------------------------------------------------------------------- 1 | require "rails_helper" 2 | 3 | module MovieManager 4 | RSpec.describe "movies API", :type => :request do 5 | let(:accept_json) { {"Accept" => "application/json"} } 6 | let(:json_content_type) { {"Content-Type" => "application/json"} } 7 | let(:accept_and_return_json) { accept_json.merge(json_content_type) } 8 | 9 | describe "GET /movies" do 10 | before do 11 | create_movie( 12 | :title => "The Hobbit", 13 | :director => "Peter Jackson" 14 | ) 15 | create_movie( 16 | :title => "The Fellowship of the Ring", 17 | :director => "Peter Jackson" 18 | ) 19 | end 20 | 21 | it "returns all the movies" do 22 | get "/movies", {}, accept_json 23 | 24 | expect(response.status).to eq 200 25 | 26 | body = JSON.parse(response.body) 27 | movie_titles = body.map { |m| m["title"] } 28 | movie_directors = body.map { |m| m["director"] } 29 | 30 | expect(movie_titles).to match_array(["The Hobbit", 31 | "The Fellowship of the Ring"]) 32 | expect(movie_directors).to match_array(["Peter Jackson", 33 | "Peter Jackson"]) 34 | end 35 | end 36 | 37 | describe "GET /movies/:id" do 38 | let(:movie) do 39 | create_movie( 40 | :title => "2001: A Space Odyssy", 41 | :director => "Stanley Kubrick" 42 | ) 43 | end 44 | 45 | it "returns a requested movie" do 46 | get "/movies/#{movie.id}", {}, accept_json 47 | 48 | expect(response.status).to be 200 49 | 50 | body = JSON.parse(response.body) 51 | expect(body["title"]).to eq "2001: A Space Odyssy" 52 | expect(body["director"]).to eq "Stanley Kubrick" 53 | end 54 | end 55 | 56 | describe "PUT /movies/:id" do 57 | let(:movie) do 58 | create_movie( 59 | :title => "Star Battles", 60 | :director => "Leorge Gucas" 61 | ) 62 | end 63 | 64 | let(:movie_params) do 65 | {"title" => "Star Wars", "director" => "George Lucas"} 66 | end 67 | 68 | it "updates a movie" do 69 | patch "/movies/#{movie.id}", movie_params.to_json, accept_and_return_json 70 | 71 | expect(response.status).to be 200 72 | 73 | body = JSON.parse(response.body) 74 | 75 | expect(body["title"]).to eq "Star Wars" 76 | expect(body["director"]).to eq "George Lucas" 77 | end 78 | end 79 | 80 | describe "POST /movies" do 81 | let(:movie_params) do 82 | { 83 | "title" => "Indiana Jones and the Temple of Doom", 84 | "director" => "Steven Spielberg" 85 | } 86 | end 87 | 88 | it "creates a movie" do 89 | post "/movies", movie_params.to_json, accept_and_return_json 90 | 91 | expect(response.status).to eq 201 92 | 93 | response_body = JSON.parse(response.body) 94 | 95 | expect(response_body["id"]).to be_present 96 | expect(response_body["director"]).to eq("Steven Spielberg") 97 | 98 | expect(response_body["title"]) 99 | .to eq "Indiana Jones and the Temple of Doom" 100 | end 101 | end 102 | 103 | describe "DELETE /movies/:id" do 104 | let(:movie) do 105 | create_movie( 106 | :title => "The Shining", 107 | :director => "Stanley Kubrick" 108 | ) 109 | end 110 | 111 | it "deletes a movie" do 112 | delete "/movies/#{movie.id}", {}, accept_json 113 | 114 | expect(response.status).to be 204 115 | end 116 | end 117 | end 118 | end 119 | -------------------------------------------------------------------------------- /components/movie_manager/spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | RSpec.configure do |config| 2 | config.order = :random 3 | 4 | Kernel.srand config.seed 5 | 6 | config.expect_with :rspec do |expectations| 7 | expectations.syntax = :expect 8 | end 9 | 10 | config.mock_with :rspec do |mocks| 11 | mocks.syntax = :expect 12 | mocks.verify_partial_doubles = true 13 | end 14 | 15 | config.disable_monkey_patching! 16 | end 17 | -------------------------------------------------------------------------------- /components/movie_manager/spec/support/object_creation_methods.rb: -------------------------------------------------------------------------------- 1 | module ObjectCreationMethods 2 | def create_movie(overrides = {}) 3 | new_movie(overrides).tap(&:save!) 4 | end 5 | 6 | def new_movie(overrides = {}) 7 | defaults = { 8 | title: "The Shining", 9 | director: "Stanley Kubrick" 10 | 11 | } 12 | 13 | MovieManager::MovieRepo::Movie.new(defaults.merge(overrides)) 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /components/movie_manager/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exit_code=0 4 | 5 | echo "*** Running movie manager engine specs" 6 | bundle install | grep Installing 7 | RAILS_ENV=test bundle exec rake db:create 8 | RAILS_ENV=test bundle exec rake db:migrate 9 | bundle exec rspec spec 10 | exit_code+=$? 11 | 12 | exit $exit_code 13 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | require ::File.expand_path('../config/environment', __FILE__) 2 | run Rails.application 3 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../boot', __FILE__) 2 | 3 | require "active_record/railtie" 4 | require "action_controller/railtie" 5 | require "action_view/railtie" 6 | require "sprockets/railtie" 7 | 8 | Bundler.setup(:default, Rails.env) 9 | 10 | require "pry-rails" 11 | require "rack/cors" 12 | 13 | require "documentation" 14 | require "movie_manager" 15 | 16 | module JsonRails 17 | class Application < Rails::Application 18 | config.i18n.enforce_available_locales = true 19 | 20 | config.middleware.use Rack::Cors do 21 | allow do 22 | origins "*" 23 | resource "*", :headers => :any, :methods => [:get, :post, :delete, :put, :options] 24 | end 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__) 2 | 3 | require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) 4 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: postgresql 3 | encoding: unicode 4 | database: json-rails_development 5 | pool: 5 6 | 7 | test: 8 | adapter: postgresql 9 | encoding: unicode 10 | database: json-rails_test 11 | pool: 5 12 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../application', __FILE__) 2 | JsonRails::Application.initialize! 3 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | JsonRails::Application.configure do 2 | config.cache_classes = false 3 | config.eager_load = false 4 | config.consider_all_requests_local = true 5 | config.action_controller.perform_caching = false 6 | config.active_support.deprecation = :log 7 | config.active_record.migration_error = :page_load 8 | config.assets.debug = true 9 | end 10 | -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | JsonRails::Application.configure do 2 | config.cache_classes = true 3 | config.eager_load = true 4 | config.consider_all_requests_local = false 5 | config.action_controller.perform_caching = true 6 | config.serve_static_assets = true 7 | config.assets.js_compressor = :uglifier 8 | config.assets.compile = false 9 | config.assets.digest = true 10 | config.assets.version = '1.0' 11 | config.log_level = :debug 12 | config.i18n.fallbacks = true 13 | config.active_support.deprecation = :notify 14 | config.log_formatter = ::Logger::Formatter.new 15 | end 16 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | JsonRails::Application.configure do 2 | config.cache_classes = true 3 | config.eager_load = false 4 | config.serve_static_assets = true 5 | config.static_cache_control = "public, max-age=3600" 6 | config.consider_all_requests_local = true 7 | config.action_controller.perform_caching = false 8 | config.action_dispatch.show_exceptions = false 9 | config.action_controller.allow_forgery_protection = false 10 | config.active_support.deprecation = :stderr 11 | end 12 | -------------------------------------------------------------------------------- /config/initializers/secret_token.rb: -------------------------------------------------------------------------------- 1 | JsonRails::Application.config.secret_key_base = '98c57dee58abd58bae2fb48e704754fef46df62f16e5ccb1d3eed622b592e71a1912488472883d3b6b4c01c0a651377c0c95f9db644f1012f3f0c3a513f7a37c' 2 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | ActiveSupport.on_load(:action_controller) do 2 | wrap_parameters format: [:json] if respond_to?(:wrap_parameters) 3 | end 4 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | JsonRails::Application.routes.draw do 2 | mount Documentation::Engine, at: "/" 3 | mount MovieManager::Engine, at: "/api" 4 | end 5 | -------------------------------------------------------------------------------- /db/schema.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | # This file is auto-generated from the current state of the database. Instead 3 | # of editing this file, please use the migrations feature of Active Record to 4 | # incrementally modify your database, and then regenerate this schema definition. 5 | # 6 | # Note that this schema.rb definition is the authoritative source for your 7 | # database schema. If you need to create the application database on another 8 | # system, you should be using db:schema:load, not running all the migrations 9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations 10 | # you'll amass, the slower it'll run and the greater likelihood for issues). 11 | # 12 | # It's strongly recommended that you check this file into your version control system. 13 | 14 | ActiveRecord::Schema.define(version: 20141206230010) do 15 | 16 | # These are extensions that must be enabled in order to support this database 17 | enable_extension "plpgsql" 18 | 19 | create_table "movie_manager_movies", force: true do |t| 20 | t.string "title", null: false 21 | t.string "director" 22 | t.datetime "created_at" 23 | t.datetime "updated_at" 24 | end 25 | 26 | end 27 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | [ 2 | { title: "Seven Samurai", director: "Akira Kurozawa" }, 3 | { title: "Dune", director: "Alan Smithee" }, 4 | { title: "2001", director: "Stanley Kubrick" } 5 | ].each do |movie_info| 6 | MovieManager::MovieRepo.persist(title: movie_info[:title], 7 | director: movie_info[:director]) 8 | end 9 | -------------------------------------------------------------------------------- /deploy_app.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x -e 4 | 5 | echo "Pushing to heroku acceptance environment" 6 | git push git@heroku.com:json-rails-acceptance.git master 7 | 8 | echo "Migrating acceptance database" 9 | heroku run rake db:migrate --app json-rails-acceptance 10 | 11 | echo "Restarting app" 12 | heroku restart --app json-rails-acceptance 13 | --------------------------------------------------------------------------------