├── log
└── .gitkeep
├── .rspec
├── lib
├── tasks
│ ├── .gitkeep
│ └── db.rake
├── assets
│ └── .gitkeep
├── simplecov
│ └── rails_api_profile.rb
├── api_tasters
│ ├── users.rb
│ ├── sessions.rb
│ ├── locations.rb
│ └── units.rb
├── examples.rb
└── extensions
│ └── active_model_serializer
│ └── include_only_declared_associations.rb
├── public
├── favicon.ico
├── robots.txt
├── 500.html
├── 422.html
└── 404.html
├── app
├── mailers
│ └── .gitkeep
├── models
│ ├── .gitkeep
│ ├── location.rb
│ ├── user.rb
│ └── unit.rb
├── serializers
│ ├── base_serializer.rb
│ ├── location_serializer.rb
│ ├── unit_serializer.rb
│ └── user_serializer.rb
├── controllers
│ ├── user
│ │ └── base_controller.rb
│ ├── users_controller.rb
│ ├── sessions_controller.rb
│ ├── application_controller.rb
│ ├── units_controller.rb
│ └── locations_controller.rb
├── responders
│ └── api_responder.rb
├── services
│ └── authentication_service.rb
└── interactors
│ ├── unit_saver.rb
│ └── unit_fetcher.rb
├── .ruby-version
├── db
├── seeds
│ ├── development
│ │ └── all.seeds.rb
│ └── staging
│ │ └── all.seeds.rb
├── migrate
│ ├── 20130614112947_create_locations.rb
│ ├── 20130614115836_create_units.rb
│ └── 20130319140714_devise_create_users.rb
├── seeds.rb
└── schema.rb
├── script
├── server
├── ci
├── quality
├── rails
├── ci_deploy
└── bootstrap
├── Procfile
├── doc
├── schema.png
└── README_FOR_APP
├── config
├── initializers
│ ├── mailer.rb
│ ├── api_taster.rb
│ ├── active_model_serializer.rb
│ ├── mail_safe.rb
│ ├── bullet.rb
│ ├── generators.rb
│ ├── mime_types.rb
│ ├── time_formats.rb
│ ├── 01_config.rb
│ ├── requires.rb
│ ├── strong_parameters.rb
│ ├── wrap_parameters.rb
│ ├── secret_token.rb
│ ├── rollbar.rb
│ └── devise.rb
├── environment.rb
├── boot.rb
├── locales
│ ├── en.yml
│ └── devise.en.yml
├── database.yml.example
├── routes.rb
├── environments
│ ├── development.rb
│ ├── test.rb
│ └── production.rb
├── rails_best_practices.yml
└── application.rb
├── .env.example
├── spec
├── factories
│ ├── location.rb
│ ├── sequences.rb
│ ├── users.rb
│ └── unit.rb
├── support
│ ├── extensions
│ │ ├── active_record
│ │ │ └── sliced.rb
│ │ └── rspec-rails
│ │ │ └── mock_model.rb
│ ├── matchers
│ │ ├── be_a_full_user_representation.rb
│ │ ├── include_attributes.rb
│ │ ├── be_a_location_representation.rb
│ │ ├── be_a_user_representation.rb
│ │ └── be_a_unit_representation.rb
│ ├── shared_examples
│ │ ├── success_response.rb
│ │ └── authentication.rb
│ └── helpers.rb
├── serializers
│ ├── unit_serializer_spec.rb
│ ├── location_serializer_spec.rb
│ └── user_serializer_spec.rb
├── models
│ ├── user_spec.rb
│ ├── location_spec.rb
│ └── unit_spec.rb
├── controllers
│ ├── sessions_controller_spec.rb
│ ├── users_controller_spec.rb
│ ├── locations_controller_spec.rb
│ └── units_controller_spec.rb
├── api
│ ├── sessions_spec.rb
│ ├── users_spec.rb
│ ├── locations_spec.rb
│ └── units_spec.rb
├── interactors
│ ├── unit_saver_spec.rb
│ └── unit_fetcher_spec.rb
└── spec_helper.rb
├── config.ru
├── Rakefile
├── .gitignore
├── Guardfile
├── Gemfile
├── README.md
└── Gemfile.lock
/log/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --color
2 |
--------------------------------------------------------------------------------
/lib/tasks/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/mailers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/models/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.ruby-version:
--------------------------------------------------------------------------------
1 | 2.0.0-p247
2 |
--------------------------------------------------------------------------------
/db/seeds/development/all.seeds.rb:
--------------------------------------------------------------------------------
1 | Examples.setup!
2 |
--------------------------------------------------------------------------------
/db/seeds/staging/all.seeds.rb:
--------------------------------------------------------------------------------
1 | Examples.setup!
2 |
--------------------------------------------------------------------------------
/script/server:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | exec bin/foreman start
4 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: bundle exec rails server thin -p $PORT -e $RACK_ENV
2 |
--------------------------------------------------------------------------------
/doc/schema.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fs/inventory-reborn/master/doc/schema.png
--------------------------------------------------------------------------------
/app/serializers/base_serializer.rb:
--------------------------------------------------------------------------------
1 | class BaseSerializer < ActiveModel::Serializer
2 | end
3 |
--------------------------------------------------------------------------------
/config/initializers/mailer.rb:
--------------------------------------------------------------------------------
1 | ActionMailer::Base.default_url_options[:host] = app_config.host
2 |
--------------------------------------------------------------------------------
/script/ci:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | set -e
4 |
5 | bundle exec rspec spec
6 |
7 | script/quality
8 |
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | # Add your API tokens here
2 | RACK_ENV=development
3 | # ROLLBAR_KEY=your_key_here
4 |
5 |
--------------------------------------------------------------------------------
/app/serializers/location_serializer.rb:
--------------------------------------------------------------------------------
1 | class LocationSerializer < BaseSerializer
2 | attributes :id, :name
3 | end
4 |
--------------------------------------------------------------------------------
/config/initializers/api_taster.rb:
--------------------------------------------------------------------------------
1 | ApiTaster.route_path = Rails.root.join('lib', 'api_tasters') if defined? ApiTaster
2 |
--------------------------------------------------------------------------------
/spec/factories/location.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :location do
3 | name { Faker::Name.title }
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/app/controllers/user/base_controller.rb:
--------------------------------------------------------------------------------
1 | class User::BaseController < ApplicationController
2 | before_filter :authenticate_user!
3 | end
4 |
--------------------------------------------------------------------------------
/spec/factories/sequences.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | sequence(:email) { |n| "user#{n}@example.com" }
3 | sequence(:password) { '123456' }
4 | end
5 |
--------------------------------------------------------------------------------
/spec/factories/users.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :user do
3 | email
4 | password
5 | full_name { Faker::Name.name }
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/spec/support/extensions/active_record/sliced.rb:
--------------------------------------------------------------------------------
1 | ActiveRecord::Base.class_eval do
2 | def sliced_attributes(keys)
3 | attributes.slice(*keys)
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/app/models/location.rb:
--------------------------------------------------------------------------------
1 | class Location < ActiveRecord::Base
2 | has_many :units, include: :user, order: :id
3 |
4 | validates :name, presence: true, uniqueness: true
5 | end
6 |
--------------------------------------------------------------------------------
/config/initializers/active_model_serializer.rb:
--------------------------------------------------------------------------------
1 | ActiveSupport.on_load(:active_model_serializers) do
2 | self.root = false
3 | ActiveModel::ArraySerializer.root = false
4 | end
5 |
--------------------------------------------------------------------------------
/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 InventoryReborn::Application
5 |
--------------------------------------------------------------------------------
/config/initializers/mail_safe.rb:
--------------------------------------------------------------------------------
1 | # allow send emails to the @example.com
2 | #
3 | if defined?(MailSafe::Config)
4 | MailSafe::Config.internal_address_definition = /^.*@example\.com$/i
5 | end
--------------------------------------------------------------------------------
/script/quality:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | set -e
4 |
5 | bin/brakeman --quiet --skip-libs --except ForgerySetting
6 | bin/rails_best_practices --silent --spec --features -x lib/templates
7 |
--------------------------------------------------------------------------------
/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the rails application
2 | require File.expand_path('../application', __FILE__)
3 |
4 | # Initialize the rails application
5 | InventoryReborn::Application.initialize!
6 |
--------------------------------------------------------------------------------
/app/serializers/unit_serializer.rb:
--------------------------------------------------------------------------------
1 | class UnitSerializer < BaseSerializer
2 | attributes :unit_type, :inv_id, :name, :description, :on_depot, :out_of_order
3 |
4 | has_one :user, :location
5 | end
6 |
--------------------------------------------------------------------------------
/app/controllers/users_controller.rb:
--------------------------------------------------------------------------------
1 | class UsersController < ApplicationController
2 | before_filter :authenticate_user!
3 |
4 | expose(:users)
5 |
6 | def index
7 | respond_with users
8 | end
9 | end
--------------------------------------------------------------------------------
/config/boot.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 |
3 | # Set up gems listed in the Gemfile.
4 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
5 |
6 | require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
7 |
--------------------------------------------------------------------------------
/lib/simplecov/rails_api_profile.rb:
--------------------------------------------------------------------------------
1 | require 'simplecov'
2 |
3 | SimpleCov.adapters.define 'rails-api' do
4 | load_adapter 'rails'
5 | add_filter 'api_taster'
6 | add_filter 'examples'
7 | add_filter 'serializers/'
8 | end
9 |
--------------------------------------------------------------------------------
/doc/README_FOR_APP:
--------------------------------------------------------------------------------
1 | Use this README file to introduce your application and point to useful places in the API for learning more.
2 | Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.
3 |
--------------------------------------------------------------------------------
/spec/support/matchers/be_a_full_user_representation.rb:
--------------------------------------------------------------------------------
1 | RSpec::Matchers.define :be_a_full_user_representation do |user|
2 | match do |json|
3 | json.should be_a_user_representation(user, 'authentication_token')
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/spec/support/matchers/include_attributes.rb:
--------------------------------------------------------------------------------
1 | RSpec::Matchers.define :include_attributes do |expected|
2 | match_for_should do |actual|
3 | actual.should RSpec::Matchers::BuiltIn::Include.new(expected.as_json)
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/app/serializers/user_serializer.rb:
--------------------------------------------------------------------------------
1 | class UserSerializer < BaseSerializer
2 | attributes :id, :authentication_token, :email, :full_name
3 |
4 | def include_authentication_token?
5 | options[:full_representation]
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2 | #
3 | # To ban all spiders from the entire site uncomment the next two lines:
4 | # User-Agent: *
5 | # Disallow: /
6 |
--------------------------------------------------------------------------------
/spec/support/shared_examples/success_response.rb:
--------------------------------------------------------------------------------
1 | shared_examples 'a request with valid params' do |code|
2 | it 'returns http success' do
3 | expect(response).to be_success
4 | expect(response.code).to eq code
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20130614112947_create_locations.rb:
--------------------------------------------------------------------------------
1 | class CreateLocations < ActiveRecord::Migration
2 | def change
3 | create_table :locations do |t|
4 | t.string :name
5 |
6 | t.timestamps
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/lib/api_tasters/users.rb:
--------------------------------------------------------------------------------
1 | ApiTaster.routes do
2 | desc <<-markdown.strip_heredoc
3 | ## List all users
4 | markdown
5 |
6 | get '/users',
7 | authentication_token: Examples.user.authentication_token
8 | end if defined? ApiTaster
--------------------------------------------------------------------------------
/config/initializers/bullet.rb:
--------------------------------------------------------------------------------
1 | Rails.application.config.after_initialize do
2 | Bullet.enable = true
3 | Bullet.alert = true
4 | Bullet.rails_logger = true
5 | Bullet.console = true
6 | Bullet.airbrake = true
7 | end if defined?(Bullet)
8 |
--------------------------------------------------------------------------------
/config/initializers/generators.rb:
--------------------------------------------------------------------------------
1 | InventoryReborn::Application.configure do
2 | config.generators do |g|
3 | g.fixture_replacement :factory_girl, dir: 'spec/factories'
4 | g.stylesheets false
5 | g.javascripts false
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 | # Mime::Type.register_alias "text/html", :iphone
6 |
--------------------------------------------------------------------------------
/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Sample localization file for English. Add more files in this directory for other locales.
2 | # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3 |
4 | en:
5 | hello: "Hello world"
6 |
--------------------------------------------------------------------------------
/config/initializers/time_formats.rb:
--------------------------------------------------------------------------------
1 | {
2 | short_date: '%x',
3 | long_date: '%a, %b %d, %Y',
4 | us: '%m/%d/%Y %I:%M %p',
5 | us_date: '%m/%d/%Y',
6 | us_time: '%I:%M %p'
7 | }.each do |k, v|
8 | Time::DATE_FORMATS.update(k => v)
9 | end
10 |
--------------------------------------------------------------------------------
/lib/tasks/db.rake:
--------------------------------------------------------------------------------
1 | namespace :db do
2 | desc 'Generates model schema diagram'
3 | task generate_schema_diagram: :environment do
4 | %x(bundle exec erd --filetype=png --notation=uml --inheritance --polymorphism --filename=doc/schema)
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/spec/support/shared_examples/authentication.rb:
--------------------------------------------------------------------------------
1 | shared_examples 'a method that requires an authentication' do
2 | it 'responds unauthorized with an HTTP 401 status code' do
3 | send method, url
4 | expect(response.code).to eq '401'
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/config/initializers/01_config.rb:
--------------------------------------------------------------------------------
1 | # The shortcut for getting application config
2 | # Application config should be stored in the config/application.rb, config/environments/*.rb
3 | module Kernel
4 | def app_config
5 | Rails.application.config
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/spec/support/helpers.rb:
--------------------------------------------------------------------------------
1 | module Helpers
2 | def set_devise_mapping(mapping_name = :user)
3 | @request.env['devise.mapping'] = Devise.mappings[mapping_name]
4 | end
5 |
6 | def json_response_body
7 | JSON.parse(response.body)
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/config/initializers/requires.rb:
--------------------------------------------------------------------------------
1 | # Require recursively all files in the lib/extensions
2 | Dir[Rails.root.join('lib/extensions/**/*.rb')].each {|f| require f}
3 |
4 | # Require only files placed in the lib folder
5 | Dir[Rails.root.join('lib/*.rb')].each {|f| require f}
6 |
--------------------------------------------------------------------------------
/lib/api_tasters/sessions.rb:
--------------------------------------------------------------------------------
1 | ApiTaster.routes do
2 | desc <<-markdown.strip_heredoc
3 | ## Visitor signs in
4 | markdown
5 |
6 | post '/users/sign_in', user: {
7 | email: Examples.user.email,
8 | password: Examples.password
9 | }
10 | end if defined? ApiTaster
11 |
--------------------------------------------------------------------------------
/app/controllers/sessions_controller.rb:
--------------------------------------------------------------------------------
1 | class SessionsController < Devise::SessionsController
2 | wrap_parameters :user
3 |
4 | def create
5 | user = AuthenticationService.new(warden).authenticate!
6 |
7 | respond_with user,
8 | full_representation: true
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/spec/serializers/unit_serializer_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe UnitSerializer do
4 | let(:unit) { build :unit }
5 | let(:json) { UnitSerializer.new(unit).to_json }
6 |
7 | subject { JSON.parse(json) }
8 |
9 | it { should be_a_unit_representation(unit) }
10 | end
11 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env rake
2 | # Add your own tasks in files placed in lib/tasks ending in .rake,
3 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4 |
5 | require File.expand_path('../config/application', __FILE__)
6 |
7 | InventoryReborn::Application.load_tasks
8 |
--------------------------------------------------------------------------------
/app/models/user.rb:
--------------------------------------------------------------------------------
1 | class User < ActiveRecord::Base
2 | devise :database_authenticatable, :registerable,
3 | :recoverable, :validatable,
4 | :token_authenticatable
5 |
6 | has_many :units, include: :location, order: :id
7 |
8 | before_save :ensure_authentication_token
9 | end
10 |
--------------------------------------------------------------------------------
/config/initializers/strong_parameters.rb:
--------------------------------------------------------------------------------
1 | ActiveSupport.on_load(:active_record) do
2 | ActiveRecord::Base.send(:include, ActiveModel::ForbiddenAttributesProtection)
3 | end
4 |
5 | ActiveSupport.on_load(:action_controller) do
6 | ActionController::API.send :include, ActionController::StrongParameters
7 | end
8 |
--------------------------------------------------------------------------------
/spec/models/user_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe User do
4 | describe 'validations' do
5 | context 'uniqueness' do
6 | it { should validate_uniqueness_of :email }
7 | end
8 | end
9 |
10 | describe 'associations' do
11 | it { should have_many :units }
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/script/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3 |
4 | APP_PATH = File.expand_path('../../config/application', __FILE__)
5 | require File.expand_path('../../config/boot', __FILE__)
6 | require 'rails/commands'
7 |
--------------------------------------------------------------------------------
/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::API
2 | include ActionController::MimeResponds
3 |
4 | self.responder = ApiResponder
5 |
6 | decent_configuration do
7 | strategy DecentExposure::StrongParametersStrategy
8 | end
9 |
10 | respond_to :json
11 | end
12 |
--------------------------------------------------------------------------------
/spec/models/location_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Location do
4 | describe 'associations' do
5 | it { should have_many :units }
6 | end
7 |
8 | describe 'validations' do
9 | it { should validate_presence_of :name }
10 | it { should validate_uniqueness_of :name }
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/spec/serializers/location_serializer_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe LocationSerializer do
4 | let(:location) { build :location, id: 1 }
5 | let(:json) { LocationSerializer.new(location).to_json }
6 |
7 | subject { JSON.parse(json) }
8 |
9 | it { should be_a_location_representation(location) }
10 | end
11 |
--------------------------------------------------------------------------------
/app/models/unit.rb:
--------------------------------------------------------------------------------
1 | class Unit < ActiveRecord::Base
2 | belongs_to :user
3 | belongs_to :location
4 |
5 | validates :inv_id, presence: true, uniqueness: true, numericality: true
6 | validates :name, :unit_type, :location, :user, presence: true
7 | validates :out_of_order_note, presence: true, if: proc { |u| u.out_of_order? }
8 | end
9 |
--------------------------------------------------------------------------------
/spec/factories/unit.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :unit do
3 | unit_type 'Awesome Type'
4 | sequence :inv_id
5 | name { Faker::Name.title }
6 | description 'Awesome Description'
7 | on_depot false
8 | out_of_order true
9 | out_of_order_note 'Awesome Text'
10 | user
11 | location
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/support/matchers/be_a_location_representation.rb:
--------------------------------------------------------------------------------
1 | RSpec::Matchers.define :be_a_location_representation do |location|
2 | match do |json|
3 | response_attributes = location.sliced_attributes %w[
4 | id
5 | name
6 | ]
7 |
8 | expect(json).to be
9 | expect(json).to include_attributes(response_attributes)
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
7 | # Mayor.create(name: 'Emanuel', city: cities.first)
8 |
--------------------------------------------------------------------------------
/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | ActiveSupport.on_load(:action_controller) do
2 | # Make sure ParamsWrapper module included
3 | ActionController::API.send(:include, ActionController::ParamsWrapper)
4 |
5 | # Enable parameter wrapping for JSON
6 | wrap_parameters(
7 | format: [:json, :url_encoded_form],
8 | exclude: [Devise.token_authentication_key]
9 | )
10 | end
11 |
--------------------------------------------------------------------------------
/app/responders/api_responder.rb:
--------------------------------------------------------------------------------
1 | class ApiResponder < ActionController::Responder
2 | def api_behavior(error)
3 | raise error unless resourceful?
4 |
5 | if get?
6 | display resource
7 | elsif post?
8 | display resource, status: :created, location: nil
9 | elsif put?
10 | display resource, status: :ok
11 | else
12 | head :no_content
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/spec/support/matchers/be_a_user_representation.rb:
--------------------------------------------------------------------------------
1 | RSpec::Matchers.define :be_a_user_representation do |user, *keys|
2 | match do |json|
3 | default_keys = %w[
4 | id
5 | email
6 | full_name
7 | ]
8 | keys.concat(default_keys)
9 | response_attributes = user.sliced_attributes keys
10 |
11 | json.should be
12 | json.should include_attributes(response_attributes)
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/spec/support/matchers/be_a_unit_representation.rb:
--------------------------------------------------------------------------------
1 | RSpec::Matchers.define :be_a_unit_representation do |unit|
2 | match do |json|
3 | response_attributes = unit.sliced_attributes %w[
4 | unit_type
5 | inv_id
6 | name
7 | description
8 | on_depot
9 | out_of_order
10 | ]
11 |
12 | expect(json).to be
13 | expect(json).to include_attributes(response_attributes)
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/services/authentication_service.rb:
--------------------------------------------------------------------------------
1 | class AuthenticationService
2 | SCOPE = :user
3 |
4 | def initialize(warden)
5 | @warden = warden
6 | end
7 |
8 | def authenticate!
9 | @warden.authenticate!(authentication_options).tap do |user|
10 | user.ensure_authentication_token!
11 | end
12 | end
13 |
14 | private
15 |
16 | def authentication_options
17 | { store: false, scope: SCOPE }
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/config/initializers/secret_token.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Your secret key for verifying the integrity of signed cookies.
4 | # If you change this key, all old signed cookies will become invalid!
5 | # Make sure the secret is at least 30 characters and all random,
6 | # no regular words or you'll be exposed to dictionary attacks.
7 | Rails.application.config.secret_token = '2bcc1492fb9e2f8158a1bb5e951022317eba080b195d676d77d65f2f8a2ee751d816683e05a8ea21673219'
8 |
--------------------------------------------------------------------------------
/spec/controllers/sessions_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe SessionsController do
4 | before do
5 | set_devise_mapping(:user)
6 | end
7 |
8 | describe 'POST #create' do
9 | before do
10 | AuthenticationService.
11 | any_instance.
12 | should_receive(:authenticate!) { build :user }
13 |
14 | post :create,
15 | format: :json
16 | end
17 |
18 | it_behaves_like 'a request with valid params', '201'
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/spec/support/extensions/rspec-rails/mock_model.rb:
--------------------------------------------------------------------------------
1 | module RSpec
2 | module Rails
3 | module Mocks
4 | def mock_model_with_read_attribute_for_serialization(string_or_model_class, stubs = {})
5 | stubs = stubs.update(read_attribute_for_serialization: 'attribute')
6 | mock_model_without_read_attribute_for_serialization(string_or_model_class, stubs)
7 | end
8 |
9 | alias_method_chain :mock_model, :read_attribute_for_serialization
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 | #
3 | # If you find yourself ignoring temporary files generated by your text editor
4 | # or operating system, you probably want to add a global ignore instead:
5 | # git config --global core.excludesfile ~/.gitignore_global
6 |
7 | /.bundle
8 | /db/*.sqlite3
9 | /log/*.log
10 | /tmp
11 | coverage/*
12 | rerun.txt
13 | config/database.yml
14 | doc/**/*
15 | vendor/bundle
16 | vendor/cache
17 | vendor/ruby
18 | bin
19 | .sass-cache
20 | ._*
21 | .env
22 |
--------------------------------------------------------------------------------
/config/database.yml.example:
--------------------------------------------------------------------------------
1 | development:
2 | adapter: postgresql
3 | encoding: unicode
4 | database: rails3_base_api_dev
5 | pool: 5
6 | username: postgres
7 | password: postgres
8 |
9 | # Warning: The database defined as "test" will be erased and
10 | # re-generated from your development database when you run "rake".
11 | # Do not set this db to the same as development or production.
12 | test:
13 | adapter: postgresql
14 | encoding: unicode
15 | database: rails3_base_api_test
16 | pool: 5
17 | username: postgres
18 | password: postgres
19 |
--------------------------------------------------------------------------------
/Guardfile:
--------------------------------------------------------------------------------
1 | guard 'rspec', notification: true, zeus: true, binstubs: true 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 |
6 | # Rails example
7 | watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
8 | watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb"] }
9 | watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
10 | watch('app/controllers/application_controller.rb') { "spec/controllers" }
11 | end
12 |
13 |
--------------------------------------------------------------------------------
/spec/controllers/users_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe UsersController do
4 | let(:user) { create :user }
5 | let(:users) { [user] }
6 |
7 | before do
8 | sign_in user
9 | end
10 |
11 | describe "GET #index" do
12 | before do
13 | User.stub(:scoped) { users }
14 | users.stub(:where) { users }
15 |
16 | get 'index', format: 'json'
17 | end
18 |
19 | it_behaves_like 'a request with valid params', '200'
20 |
21 | it 'assigns users' do
22 | expect(controller.users).to eq users
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/db/migrate/20130614115836_create_units.rb:
--------------------------------------------------------------------------------
1 | class CreateUnits < ActiveRecord::Migration
2 | def change
3 | create_table :units do |t|
4 | t.string :unit_type
5 | t.integer :inv_id
6 | t.string :name
7 | t.text :description
8 | t.integer :user_id
9 | t.integer :location_id
10 | t.boolean :on_depot, default: false
11 | t.boolean :out_of_order, default: false
12 | t.text :out_of_order_note
13 |
14 | t.timestamps
15 | end
16 |
17 | add_index :units, :inv_id
18 | add_index :units, :location_id
19 | add_index :units, :user_id
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/spec/serializers/user_serializer_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe UserSerializer do
4 | let(:user) { build :user, id: 1, authentication_token: 'token' }
5 | subject { JSON.parse(json) }
6 |
7 | context 'full representation' do
8 | let(:json) { UserSerializer.new(user, full_representation: true).to_json }
9 |
10 | it { should be_a_full_user_representation(user) }
11 | end
12 |
13 | context 'base representation' do
14 | let(:json) { UserSerializer.new(user).to_json }
15 |
16 | it { should be_a_user_representation(user) }
17 | it { should_not be_a_full_user_representation(user) }
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/lib/examples.rb:
--------------------------------------------------------------------------------
1 | module Examples
2 | extend self
3 |
4 | def user
5 | @user ||= User.first
6 | end
7 |
8 | def password
9 | '123456'
10 | end
11 |
12 | def location
13 | @location ||= Location.first_or_create FactoryGirl.attributes_for(:location)
14 | end
15 |
16 | def unit
17 | @unit ||= Unit.first_or_create FactoryGirl.attributes_for(:unit, user: user, location: location)
18 | end
19 |
20 | def setup!
21 | ActiveRecord::Base.transaction do
22 | FactoryGirl.create :user
23 |
24 | FactoryGirl.create :location
25 |
26 | FactoryGirl.create_list :unit, 3, user: user, location: location
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/config/routes.rb:
--------------------------------------------------------------------------------
1 | InventoryReborn::Application.routes.draw do
2 | scope defaults: { format: :json } do
3 | devise_for :users, only: []
4 | devise_scope :user do
5 | post 'users/sign_in', to: 'sessions#create'
6 | end
7 |
8 | resources :users, only: :index do
9 | resources :units, only: :index
10 | end
11 |
12 | resources :locations, only: [:index, :show, :create, :update] do
13 | resources :units, only: :index
14 | end
15 |
16 | resources :units, only: [:index, :show, :create, :update]
17 | end
18 |
19 | if defined? ApiTaster::Engine
20 | mount ApiTaster::Engine => '/api_taster'
21 | root to: ApiTaster::Engine
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/app/interactors/unit_saver.rb:
--------------------------------------------------------------------------------
1 | class UnitSaver
2 | include Interactor
3 |
4 | def setup
5 | @unit = context[:unit]
6 | @params = context[:unit_params]
7 | end
8 |
9 | def perform
10 | @unit.assign_attributes(unit_params)
11 | @unit.user = user
12 | @unit.location = location
13 |
14 | @unit.save!
15 | end
16 |
17 | private
18 |
19 | def location
20 | @location ||= Location.find(@params[:location_id])
21 | end
22 |
23 | def user
24 | @user ||= User.find(@params[:user_id])
25 | end
26 |
27 | def unit_params
28 | @unit_params ||= @params.except(:location_id, :user_id).permit(:unit_type, :inv_id, :name,
29 | :description, :on_depot, :out_of_order, :out_of_order_note)
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/spec/api/sessions_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe '/users/sign_in' do
4 | subject { json_response_body }
5 |
6 | describe 'sign in' do
7 | let(:url) { '/users/sign_in' }
8 |
9 | context 'with valid credentials' do
10 | let(:user) { create :user, password: '123456' }
11 | let(:params) do
12 | {
13 | email: user.email,
14 | password: '123456'
15 | }
16 | end
17 |
18 | before { post url, params }
19 |
20 | it { should be_a_full_user_representation(user) }
21 | end
22 |
23 | context 'with invalid credentials' do
24 | let(:method) { :post }
25 |
26 | it_behaves_like 'a method that requires an authentication'
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
We're sorry, but something went wrong.
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/interactors/unit_fetcher.rb:
--------------------------------------------------------------------------------
1 | class UnitFetcher
2 | include Interactor
3 |
4 | def perform
5 | get_units
6 | get_ancestors
7 | end
8 |
9 | private
10 |
11 | def get_units
12 | context[:units] = user.units.presence || location.units.presence || Unit.includes(:user, :location)
13 | end
14 |
15 | def get_ancestors
16 | context[:ancestors] = if user.persisted?
17 | [:location]
18 | elsif location.persisted?
19 | [:user]
20 | else
21 | [:user, :location]
22 | end
23 | end
24 |
25 | def user
26 | @user ||= context['user_id'] ? User.find(context['user_id']) : User.new
27 | end
28 |
29 | def location
30 | @location ||= context['location_id'] ? Location.find(context['location_id']) : Location.new
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/app/controllers/units_controller.rb:
--------------------------------------------------------------------------------
1 | class UnitsController < ApplicationController
2 | before_filter :authenticate_user!
3 |
4 | expose(:unit_fetcher) { UnitFetcher.perform(params) }
5 | expose(:units) { unit_fetcher.units }
6 | expose(:unit)
7 |
8 | def index
9 | respond_with units,
10 | serializer_includes: {
11 | unit: unit_fetcher.ancestors
12 | }
13 | end
14 |
15 | def show
16 | respond_with unit,
17 | serializer_includes: {
18 | unit: [:user, :location]
19 | }
20 | end
21 |
22 | def create
23 | UnitSaver.perform(unit: unit, unit_params: params[:unit])
24 |
25 | respond_with unit
26 | end
27 |
28 | def update
29 | UnitSaver.perform(unit: unit, unit_params: params[:unit])
30 |
31 | respond_with unit
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/spec/api/users_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'resource users' do
4 | describe 'list' do
5 | let!(:users) { create_list :user, 2 }
6 | let!(:user) { users.first }
7 | let(:params) { { authentication_token: user.authentication_token } }
8 | subject { json_response_body }
9 |
10 | context 'GET /users' do
11 | let(:method) { :get }
12 | let(:url) { '/users' }
13 |
14 | it_behaves_like 'a method that requires an authentication'
15 |
16 | context 'with authentication token' do
17 | before { get url, params }
18 |
19 | it { should be_a_kind_of Array }
20 | its(:first) { should be_a_user_representation(user) }
21 | its(:count) { should eq(2) }
22 | end
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/public/422.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
The change you wanted was rejected.
23 |
Maybe you tried to change something you didn't have access to.
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/app/controllers/locations_controller.rb:
--------------------------------------------------------------------------------
1 | class LocationsController < ApplicationController
2 | before_filter :authenticate_user!
3 |
4 | # We can't use loaction method b/c
5 | # it defined in the ActionController already
6 | expose(:unit_locations) { Location.scoped }
7 | expose(:unit_location, model: :location, attributes: :location_params)
8 |
9 | def index
10 | respond_with unit_locations
11 | end
12 |
13 | def show
14 | respond_with unit_location
15 | end
16 |
17 | def create
18 | unit_location.save
19 |
20 | respond_with unit_location
21 | end
22 |
23 | def update
24 | unit_location.save
25 |
26 | respond_with unit_location
27 | end
28 |
29 | private
30 |
31 | def location_params
32 | params.require(:location).permit(:name)
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
The page you were looking for doesn't exist.
23 |
You may have mistyped the address or the page may have moved.
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/lib/api_tasters/locations.rb:
--------------------------------------------------------------------------------
1 | ApiTaster.routes do
2 | desc <<-markdown.strip_heredoc
3 | ## List all locations
4 | markdown
5 |
6 | get '/locations',
7 | authentication_token: Examples.user.authentication_token
8 |
9 | desc <<-markdown.strip_heredoc
10 | ## List Single location
11 | markdown
12 |
13 | get '/locations/:id',
14 | id: Examples.location.id,
15 | authentication_token: Examples.user.authentication_token
16 |
17 | desc <<-markdown.strip_heredoc
18 | ## Create location
19 | markdown
20 |
21 | post '/locations',
22 | location: FactoryGirl.attributes_for(:location),
23 | authentication_token: Examples.user.authentication_token
24 |
25 | desc <<-markdown.strip_heredoc
26 | ## Update location
27 | markdown
28 |
29 | put '/locations/:id',
30 | id: Examples.location.id,
31 | location: FactoryGirl.attributes_for(:location),
32 | authentication_token: Examples.user.authentication_token
33 | end if defined? ApiTaster
34 |
--------------------------------------------------------------------------------
/db/migrate/20130319140714_devise_create_users.rb:
--------------------------------------------------------------------------------
1 | class DeviseCreateUsers < ActiveRecord::Migration
2 | def change
3 | create_table(:users) do |t|
4 | ## Database authenticatable
5 | t.string :email, null: false, default: ''
6 | t.string :encrypted_password, null: false, default: ''
7 |
8 | ## Recoverable
9 | t.string :reset_password_token
10 | t.datetime :reset_password_sent_at
11 |
12 | ## Rememberable
13 | t.datetime :remember_created_at
14 |
15 | ## Trackable
16 | t.integer :sign_in_count, default: 0
17 | t.datetime :current_sign_in_at
18 | t.datetime :last_sign_in_at
19 | t.string :current_sign_in_ip
20 | t.string :last_sign_in_ip
21 |
22 | ## Token authenticatable
23 | t.string :authentication_token
24 |
25 | t.string :full_name
26 |
27 | t.timestamps
28 | end
29 |
30 | add_index :users, :email, unique: true
31 | add_index :users, :reset_password_token, unique: true
32 | add_index :users, :authentication_token, unique: true
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/lib/extensions/active_model_serializer/include_only_declared_associations.rb:
--------------------------------------------------------------------------------
1 | require 'active_support/concern'
2 |
3 | module ActiveModel::Serializer::IncludeOnlyDeclaredAssociations
4 | extend ActiveSupport::Concern
5 |
6 | included do
7 | alias_method_chain :include_associations!, :only_declared_associations
8 | end
9 |
10 | private
11 |
12 | def include_associations_with_only_declared_associations!
13 | include_only_declared_associations!
14 | end
15 |
16 | def include_only_declared_associations!
17 | associations_inclusion_options.each do |association|
18 | include!(association)
19 | end if has_associations_inclusion_options?
20 | end
21 |
22 | def has_associations_inclusion_options?
23 | options.include?(:serializer_includes) &&
24 | associations_inclusion_options.present?
25 | end
26 |
27 | def associations_inclusion_options
28 | options[:serializer_includes][current_serializer]
29 | end
30 |
31 | def current_serializer
32 | self.class.name.demodulize.underscore.sub(/_serializer$/, '').to_sym
33 | end
34 | end
35 |
36 | ActiveModel::Serializer.send(:include, ActiveModel::Serializer::IncludeOnlyDeclaredAssociations)
37 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | ruby '2.0.0'
4 |
5 | gem 'rails', '3.2.13'
6 |
7 | gem 'rails-api'
8 |
9 | gem 'pg'
10 | gem 'thin'
11 | gem 'decent_exposure'
12 | gem 'active_model_serializers'
13 | gem 'seedbank', github: 'james2m/seedbank'
14 | gem 'dotenv'
15 | gem 'strong_parameters'
16 | gem 'devise'
17 | gem 'rollbar'
18 | gem 'interactor-rails'
19 |
20 | group :development do
21 | gem 'letter_opener'
22 | gem 'foreman'
23 | gem 'bullet'
24 |
25 | gem 'guard-rspec'
26 | gem 'rb-fsevent', require: false
27 | gem 'zeus'
28 | gem 'rails-erd'
29 | gem 'pry-remote'
30 | gem 'pry-stack_explorer'
31 | end
32 |
33 | group :development, :test do
34 | gem 'rspec-rails'
35 | gem 'mail_safe'
36 | gem 'rails_best_practices'
37 | gem 'brakeman'
38 | gem 'pry-rails'
39 | gem 'pry-debugger'
40 | end
41 |
42 | group :test do
43 | gem 'simplecov', require: false
44 | gem 'webmock', require: false
45 |
46 | gem 'capybara'
47 | gem 'database_cleaner'
48 | gem 'email_spec'
49 | gem 'shoulda-matchers'
50 | end
51 |
52 | group :development, :staging do
53 | gem 'api_taster'
54 | end
55 |
56 | group :development, :test, :staging do
57 | gem 'faker'
58 | gem 'factory_girl_rails'
59 | end
60 |
--------------------------------------------------------------------------------
/spec/models/unit_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Unit do
4 | let(:unit) { build :unit }
5 |
6 | describe 'associations' do
7 | it { should belong_to :user }
8 | it { should belong_to :location }
9 | end
10 |
11 | describe 'validations' do
12 | context 'presence' do
13 | it { should validate_presence_of :name }
14 | it { should validate_presence_of :unit_type }
15 | it { should validate_presence_of :location }
16 | it { should validate_presence_of :user }
17 | it { should validate_presence_of :inv_id }
18 |
19 | context 'out_of_order_note' do
20 | it 'skip validation with out_of_order is not true' do
21 | unit.out_of_order = false
22 | unit.out_of_order_note = nil
23 | unit.should be_valid
24 | end
25 |
26 | it 'validates presence if out_of_order is true' do
27 | unit.out_of_order_note = nil
28 | unit.should_not be_valid
29 | end
30 | end
31 | end
32 |
33 | context 'uniqueness' do
34 | it { should validate_uniqueness_of :inv_id }
35 | end
36 |
37 | context 'numericality' do
38 | it { should validate_numericality_of :inv_id }
39 | end
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/spec/interactors/unit_saver_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe UnitSaver do
4 | let(:user) { build :user }
5 | let(:unit) { build :unit }
6 | let(:location) { build :location }
7 | let(:unit_params) { attributes_for :unit }
8 |
9 | before do
10 | unit.stub(:save!) { true }
11 | Location.stub(:find) { location }
12 | User.stub(:find) { user }
13 | unit_params.stub(:except) { unit_params }
14 | unit_params.stub(:permit) { unit_params }
15 | end
16 |
17 | describe '#perform' do
18 | it 'receive assing_attributes' do
19 | unit.should_receive(:assign_attributes) { unit }
20 | UnitSaver.perform(unit: unit, unit_params: unit_params)
21 | end
22 |
23 | it 'receive save' do
24 | unit.should_receive(:save!) { true }
25 | UnitSaver.perform(unit: unit, unit_params: unit_params)
26 | end
27 |
28 | context 'assign user and location to unit' do
29 | before do
30 | UnitSaver.perform(unit: unit, unit_params: unit_params)
31 | end
32 |
33 | it 'assign user to unit' do
34 | unit.user.should eq user
35 | end
36 |
37 | it 'assign location to unit' do
38 | unit.location.should eq location
39 | end
40 | end
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | require 'simplecov/rails_api_profile'
2 | SimpleCov.start 'rails-api'
3 |
4 | ENV["RAILS_ENV"] ||= 'test'
5 |
6 | require File.expand_path("../../config/environment", __FILE__)
7 | require 'rspec/rails'
8 | # require 'rspec/autorun' should be diabled with guard
9 |
10 | paths = Dir[Rails.root.join('spec/**/{support,extensions}/**/*.rb')]
11 | paths.each { |file| require file }
12 |
13 | RSpec.configure do |config|
14 | config.use_transactional_fixtures = true
15 |
16 | config.include Rails.application.routes.url_helpers
17 | config.include EmailSpec::Helpers
18 | config.include EmailSpec::Matchers
19 | config.include Devise::TestHelpers, type: :controller
20 | config.include FactoryGirl::Syntax::Methods
21 | config.include Helpers
22 |
23 | config.infer_base_class_for_anonymous_controllers = false
24 |
25 | config.order = "random"
26 |
27 | config.before :suite do
28 | DatabaseCleaner.strategy = :transaction
29 | DatabaseCleaner.clean_with :truncation
30 | end
31 |
32 | config.before do
33 | ActionMailer::Base.deliveries.clear
34 | end
35 |
36 | # Make sure we will send all requests with correct content type
37 | #
38 | config.before(type: :controller) do
39 | request.env['CONTENT_TYPE'] = 'application/json'
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | InventoryReborn::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # In the development environment your application's code is reloaded on
5 | # every request. This slows down response time but is perfect for development
6 | # since you don't have to restart the web server when you make code changes.
7 | config.cache_classes = false
8 |
9 | # Log error messages when you accidentally call methods on nil.
10 | config.whiny_nils = true
11 |
12 | # Show full error reports and disable caching
13 | config.consider_all_requests_local = true
14 | config.action_controller.perform_caching = false
15 |
16 | # Don't care if the mailer can't send
17 | config.action_mailer.raise_delivery_errors = false
18 |
19 | # Print deprecation notices to the Rails logger
20 | config.active_support.deprecation = :log
21 |
22 | # Only use best-standards-support built into browsers
23 | config.action_dispatch.best_standards_support = :builtin
24 |
25 | # Raise exception on mass assignment protection for Active Record models
26 | config.active_record.mass_assignment_sanitizer = :strict
27 |
28 | # Log the query plan for queries taking more than this (works
29 | # with SQLite, MySQL, and PostgreSQL)
30 | config.active_record.auto_explain_threshold_in_seconds = 0.5
31 |
32 | # Do not compress assets
33 | config.assets.compress = false
34 |
35 | # Expands the lines which load the assets
36 | config.assets.debug = true
37 | end
38 |
--------------------------------------------------------------------------------
/lib/api_tasters/units.rb:
--------------------------------------------------------------------------------
1 | ApiTaster.routes do
2 | desc <<-markdown.strip_heredoc
3 | ## List all units
4 | markdown
5 |
6 | get '/units',
7 | authentication_token: Examples.user.authentication_token
8 |
9 |
10 | desc <<-markdown.strip_heredoc
11 | ## List units for user
12 | markdown
13 |
14 | get '/users/:user_id/units',
15 | user_id: Examples.user.id,
16 | authentication_token: Examples.user.authentication_token
17 |
18 |
19 | desc <<-markdown.strip_heredoc
20 | ## List units for location
21 | markdown
22 |
23 | get '/locations/:location_id/units',
24 | location_id: Examples.location.id,
25 | authentication_token: Examples.user.authentication_token
26 |
27 | desc <<-markdown.strip_heredoc
28 | ## Single unit
29 | markdown
30 |
31 | get '/units/:id',
32 | id: Examples.unit.id,
33 | authentication_token: Examples.user.authentication_token
34 |
35 | desc <<-markdown.strip_heredoc
36 | ## Create unit
37 | markdown
38 |
39 | post '/units',
40 | {
41 | unit: FactoryGirl.attributes_for(:unit).
42 | merge({ location_id: Examples.location.id, user_id: Examples.user.id })
43 | }.merge({ authentication_token: Examples.user.authentication_token })
44 |
45 | desc <<-markdown.strip_heredoc
46 | ## Update unit
47 | markdown
48 |
49 | put '/units/:id',
50 | {
51 | id: Examples.unit.id,
52 | unit: FactoryGirl.attributes_for(:unit).
53 | merge({ location_id: Examples.location.id, user_id: Examples.user.id })
54 | }.merge({ authentication_token: Examples.user.authentication_token })
55 | end if defined? ApiTaster
56 |
--------------------------------------------------------------------------------
/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | InventoryReborn::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 | # Configure static asset server for tests with Cache-Control for performance
11 | config.serve_static_assets = true
12 | config.static_cache_control = "public, max-age=3600"
13 |
14 | # Log error messages when you accidentally call methods on nil
15 | config.whiny_nils = true
16 |
17 | # Show full error reports and disable caching
18 | config.consider_all_requests_local = true
19 | config.action_controller.perform_caching = false
20 |
21 | # Raise exceptions instead of rendering exception templates
22 | config.action_dispatch.show_exceptions = false
23 |
24 | # Disable request forgery protection in test environment
25 | config.action_controller.allow_forgery_protection = false
26 |
27 | # Tell Action Mailer not to deliver emails to the real world.
28 | # The :test delivery method accumulates sent emails in the
29 | # ActionMailer::Base.deliveries array.
30 | config.action_mailer.delivery_method = :test
31 |
32 | # Raise exception on mass assignment protection for Active Record models
33 | config.active_record.mass_assignment_sanitizer = :strict
34 |
35 | # Print deprecation notices to the stderr
36 | config.active_support.deprecation = :stderr
37 | end
38 |
--------------------------------------------------------------------------------
/config/rails_best_practices.yml:
--------------------------------------------------------------------------------
1 | AddModelVirtualAttributeCheck: { }
2 | AlwaysAddDbIndexCheck: { }
3 | #CheckSaveReturnValueCheck: { }
4 | DryBundlerInCapistranoCheck: { }
5 | HashSyntaxCheck: { }
6 | IsolateSeedDataCheck: { }
7 | KeepFindersOnTheirOwnModelCheck: { }
8 | LawOfDemeterCheck: { }
9 | #LongLineCheck: { max_line_length: 80 }
10 | MoveCodeIntoControllerCheck: { }
11 | MoveCodeIntoHelperCheck: { array_count: 3 }
12 | MoveCodeIntoModelCheck: { use_count: 2 }
13 | MoveFinderToNamedScopeCheck: { }
14 | MoveModelLogicIntoModelCheck: { use_count: 4 }
15 | NeedlessDeepNestingCheck: { nested_count: 2 }
16 | NotRescueExceptionCheck: { }
17 | NotUseDefaultRouteCheck: { }
18 | NotUseTimeAgoInWordsCheck: { }
19 | OveruseRouteCustomizationsCheck: { customize_count: 3 }
20 | ProtectMassAssignmentCheck: { }
21 | RemoveEmptyHelpersCheck: { }
22 | RemoveTabCheck: { }
23 | RemoveTrailingWhitespaceCheck: { }
24 | RemoveUnusedMethodsInControllersCheck:
25 | except_methods:
26 | - UnitsController#unit_params
27 | - LocationsController#location_params
28 | RemoveUnusedMethodsInHelpersCheck: { except_methods: [] }
29 | RemoveUnusedMethodsInModelsCheck: { except_methods: [] }
30 | ReplaceComplexCreationWithFactoryMethodCheck: { attribute_assignment_count: 2 }
31 | ReplaceInstanceVariableWithLocalVariableCheck: { }
32 | RestrictAutoGeneratedRoutesCheck: { }
33 | SimplifyRenderInControllersCheck: { }
34 | SimplifyRenderInViewsCheck: { }
35 | #UseBeforeFilterCheck: { customize_count: 2 }
36 | UseModelAssociationCheck: { }
37 | UseMultipartAlternativeAsContentTypeOfEmailCheck: { }
38 | #UseParenthesesInMethodDefCheck: { }
39 | UseObserverCheck: { }
40 | UseQueryAttributeCheck: { }
41 | UseSayWithTimeInMigrationsCheck: { }
42 | UseScopeAccessCheck: { }
43 | UseTurboSprocketsRails3Check: { }
44 |
--------------------------------------------------------------------------------
/spec/controllers/locations_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe LocationsController do
4 | let(:locations) { build_list :location, 2 }
5 | let(:location) { stub_model Location }
6 | let(:location_attributes) { attributes_for :location }
7 |
8 | before do
9 | sign_in create(:user)
10 | end
11 |
12 | describe 'GET #index' do
13 | before do
14 | Location.stub(:scoped) { locations }
15 | get 'index', format: 'json'
16 | end
17 |
18 | it_behaves_like 'a request with valid params', '200'
19 |
20 | it 'assigns unit_locations' do
21 | expect(controller.unit_locations).to eq locations
22 | end
23 | end
24 |
25 | describe 'GET #show' do
26 | before do
27 | Location.stub(:scoped) { locations }
28 | locations.stub(:find) { location }
29 |
30 | get 'show',
31 | id: location.id,
32 | format: 'json'
33 | end
34 |
35 | it_behaves_like 'a request with valid params', '200'
36 |
37 | it 'assigns unit_location' do
38 | expect(controller.unit_location).to eq location
39 | end
40 | end
41 |
42 | describe 'POST #create' do
43 | before do
44 | Location.any_instance.stub(:save) { true }
45 |
46 | post 'create',
47 | location: location_attributes,
48 | format: 'json'
49 | end
50 |
51 | it_behaves_like 'a request with valid params', '201'
52 | end
53 |
54 | describe 'PUT #update' do
55 | let!(:location) { stub_model Location }
56 |
57 | before do
58 | Location.stub(:find) { location }
59 | location.stub(:save) { true }
60 |
61 | put 'update',
62 | id: location.id,
63 | location: location_attributes,
64 | format: 'json'
65 | end
66 |
67 | it_behaves_like 'a request with valid params', '200'
68 | end
69 | end
70 |
--------------------------------------------------------------------------------
/spec/interactors/unit_fetcher_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe UnitFetcher do
4 | let(:units) { build_list :unit, 2 }
5 | let(:user) { build :user }
6 | let(:location) { build :location }
7 | let(:unit_fetcher) { UnitFetcher.perform }
8 |
9 | before do
10 | UnitFetcher.any_instance.stub(:user) { user }
11 | UnitFetcher.any_instance.stub(:location) { location }
12 | user.stub(:persisted?) { false }
13 | location.stub(:persisted?) { false }
14 | end
15 |
16 | describe '#units' do
17 | it 'should receive units for user' do
18 | user.should_receive(:units) { units }
19 | UnitFetcher.perform
20 | end
21 |
22 | it 'should not receive units for location' do
23 | user.stub(:units) { units }
24 |
25 | location.should_not_receive(:units)
26 | UnitFetcher.perform
27 | end
28 |
29 | it 'should receive units for location' do
30 | user.stub(:units) { [] }
31 |
32 | location.should_receive(:units) { units }
33 | UnitFetcher.perform
34 | end
35 |
36 | it 'should not receive includes for User' do
37 | user.stub(:units) { [] }
38 | location.stub(:units) { units }
39 |
40 | User.should_not_receive(:includes)
41 | UnitFetcher.perform
42 | end
43 |
44 | it 'should receive includes for User' do
45 | user.stub(:units) { [] }
46 | location.stub(:units) { [] }
47 |
48 | Unit.should_receive(:includes) { units }
49 | UnitFetcher.perform
50 | end
51 | end
52 |
53 | describe '#ancestors' do
54 | it 'should return user and location' do
55 | unit_fetcher.ancestors.should eq([:user, :location])
56 | end
57 |
58 | it 'should return user' do
59 | location.stub(:persisted?) { true }
60 | unit_fetcher.ancestors.should eq([:user])
61 | end
62 |
63 | it 'should return location' do
64 | user.stub(:persisted?) { true }
65 | unit_fetcher.ancestors.should eq([:location])
66 | end
67 | end
68 | end
69 |
--------------------------------------------------------------------------------
/script/ci_deploy:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | # Deploy app to heroku with semaphoreapp
4 | # http://fs.github.com/dev/ci-semaphoreapp
5 | #
6 | # Usage:
7 | # script/ci_deploy branch heroku-app-name heroku-colloborator-private-key-encoded-with-base64 heroku-colloborator-api-key
8 | # Options:
9 | # * branch - will trigger deploy only for this brunch
10 | # * heroku-app-name - name of your heroku application
11 | # * code will be pushed to git from user with this private key. Key should be encoded with base64: base64 /path/to/private_key
12 | # * heroku-colloborator-api-key - user's API key requred for run heroku run rake db:migrate
13 |
14 | require 'fileutils'
15 | require 'base64'
16 |
17 | BRANCH = ARGV.shift
18 | HEROKU_APP = ARGV.shift
19 | KEY_BASE64 = ARGV.shift
20 | API_KEY = ARGV.shift
21 | CURRENT_BRANCH = ENV['BRANCH_NAME']
22 |
23 | def prepare_ssh
24 | ssh_dir = File.expand_path('~/.ssh')
25 |
26 | FileUtils.mkdir(ssh_dir) unless File.exists?(ssh_dir)
27 |
28 | File.open("#{ssh_dir}/id_rsa", 'w') do |file|
29 | file.write(Base64.decode64(KEY_BASE64))
30 | end
31 |
32 | File.open("#{ssh_dir}/config", 'a') do |file|
33 | file << <<-HOST
34 | Host *heroku.com*
35 | StrictHostKeyChecking no
36 | UserKnownHostsFile=/dev/null
37 | HOST
38 | end
39 |
40 | File.chmod(0600, "#{ssh_dir}/id_rsa")
41 | end
42 |
43 | def prepare_git
44 | system('git remote rm heroku 2>/dev/null')
45 | system("git remote add heroku git@heroku.com:#{HEROKU_APP}.git") || exit(1)
46 | end
47 |
48 | def deploy
49 | system("git push --force heroku #{BRANCH}:master") || exit(1)
50 | end
51 |
52 | def run_migrations
53 | system("env HEROKU_API_KEY=#{API_KEY} bundle exec heroku run rake db:migrate") || exit(1)
54 | end
55 |
56 | if CURRENT_BRANCH == BRANCH
57 | puts "Going to deploy #{BRANCH}..."
58 |
59 | prepare_ssh
60 | prepare_git
61 | deploy
62 | run_migrations
63 |
64 | puts "Deployed!"
65 | else
66 | puts "Only #{BRANCH} allowed for depoy."
67 | end
--------------------------------------------------------------------------------
/config/initializers/rollbar.rb:
--------------------------------------------------------------------------------
1 | require 'rollbar/rails'
2 |
3 | Rollbar.configure do |config|
4 | config.access_token = ENV['ROLLBAR_KEY']
5 |
6 | # Without configuration, Rollbar is enabled by in all environments.
7 | # To disable in specific environments, set config.enabled=false.
8 | # Here we'll disable in 'test':
9 | if Rails.env.test? || Rails.env.development?
10 | config.enabled = false
11 | end
12 |
13 | # By default, Rollbar will try to call the `current_user` controller method
14 | # to fetch the logged-in user object, and then call that object's `id`,
15 | # `username`, and `email` methods to fetch those properties. To customize:
16 | # config.person_method = "my_current_user"
17 | # config.person_id_method = "my_id"
18 | # config.person_username_method = "my_username"
19 | # config.person_email_method = "my_email"
20 |
21 | # If you want to attach custom data to all exception and message reports,
22 | # provide a lambda like the following. It should return a hash.
23 | # config.custom_data_method = lambda { {:some_key => "some_value" } }
24 |
25 | # Add exception class names to the exception_level_filters hash to
26 | # change the level that exception is reported at. Note that if an exception
27 | # has already been reported and logged the level will need to be changed
28 | # via the rollbar interface.
29 | # Valid levels: 'critical', 'error', 'warning', 'info', 'debug', 'ignore'
30 | # 'ignore' will cause the exception to not be reported at all.
31 | # config.exception_level_filters.merge!('MyCriticalException' => 'critical')
32 |
33 | # Enable asynchronous reporting (uses girl_friday or Threading if girl_friday
34 | # is not installed)
35 | # config.use_async = true
36 | # Supply your own async handler:
37 | # config.async_handler = Proc.new { |payload|
38 | # Thread.new { Rollbar.process_payload(payload) }
39 | # }
40 |
41 | # Enable delayed reporting (using Sidekiq)
42 | # config.use_sidekiq = true
43 | # You can supply custom Sidekiq options:
44 | # config.use_sidekiq = { 'queue' => 'my_queue' }
45 | end
46 |
--------------------------------------------------------------------------------
/spec/controllers/units_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe UnitsController do
4 | let(:units) { build_list :unit, 2 }
5 | let(:unit) { build :unit, id: 1 }
6 | let(:location) { build :location, id: 1 }
7 | let(:user) { build :user, id: 1 }
8 | let(:unit_attributes) do
9 | attributes_for(:unit).merge(location_id: location.id, user_id: user.id)
10 | end
11 |
12 | before do
13 | sign_in create(:user)
14 | end
15 |
16 | describe 'GET #index' do
17 | before do
18 | controller.unit_fetcher.stub(:units) { units }
19 | get 'index', format: 'json'
20 | end
21 |
22 | it_behaves_like 'a request with valid params', '200'
23 |
24 | it 'assigns units' do
25 | expect(controller.units).to eq units
26 | end
27 | end
28 |
29 | describe 'GET #show' do
30 | before do
31 | Unit.stub(:scoped) { units }
32 | units.stub(:includes) { units }
33 | units.stub(:find) { unit }
34 |
35 | get 'show',
36 | id: unit.id,
37 | format: 'json'
38 | end
39 |
40 | it_behaves_like 'a request with valid params', '200'
41 |
42 | it 'assigns unit' do
43 | expect(controller.unit).to eq unit
44 | end
45 | end
46 |
47 | context 'update and create' do
48 | before do
49 | Location.stub(:find) { location }
50 | User.stub(:find) { user }
51 | location.stub(:persisted?) { true }
52 | end
53 |
54 | describe 'POST #create' do
55 | before do
56 | post 'create',
57 | unit: unit_attributes,
58 | format: 'json'
59 | end
60 |
61 | it_behaves_like 'a request with valid params', '201'
62 | end
63 |
64 | describe 'PUT #update' do
65 | before do
66 | Unit.stub(:scoped) { units }
67 | units.stub(:includes) { units }
68 | units.stub(:find) { unit }
69 |
70 | put 'update',
71 | id: unit.id,
72 | unit: unit_attributes,
73 | format: 'json'
74 | end
75 |
76 | it_behaves_like 'a request with valid params', '200'
77 |
78 | it 'assign attributes to unit' do
79 | expect(controller.unit).to eq unit
80 | end
81 | end
82 | end
83 | end
84 |
--------------------------------------------------------------------------------
/spec/api/locations_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'resource location' do
4 | let!(:user) { create :user }
5 | let(:params) { { authentication_token: user.authentication_token } }
6 | let(:location_attributes) { attributes_for(:location) }
7 | let(:params_with_location_attributes) { params.merge(location: location_attributes) }
8 | subject { json_response_body }
9 |
10 | describe 'list' do
11 | let!(:locations) { create_list :location, 2 }
12 | let(:method) { :get }
13 | let(:url) { '/locations' }
14 |
15 | it_behaves_like 'a method that requires an authentication'
16 |
17 | context 'with authentication token' do
18 | before { get url, params }
19 |
20 | its(:first) { should be_a_location_representation(locations.first) }
21 | its(:count) { should eq(2) }
22 | end
23 | end
24 |
25 | describe 'single' do
26 | let!(:location) { create :location }
27 | let(:method) { :get }
28 | let(:url) { "/locations/#{location.id}" }
29 |
30 | it_behaves_like 'a method that requires an authentication'
31 |
32 | context 'with authentication token' do
33 | before { get url, params }
34 |
35 | it { should be_a_location_representation(location) }
36 | end
37 | end
38 |
39 | describe 'POST /locations' do
40 | let(:method) { :post }
41 | let(:url) { "/locations" }
42 |
43 | it_behaves_like 'a method that requires an authentication'
44 |
45 | context 'with authentication token' do
46 | before { post url, params_with_location_attributes }
47 |
48 | it { should be_a_location_representation(Location.last) }
49 | end
50 | end
51 |
52 | describe 'PUT /locations/:id' do
53 | let!(:location) { create :location }
54 | let(:method) { :put }
55 | let(:url) { "/locations/#{location.id}" }
56 |
57 | it_behaves_like 'a method that requires an authentication'
58 |
59 | context 'with authentication token' do
60 | before do
61 | put url, params_with_location_attributes
62 |
63 | location.assign_attributes(location_attributes)
64 | end
65 |
66 | it { should be_a_location_representation(location) }
67 | end
68 | end
69 | end
70 |
--------------------------------------------------------------------------------
/script/bootstrap:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | require 'fileutils'
4 |
5 | def rails_root
6 | @rails_root ||= File.expand_path('../../', __FILE__)
7 | end
8 |
9 | def check(key)
10 | FileUtils.mkdir('tmp') unless File.exists?('tmp')
11 | cache_file = "tmp/.#{key}"
12 |
13 | if File.exists?(cache_file)
14 | old_version = File.read(cache_file)
15 | else
16 | old_version = nil
17 | end
18 |
19 | version = yield(old_version)
20 | File.open(cache_file, 'w') { |f| f.puts(version || 'cached') }
21 | end
22 |
23 | def setup_database_yml
24 | unless File.exists?(File.join(rails_root, 'config/database.yml'))
25 | puts 'Database configuration file is missing, installing...'
26 | FileUtils.cp(File.join(rails_root, 'config/database.yml.example'), File.join(rails_root, 'config/database.yml'))
27 | end
28 | end
29 |
30 | def setup_dotenv
31 | unless File.exists?(File.join(rails_root, '.env'))
32 | puts 'DotEnv configuration file is missing, installing...'
33 | FileUtils.cp(File.join(rails_root, '.env.example'), File.join(rails_root, '.env'))
34 | end
35 | end
36 |
37 | def install_bundler
38 | check(:bundler) do |old_version|
39 | break if old_version
40 |
41 | unless system('which bundle > /dev/null')
42 | puts 'Bundler missing, installing...'
43 | system('gem install bundler --no-ri --no-rdoc') || exit(1)
44 | end
45 | end
46 | end
47 |
48 | def install_gems(without = 'production staging')
49 | check(:gemfile) do |old_version|
50 | # check both Gemfile and Gemfile.lock as there might be local changes that hasn't been bundled yet
51 | version = File.read('Gemfile') + File.read('Gemfile.lock')
52 |
53 | if version != old_version
54 | puts 'Gemfile changed, bundling...'
55 | system("bundle install --path vendor/bundle --binstubs --without production staging #{without}") || exit(1)
56 | end
57 |
58 | version
59 | end
60 | end
61 |
62 | def migrate_db
63 | check(:schema) do |old_version|
64 | version = File.readlines('db/schema.rb').find { |line| line.include?('define(:version') }
65 |
66 | if version != old_version
67 | puts 'Schema changed, updating databases...'
68 | system('bundle exec rake db:create db:migrate db:test:prepare') || exit(1)
69 | end
70 |
71 | version
72 | end
73 | end
74 |
75 | is_ci = ARGV.shift == 'ci'
76 |
77 | setup_database_yml
78 | setup_dotenv
79 | install_bundler
80 | install_gems(is_ci ? 'development' : '')
81 | migrate_db
82 |
83 | puts 'Everything is up to date.'
84 |
--------------------------------------------------------------------------------
/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | InventoryReborn::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # Code is not reloaded between requests
5 | config.cache_classes = true
6 |
7 | # Full error reports are disabled and caching is turned on
8 | config.consider_all_requests_local = false
9 | config.action_controller.perform_caching = true
10 |
11 | # Disable Rails's static asset server (Apache or nginx will already do this)
12 | config.serve_static_assets = false
13 |
14 | # Compress JavaScripts and CSS
15 | config.assets.compress = true
16 |
17 | # Don't fallback to assets pipeline if a precompiled asset is missed
18 | config.assets.compile = false
19 |
20 | # Generate digests for assets URLs
21 | config.assets.digest = true
22 |
23 | # Defaults to nil and saved in location specified by config.assets.prefix
24 | # config.assets.manifest = YOUR_PATH
25 |
26 | # Specifies the header that your server uses for sending files
27 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
28 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
29 |
30 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
31 | # config.force_ssl = true
32 |
33 | # See everything in the log (default is :info)
34 | # config.log_level = :debug
35 |
36 | # Prepend all log lines with the following tags
37 | # config.log_tags = [ :subdomain, :uuid ]
38 |
39 | # Use a different logger for distributed setups
40 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
41 |
42 | # Use a different cache store in production
43 | # config.cache_store = :mem_cache_store
44 |
45 | # Enable serving of images, stylesheets, and JavaScripts from an asset server
46 | # config.action_controller.asset_host = "http://assets.example.com"
47 |
48 | # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
49 | # config.assets.precompile += %w( search.js )
50 |
51 | # Disable delivery errors, bad email addresses will be ignored
52 | # config.action_mailer.raise_delivery_errors = false
53 |
54 | # Enable threaded mode
55 | # config.threadsafe!
56 |
57 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
58 | # the I18n.default_locale when a translation can not be found)
59 | config.i18n.fallbacks = true
60 |
61 | # Send deprecation notices to registered listeners
62 | config.active_support.deprecation = :notify
63 |
64 | # Log the query plan for queries taking more than this (works
65 | # with SQLite, MySQL, and PostgreSQL)
66 | # config.active_record.auto_explain_threshold_in_seconds = 0.5
67 | end
68 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Example of Rails app with API
2 |
3 | ## API
4 |
5 | Status of the API could be checked at http://localhost:5000/api_taster
6 |
7 | ### Unauthenticated user:
8 |
9 | * POST `/users/sign_in.json`: Authenticate user with given email and password
10 | * GET `/posts.json`: list posts
11 | * GET `/posts/:id.json`: get a single post
12 |
13 | ### Authenticated as user:
14 |
15 | * GET `/user/comments.json`: list comments for currently authenticated user
16 | * POST `/user/comments.json`: create comment
17 |
18 | ## What's included
19 |
20 | Application currently based on Rails 3.2 stable branch and Ruby 1.9
21 |
22 | ### Application gems:
23 |
24 | * [Decent Exposure](https://github.com/voxdolo/decent_exposure) for DRY controllers
25 | * [Thin](https://github.com/macournoyer/thin) as rails web server
26 |
27 | ### Development gems
28 |
29 | * [Foreman](https://github.com/ddollar/foreman) for managing development stack with Procfile
30 | * [Letter Opener](https://github.com/ryanb/letter_opener) for preview mail in the browser instead of sending
31 | * [Mail Safe](https://github.com/myronmarston/mail_safe) keep ActionMailer emails from escaping into the wild during development
32 | * [Bullet](https://github.com/flyerhzm/bullet) gem to kill N+1 queries and unused eager loading
33 | * [Rails Best Practices](https://github.com/railsbp/rails_best_practices) code metric tool
34 | * [Brakeman](https://github.com/presidentbeef/brakeman) static analysis security vulnerability scanner
35 |
36 | ### Testing gems
37 |
38 | * [Factory Girl](https://github.com/thoughtbot/factory_girl) for easier creation of test data
39 | * [RSpec](https://github.com/rspec/rspec) for awesome, readable isolation testing
40 | * [Shoulda Matchers](http://github.com/thoughtbot/shoulda-matchers) for frequently needed Rails and RSpec matchers
41 | * [Email Spec](https://github.com/bmabey/email-spec) Collection of rspec matchers and cucumber steps for testing emails
42 | * [ApiTaster](https://github.com/fredwu/api_taster) A quick and easy way to visually test your Rails application's API.
43 |
44 | ### Initializes
45 |
46 | * `01_config.rb` - shortcut for getting application config with `app_config`
47 | * `mailer.rb` - setup default hosts for mailer from configuration
48 | * `time_formats.rb` - setup default time formats, so you can use them like object.create_at.to_s(:us_time)
49 | * `requires.rb` - automatically requires everything in lib/ & lib/extensions
50 |
51 | ### Scripts
52 |
53 | * `script/bootstrap` - setup required gems and migrate db if needed
54 | * `script/quality` - runs brakeman and rails_best_practices for the app
55 | * `script/ci` - should be used in the CI, checkout .travis.yml for example
56 | * `script/ci_deploy` - should be used in [Semaphoreapp CI to deploy code to Heroku](http://tatsoft.ru/ci-semaphoreapp)
57 |
--------------------------------------------------------------------------------
/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 to check this file into your version control system.
13 |
14 | ActiveRecord::Schema.define(:version => 20130614115836) do
15 |
16 | create_table "locations", :force => true do |t|
17 | t.string "name"
18 | t.datetime "created_at", :null => false
19 | t.datetime "updated_at", :null => false
20 | end
21 |
22 | create_table "units", :force => true do |t|
23 | t.string "unit_type"
24 | t.integer "inv_id"
25 | t.string "name"
26 | t.text "description"
27 | t.integer "user_id"
28 | t.integer "location_id"
29 | t.boolean "on_depot", :default => false
30 | t.boolean "out_of_order", :default => false
31 | t.text "out_of_order_note"
32 | t.datetime "created_at", :null => false
33 | t.datetime "updated_at", :null => false
34 | end
35 |
36 | add_index "units", ["inv_id"], :name => "index_units_on_inv_id"
37 | add_index "units", ["location_id"], :name => "index_units_on_location_id"
38 | add_index "units", ["user_id"], :name => "index_units_on_user_id"
39 |
40 | create_table "users", :force => true do |t|
41 | t.string "email", :default => "", :null => false
42 | t.string "encrypted_password", :default => "", :null => false
43 | t.string "reset_password_token"
44 | t.datetime "reset_password_sent_at"
45 | t.datetime "remember_created_at"
46 | t.integer "sign_in_count", :default => 0
47 | t.datetime "current_sign_in_at"
48 | t.datetime "last_sign_in_at"
49 | t.string "current_sign_in_ip"
50 | t.string "last_sign_in_ip"
51 | t.string "authentication_token"
52 | t.string "full_name"
53 | t.datetime "created_at", :null => false
54 | t.datetime "updated_at", :null => false
55 | end
56 |
57 | add_index "users", ["authentication_token"], :name => "index_users_on_authentication_token", :unique => true
58 | add_index "users", ["email"], :name => "index_users_on_email", :unique => true
59 | add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
60 |
61 | end
62 |
--------------------------------------------------------------------------------
/config/application.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path('../boot', __FILE__)
2 |
3 | # Pick the frameworks you want:
4 | require 'active_record/railtie'
5 | require 'action_controller/railtie'
6 | require 'action_mailer/railtie'
7 | require 'active_resource/railtie'
8 | require 'sprockets/railtie'
9 | # require "rails/test_unit/railtie"
10 |
11 | if defined?(Bundler)
12 | # If you precompile assets before deploying to production, use this line
13 | Bundler.require(*Rails.groups(assets: %w(development test)))
14 | # If you want your assets lazily compiled in production, use this line
15 | # Bundler.require(:default, :assets, Rails.env)
16 | end
17 |
18 | module InventoryReborn
19 | class Application < Rails::Application
20 | # Settings in config/environments/* take precedence over those specified here.
21 | # Application configuration should go into files in config/initializers
22 | # -- all .rb files in that directory are automatically loaded.
23 |
24 | # Custom directories with classes and modules you want to be autoloadable.
25 | # config.autoload_paths += %W(#{config.root}/extras)
26 |
27 | # Only load the plugins named here, in the order given (default is alphabetical).
28 | # :all can be used as a placeholder for all plugins not explicitly named.
29 | # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
30 |
31 | # Activate observers that should always be running.
32 | # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
33 |
34 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
35 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
36 | # config.time_zone = 'Central Time (US & Canada)'
37 |
38 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
39 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
40 | # config.i18n.default_locale = :de
41 |
42 | # Configure the default encoding used in templates for Ruby 1.9.
43 | config.encoding = 'utf-8'
44 |
45 | # Configure sensitive parameters which will be filtered from the log file.
46 | config.filter_parameters += [:password]
47 |
48 | # Enable escaping HTML in JSON.
49 | config.active_support.escape_html_entities_in_json = true
50 |
51 | # Use SQL instead of Active Record's schema dumper when creating the database.
52 | # This is necessary if your schema can't be completely dumped by the schema dumper,
53 | # like if you have constraints or database-specific column types
54 | # config.active_record.schema_format = :sql
55 |
56 | # We use ActiveModel::ForbiddenAttributesProtection instead
57 | config.active_record.whitelist_attributes = false
58 |
59 | # Enable the asset pipeline
60 | config.assets.enabled = true
61 |
62 | # Version of your assets, change this if you want to expire all your assets
63 | config.assets.version = '1.0'
64 |
65 | # If you are deploying Rails 3.1+ on Heroku, you may want to set:
66 | config.assets.initialize_on_precompile = false
67 |
68 | # By default Rails API does not include the session middleware.
69 | # Add the middleware back in to application b/c it requred by Devise and Warden
70 | config.middleware.use ActionDispatch::Session::CookieStore
71 |
72 | # Add Rack::MethodOverride middleware in order to support DELETE/PUT requests
73 | # in api_taster
74 | config.middleware.use Rack::MethodOverride
75 |
76 | # Parameter keys that are not explicitly permitted will be raised as exception
77 | config.action_controller.action_on_unpermitted_parameters = :raise
78 |
79 | # Default host for action mailer, initializers/mailer.rb
80 | config.host = 'localhost:5000'
81 | end
82 | end
83 |
--------------------------------------------------------------------------------
/config/locales/devise.en.yml:
--------------------------------------------------------------------------------
1 | # Additional translations at https://github.com/plataformatec/devise/wiki/I18n
2 |
3 | en:
4 | devise:
5 | confirmations:
6 | confirmed: "Your account was successfully confirmed. You are now signed in."
7 | send_instructions: "You will receive an email with instructions about how to confirm your account in a few minutes."
8 | send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions about how to confirm your account in a few minutes."
9 | failure:
10 | already_authenticated: "You are already signed in."
11 | inactive: "Your account was not activated yet."
12 | invalid: "Invalid email or password."
13 | invalid_token: "Invalid authentication token."
14 | locked: "Your account is locked."
15 | not_found_in_database: "Invalid email or password."
16 | timeout: "Your session expired, please sign in again to continue."
17 | unauthenticated: "You need to sign in or sign up before continuing."
18 | unconfirmed: "You have to confirm your account before continuing."
19 | mailer:
20 | confirmation_instructions:
21 | subject: "Confirmation instructions"
22 | reset_password_instructions:
23 | subject: "Reset password instructions"
24 | unlock_instructions:
25 | subject: "Unlock Instructions"
26 | omniauth_callbacks:
27 | failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
28 | success: "Successfully authenticated from %{kind} account."
29 | passwords:
30 | no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
31 | send_instructions: "You will receive an email with instructions about how to reset your password in a few minutes."
32 | send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
33 | updated: "Your password was changed successfully. You are now signed in."
34 | updated_not_active: "Your password was changed successfully."
35 | registrations:
36 | destroyed: "Bye! Your account was successfully cancelled. We hope to see you again soon."
37 | signed_up: "Welcome! You have signed up successfully."
38 | signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
39 | signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
40 | signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please open the link to activate your account."
41 | update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and click on the confirm link to finalize confirming your new email address."
42 | updated: "You updated your account successfully."
43 | sessions:
44 | signed_in: "Signed in successfully."
45 | signed_out: "Signed out successfully."
46 | unlocks:
47 | send_instructions: "You will receive an email with instructions about how to unlock your account in a few minutes."
48 | send_paranoid_instructions: "If your account exists, you will receive an email with instructions about how to unlock it in a few minutes."
49 | unlocked: "Your account has been unlocked successfully. Please sign in to continue."
50 | errors:
51 | messages:
52 | already_confirmed: "was already confirmed, please try signing in"
53 | confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
54 | expired: "has expired, please request a new one"
55 | not_found: "not found"
56 | not_locked: "was not locked"
57 | not_saved:
58 | one: "1 error prohibited this %{resource} from being saved:"
59 | other: "%{count} errors prohibited this %{resource} from being saved:"
60 |
--------------------------------------------------------------------------------
/spec/api/units_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'resource units' do
4 | let!(:user) { create :user }
5 | let!(:location) { create :location }
6 | let(:params) { { authentication_token: user.authentication_token } }
7 | let(:params_with_unit_attributes) { params.merge(unit: unit_attributes) }
8 | let(:unit_attributes) do
9 | attributes_for(:unit).
10 | merge(location_id: location.id, user_id: user.id)
11 | end
12 | subject { json_response_body }
13 |
14 | describe 'list' do
15 | let!(:units) { create_list :unit, 2 }
16 | let!(:user_units) { create_list :unit, 2, user: user }
17 | let!(:location_units) { create_list :unit, 2, location: location }
18 |
19 | describe 'GET /units' do
20 | let(:method) { :get }
21 | let(:url) { '/units' }
22 |
23 | it_behaves_like 'a method that requires an authentication'
24 |
25 | context 'with authentication token' do
26 | before { get url, params }
27 |
28 | it { should be_a_kind_of Array }
29 | its(:first) { should be_a_unit_representation(units.first) }
30 | its(:count) { should eq(6) }
31 |
32 | context 'have user' do
33 | subject { json_response_body.first['user'] }
34 | it { should be_a_user_representation(units.first.user) }
35 | end
36 |
37 | context 'have location' do
38 | subject { json_response_body.first['location'] }
39 | it { should be_a_location_representation(units.first.location) }
40 | end
41 | end
42 | end
43 |
44 | describe 'GET /users/:id/units' do
45 | let(:method) { :get }
46 | let(:url) { "/users/#{user.id}/units" }
47 |
48 | it_behaves_like 'a method that requires an authentication'
49 |
50 | context 'with authentication token' do
51 | before { get url, params }
52 |
53 | it { should be_a_kind_of Array }
54 | its(:first) { should be_a_unit_representation(user_units.first) }
55 | its(:count) { should eq(2) }
56 |
57 | context 'without user' do
58 | subject { json_response_body.first['user'] }
59 | it { should be_nil }
60 | end
61 |
62 | context 'have location' do
63 | subject { json_response_body.first['location'] }
64 | it { should be_a_location_representation(user_units.first.location) }
65 | end
66 | end
67 | end
68 |
69 | describe 'GET /locations/:id/units' do
70 | let(:method) { :get }
71 | let(:url) { "/locations/#{location.id}/units" }
72 |
73 | it_behaves_like 'a method that requires an authentication'
74 |
75 | context 'with authentication token' do
76 | before { get url, params }
77 |
78 | it { should be_a_kind_of Array }
79 | its(:first) { should be_a_unit_representation(location_units.first) }
80 | its(:count) { should eq(2) }
81 |
82 | context 'have user' do
83 | subject { json_response_body.first['user'] }
84 | it { should be_a_user_representation(location_units.first.user) }
85 | end
86 |
87 | context 'without location' do
88 | subject { json_response_body.first['location'] }
89 | it { should be_nil }
90 | end
91 | end
92 | end
93 | end
94 |
95 | describe 'GET /units/:id' do
96 | let!(:unit) { create :unit, user: user, location: location }
97 | let(:method) { :get }
98 | let(:url) { "/units/#{unit.id}" }
99 |
100 | it_behaves_like 'a method that requires an authentication'
101 |
102 | context 'with authentication token' do
103 | before { get url, params }
104 |
105 | it { should be_a_unit_representation(unit) }
106 |
107 | context 'have user' do
108 | subject { json_response_body['user'] }
109 | it { should be_a_user_representation(user) }
110 | end
111 |
112 | context 'have location' do
113 | subject { json_response_body['location'] }
114 | it { should be_a_location_representation(location) }
115 | end
116 | end
117 | end
118 |
119 | describe 'POST /units' do
120 | let(:method) { :post }
121 | let(:url) { "/units" }
122 |
123 | it_behaves_like 'a method that requires an authentication'
124 |
125 | context 'with authentication token' do
126 | before { post url, params_with_unit_attributes }
127 |
128 | it { should be_a_unit_representation(user.units.last) }
129 | end
130 | end
131 |
132 | describe 'PUT /units/:id' do
133 | let!(:unit) { create :unit, user: user, location: location }
134 | let(:method) { :put }
135 | let(:url) { "/units/#{unit.id}" }
136 |
137 | it_behaves_like 'a method that requires an authentication'
138 |
139 | context 'with authentication token' do
140 | before do
141 | put url, params_with_unit_attributes
142 |
143 | unit.assign_attributes(unit_attributes)
144 | end
145 |
146 | it { should be_a_unit_representation(unit) }
147 | end
148 | end
149 | end
150 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GIT
2 | remote: git://github.com/james2m/seedbank.git
3 | revision: c7a272751336f0d17103028f45b88eac62cbedd7
4 | specs:
5 | seedbank (0.3.0.pre2)
6 |
7 | GEM
8 | remote: https://rubygems.org/
9 | specs:
10 | actionmailer (3.2.13)
11 | actionpack (= 3.2.13)
12 | mail (~> 2.5.3)
13 | actionpack (3.2.13)
14 | activemodel (= 3.2.13)
15 | activesupport (= 3.2.13)
16 | builder (~> 3.0.0)
17 | erubis (~> 2.7.0)
18 | journey (~> 1.0.4)
19 | rack (~> 1.4.5)
20 | rack-cache (~> 1.2)
21 | rack-test (~> 0.6.1)
22 | sprockets (~> 2.2.1)
23 | active_model_serializers (0.8.1)
24 | activemodel (>= 3.0)
25 | activemodel (3.2.13)
26 | activesupport (= 3.2.13)
27 | builder (~> 3.0.0)
28 | activerecord (3.2.13)
29 | activemodel (= 3.2.13)
30 | activesupport (= 3.2.13)
31 | arel (~> 3.0.2)
32 | tzinfo (~> 0.3.29)
33 | activeresource (3.2.13)
34 | activemodel (= 3.2.13)
35 | activesupport (= 3.2.13)
36 | activesupport (3.2.13)
37 | i18n (= 0.6.1)
38 | multi_json (~> 1.0)
39 | addressable (2.3.5)
40 | api_taster (0.7.0)
41 | bootstrap-sass (~> 2.1)
42 | jquery-rails
43 | rails (~> 3.2.0)
44 | redcarpet
45 | remotipart (~> 1.0)
46 | sass-rails
47 | arel (3.0.2)
48 | awesome_print (1.1.0)
49 | bcrypt-ruby (3.0.1)
50 | binding_of_caller (0.7.2)
51 | debug_inspector (>= 0.0.1)
52 | bootstrap-sass (2.3.2.2)
53 | sass (~> 3.2)
54 | brakeman (2.0.0)
55 | erubis (~> 2.6)
56 | fastercsv (~> 1.5)
57 | haml (>= 3.0, < 5.0)
58 | highline (~> 1.6.19)
59 | multi_json (~> 1.2)
60 | ruby2ruby (~> 2.0.5)
61 | ruby_parser (~> 3.1.1)
62 | sass (~> 3.0)
63 | slim (~> 1.3.6)
64 | terminal-table (~> 1.4)
65 | builder (3.0.4)
66 | bullet (4.6.0)
67 | uniform_notifier
68 | capybara (2.1.0)
69 | mime-types (>= 1.16)
70 | nokogiri (>= 1.3.3)
71 | rack (>= 1.0.0)
72 | rack-test (>= 0.5.4)
73 | xpath (~> 2.0)
74 | choice (0.1.6)
75 | code_analyzer (0.3.2)
76 | sexp_processor
77 | coderay (1.0.9)
78 | colored (1.2)
79 | columnize (0.3.6)
80 | crack (0.4.0)
81 | safe_yaml (~> 0.9.0)
82 | daemons (1.1.9)
83 | database_cleaner (1.0.1)
84 | debug_inspector (0.0.2)
85 | debugger (1.6.5)
86 | columnize (>= 0.3.1)
87 | debugger-linecache (~> 1.2.0)
88 | debugger-ruby_core_source (~> 1.3.1)
89 | debugger-linecache (1.2.0)
90 | debugger-ruby_core_source (1.3.1)
91 | decent_exposure (2.2.0)
92 | devise (2.2.4)
93 | bcrypt-ruby (~> 3.0)
94 | orm_adapter (~> 0.1)
95 | railties (~> 3.1)
96 | warden (~> 1.2.1)
97 | diff-lcs (1.2.4)
98 | dotenv (0.8.0)
99 | email_spec (1.4.0)
100 | launchy (~> 2.1)
101 | mail (~> 2.2)
102 | erubis (2.7.0)
103 | eventmachine (1.0.3)
104 | factory_girl (4.2.0)
105 | activesupport (>= 3.0.0)
106 | factory_girl_rails (4.2.1)
107 | factory_girl (~> 4.2.0)
108 | railties (>= 3.0.0)
109 | faker (1.1.2)
110 | i18n (~> 0.5)
111 | fastercsv (1.5.5)
112 | ffi (1.9.0)
113 | foreman (0.63.0)
114 | dotenv (>= 0.7)
115 | thor (>= 0.13.6)
116 | formatador (0.2.4)
117 | guard (1.8.1)
118 | formatador (>= 0.2.4)
119 | listen (>= 1.0.0)
120 | lumberjack (>= 1.0.2)
121 | pry (>= 0.9.10)
122 | thor (>= 0.14.6)
123 | guard-rspec (3.0.2)
124 | guard (>= 1.8)
125 | rspec (~> 2.13)
126 | haml (4.0.3)
127 | tilt
128 | highline (1.6.19)
129 | hike (1.2.3)
130 | i18n (0.6.1)
131 | interactor (2.0.0)
132 | interactor-rails (1.0.1)
133 | interactor (< 3)
134 | rails (>= 3, < 5)
135 | journey (1.0.4)
136 | jquery-rails (3.0.4)
137 | railties (>= 3.0, < 5.0)
138 | thor (>= 0.14, < 2.0)
139 | json (1.8.0)
140 | launchy (2.3.0)
141 | addressable (~> 2.3)
142 | letter_opener (1.1.2)
143 | launchy (~> 2.2)
144 | listen (1.2.2)
145 | rb-fsevent (>= 0.9.3)
146 | rb-inotify (>= 0.9)
147 | rb-kqueue (>= 0.2)
148 | lumberjack (1.0.4)
149 | mail (2.5.4)
150 | mime-types (~> 1.16)
151 | treetop (~> 1.4.8)
152 | mail_safe (0.3.1)
153 | actionmailer (>= 1.3.6)
154 | method_source (0.8.1)
155 | mime-types (1.23)
156 | mini_portile (0.5.0)
157 | multi_json (1.7.7)
158 | nokogiri (1.6.0)
159 | mini_portile (~> 0.5.0)
160 | orm_adapter (0.4.0)
161 | pg (0.15.1)
162 | polyglot (0.3.3)
163 | pry (0.9.12.2)
164 | coderay (~> 1.0.5)
165 | method_source (~> 0.8)
166 | slop (~> 3.4)
167 | pry-debugger (0.2.2)
168 | debugger (~> 1.3)
169 | pry (~> 0.9.10)
170 | pry-rails (0.3.2)
171 | pry (>= 0.9.10)
172 | pry-remote (0.1.7)
173 | pry (~> 0.9)
174 | slop (~> 3.0)
175 | pry-stack_explorer (0.4.9.1)
176 | binding_of_caller (>= 0.7)
177 | pry (>= 0.9.11)
178 | rack (1.4.5)
179 | rack-cache (1.2)
180 | rack (>= 0.4)
181 | rack-ssl (1.3.3)
182 | rack
183 | rack-test (0.6.2)
184 | rack (>= 1.0)
185 | rails (3.2.13)
186 | actionmailer (= 3.2.13)
187 | actionpack (= 3.2.13)
188 | activerecord (= 3.2.13)
189 | activeresource (= 3.2.13)
190 | activesupport (= 3.2.13)
191 | bundler (~> 1.0)
192 | railties (= 3.2.13)
193 | rails-api (0.1.0)
194 | actionpack (>= 3.2.11)
195 | railties (>= 3.2.11)
196 | tzinfo (~> 0.3.31)
197 | rails-erd (1.1.0)
198 | activerecord (>= 3.0)
199 | activesupport (>= 3.0)
200 | choice (~> 0.1.6)
201 | ruby-graphviz (~> 1.0.4)
202 | rails_best_practices (1.13.8)
203 | activesupport
204 | awesome_print
205 | code_analyzer
206 | colored
207 | erubis
208 | i18n
209 | ruby-progressbar
210 | railties (3.2.13)
211 | actionpack (= 3.2.13)
212 | activesupport (= 3.2.13)
213 | rack-ssl (~> 1.3.2)
214 | rake (>= 0.8.7)
215 | rdoc (~> 3.4)
216 | thor (>= 0.14.6, < 2.0)
217 | rake (10.1.0)
218 | rb-fsevent (0.9.3)
219 | rb-inotify (0.9.0)
220 | ffi (>= 0.5.0)
221 | rb-kqueue (0.2.0)
222 | ffi (>= 0.5.0)
223 | rdoc (3.12.2)
224 | json (~> 1.4)
225 | redcarpet (3.0.0)
226 | remotipart (1.2.1)
227 | rollbar (0.10.11)
228 | multi_json (~> 1.5)
229 | rspec (2.13.0)
230 | rspec-core (~> 2.13.0)
231 | rspec-expectations (~> 2.13.0)
232 | rspec-mocks (~> 2.13.0)
233 | rspec-core (2.13.1)
234 | rspec-expectations (2.13.0)
235 | diff-lcs (>= 1.1.3, < 2.0)
236 | rspec-mocks (2.13.1)
237 | rspec-rails (2.13.2)
238 | actionpack (>= 3.0)
239 | activesupport (>= 3.0)
240 | railties (>= 3.0)
241 | rspec-core (~> 2.13.0)
242 | rspec-expectations (~> 2.13.0)
243 | rspec-mocks (~> 2.13.0)
244 | ruby-graphviz (1.0.9)
245 | ruby-progressbar (1.1.1)
246 | ruby2ruby (2.0.6)
247 | ruby_parser (~> 3.1)
248 | sexp_processor (~> 4.0)
249 | ruby_parser (3.1.3)
250 | sexp_processor (~> 4.1)
251 | safe_yaml (0.9.3)
252 | sass (3.2.9)
253 | sass-rails (3.2.6)
254 | railties (~> 3.2.0)
255 | sass (>= 3.1.10)
256 | tilt (~> 1.3)
257 | sexp_processor (4.2.1)
258 | shoulda-matchers (2.2.0)
259 | activesupport (>= 3.0.0)
260 | simplecov (0.7.1)
261 | multi_json (~> 1.0)
262 | simplecov-html (~> 0.7.1)
263 | simplecov-html (0.7.1)
264 | slim (1.3.9)
265 | temple (~> 0.6.3)
266 | tilt (~> 1.3, >= 1.3.3)
267 | slop (3.4.5)
268 | sprockets (2.2.2)
269 | hike (~> 1.2)
270 | multi_json (~> 1.0)
271 | rack (~> 1.0)
272 | tilt (~> 1.1, != 1.3.0)
273 | strong_parameters (0.2.1)
274 | actionpack (~> 3.0)
275 | activemodel (~> 3.0)
276 | railties (~> 3.0)
277 | temple (0.6.5)
278 | terminal-table (1.4.5)
279 | thin (1.5.1)
280 | daemons (>= 1.0.9)
281 | eventmachine (>= 0.12.6)
282 | rack (>= 1.0.0)
283 | thor (0.18.1)
284 | tilt (1.4.1)
285 | treetop (1.4.14)
286 | polyglot
287 | polyglot (>= 0.3.1)
288 | tzinfo (0.3.37)
289 | uniform_notifier (1.2.0)
290 | warden (1.2.1)
291 | rack (>= 1.0)
292 | webmock (1.12.3)
293 | addressable (>= 2.2.7)
294 | crack (>= 0.3.2)
295 | xpath (2.0.0)
296 | nokogiri (~> 1.3)
297 | zeus (0.13.3)
298 | method_source (>= 0.6.7)
299 |
300 | PLATFORMS
301 | ruby
302 |
303 | DEPENDENCIES
304 | active_model_serializers
305 | api_taster
306 | brakeman
307 | bullet
308 | capybara
309 | database_cleaner
310 | decent_exposure
311 | devise
312 | dotenv
313 | email_spec
314 | factory_girl_rails
315 | faker
316 | foreman
317 | guard-rspec
318 | interactor-rails
319 | letter_opener
320 | mail_safe
321 | pg
322 | pry-debugger
323 | pry-rails
324 | pry-remote
325 | pry-stack_explorer
326 | rails (= 3.2.13)
327 | rails-api
328 | rails-erd
329 | rails_best_practices
330 | rb-fsevent
331 | rollbar
332 | rspec-rails
333 | seedbank!
334 | shoulda-matchers
335 | simplecov
336 | strong_parameters
337 | thin
338 | webmock
339 | zeus
340 |
--------------------------------------------------------------------------------
/config/initializers/devise.rb:
--------------------------------------------------------------------------------
1 | # Use this hook to configure devise mailer, warden hooks and so forth.
2 | # Many of these configuration options can be set straight in your model.
3 | Devise.setup do |config|
4 | # ==> Mailer Configuration
5 | # Configure the e-mail address which will be shown in Devise::Mailer,
6 | # note that it will be overwritten if you use your own mailer class with default "from" parameter.
7 | config.mailer_sender = "please-change-me-at-config-initializers-devise@example.com"
8 |
9 | # Configure the class responsible to send e-mails.
10 | # config.mailer = "Devise::Mailer"
11 |
12 | # ==> ORM configuration
13 | # Load and configure the ORM. Supports :active_record (default) and
14 | # :mongoid (bson_ext recommended) by default. Other ORMs may be
15 | # available as additional gems.
16 | require 'devise/orm/active_record'
17 |
18 | # ==> Configuration for any authentication mechanism
19 | # Configure which keys are used when authenticating a user. The default is
20 | # just :email. You can configure it to use [:username, :subdomain], so for
21 | # authenticating a user, both parameters are required. Remember that those
22 | # parameters are used only when authenticating and not when retrieving from
23 | # session. If you need permissions, you should implement that in a before filter.
24 | # You can also supply a hash where the value is a boolean determining whether
25 | # or not authentication should be aborted when the value is not present.
26 | # config.authentication_keys = [ :email ]
27 |
28 | # Configure parameters from the request object used for authentication. Each entry
29 | # given should be a request method and it will automatically be passed to the
30 | # find_for_authentication method and considered in your model lookup. For instance,
31 | # if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
32 | # The same considerations mentioned for authentication_keys also apply to request_keys.
33 | # config.request_keys = []
34 |
35 | # Configure which authentication keys should be case-insensitive.
36 | # These keys will be downcased upon creating or modifying a user and when used
37 | # to authenticate or find a user. Default is :email.
38 | config.case_insensitive_keys = [ :email ]
39 |
40 | # Configure which authentication keys should have whitespace stripped.
41 | # These keys will have whitespace before and after removed upon creating or
42 | # modifying a user and when used to authenticate or find a user. Default is :email.
43 | config.strip_whitespace_keys = [ :email ]
44 |
45 | # Tell if authentication through request.params is enabled. True by default.
46 | # It can be set to an array that will enable params authentication only for the
47 | # given strategies, for example, `config.params_authenticatable = [:database]` will
48 | # enable it only for database (email + password) authentication.
49 | # config.params_authenticatable = true
50 |
51 | # Tell if authentication through HTTP Basic Auth is enabled. False by default.
52 | # It can be set to an array that will enable http authentication only for the
53 | # given strategies, for example, `config.http_authenticatable = [:token]` will
54 | # enable it only for token authentication.
55 | # config.http_authenticatable = false
56 |
57 | # If http headers should be returned for AJAX requests. True by default.
58 | # config.http_authenticatable_on_xhr = true
59 |
60 | # The realm used in Http Basic Authentication. "Application" by default.
61 | # config.http_authentication_realm = "Application"
62 |
63 | # It will change confirmation, password recovery and other workflows
64 | # to behave the same regardless if the e-mail provided was right or wrong.
65 | # Does not affect registerable.
66 | # config.paranoid = true
67 |
68 | # By default Devise will store the user in session. You can skip storage for
69 | # :http_auth and :token_auth by adding those symbols to the array below.
70 | # Notice that if you are skipping storage for all authentication paths, you
71 | # may want to disable generating routes to Devise's sessions controller by
72 | # passing :skip => :sessions to `devise_for` in your config/routes.rb
73 | config.skip_session_storage = [:http_auth]
74 |
75 | # ==> Configuration for :database_authenticatable
76 | # For bcrypt, this is the cost for hashing the password and defaults to 10. If
77 | # using other encryptors, it sets how many times you want the password re-encrypted.
78 | #
79 | # Limiting the stretches to just one in testing will increase the performance of
80 | # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
81 | # a value less than 10 in other environments.
82 | config.stretches = Rails.env.test? ? 1 : 10
83 |
84 | # Setup a pepper to generate the encrypted password.
85 | # config.pepper = "5047b130f92d256479f134ed6a8bf278dfa696a8dc63442f124623f2c9cedb2d9b3718a738d15125fc9da48710b3cd12804d53cd9c450426e4313a101a753fae"
86 |
87 | # ==> Configuration for :confirmable
88 | # A period that the user is allowed to access the website even without
89 | # confirming his account. For instance, if set to 2.days, the user will be
90 | # able to access the website for two days without confirming his account,
91 | # access will be blocked just in the third day. Default is 0.days, meaning
92 | # the user cannot access the website without confirming his account.
93 | # config.allow_unconfirmed_access_for = 2.days
94 |
95 | # A period that the user is allowed to confirm their account before their
96 | # token becomes invalid. For example, if set to 3.days, the user can confirm
97 | # their account within 3 days after the mail was sent, but on the fourth day
98 | # their account can't be confirmed with the token any more.
99 | # Default is nil, meaning there is no restriction on how long a user can take
100 | # before confirming their account.
101 | # config.confirm_within = 3.days
102 |
103 | # If true, requires any email changes to be confirmed (exactly the same way as
104 | # initial account confirmation) to be applied. Requires additional unconfirmed_email
105 | # db field (see migrations). Until confirmed new email is stored in
106 | # unconfirmed email column, and copied to email column on successful confirmation.
107 | config.reconfirmable = true
108 |
109 | # Defines which key will be used when confirming an account
110 | # config.confirmation_keys = [ :email ]
111 |
112 | # ==> Configuration for :rememberable
113 | # The time the user will be remembered without asking for credentials again.
114 | # config.remember_for = 2.weeks
115 |
116 | # If true, extends the user's remember period when remembered via cookie.
117 | # config.extend_remember_period = false
118 |
119 | # Options to be passed to the created cookie. For instance, you can set
120 | # :secure => true in order to force SSL only cookies.
121 | # config.rememberable_options = {}
122 |
123 | # ==> Configuration for :validatable
124 | # Range for password length. Default is 8..128.
125 | config.password_length = 6..128
126 |
127 | # Email regex used to validate email formats. It simply asserts that
128 | # an one (and only one) @ exists in the given string. This is mainly
129 | # to give user feedback and not to assert the e-mail validity.
130 | # config.email_regexp = /\A[^@]+@[^@]+\z/
131 |
132 | # ==> Configuration for :timeoutable
133 | # The time you want to timeout the user session without activity. After this
134 | # time the user will be asked for credentials again. Default is 30 minutes.
135 | # config.timeout_in = 30.minutes
136 |
137 | # If true, expires auth token on session timeout.
138 | # config.expire_auth_token_on_timeout = false
139 |
140 | # ==> Configuration for :lockable
141 | # Defines which strategy will be used to lock an account.
142 | # :failed_attempts = Locks an account after a number of failed attempts to sign in.
143 | # :none = No lock strategy. You should handle locking by yourself.
144 | # config.lock_strategy = :failed_attempts
145 |
146 | # Defines which key will be used when locking and unlocking an account
147 | # config.unlock_keys = [ :email ]
148 |
149 | # Defines which strategy will be used to unlock an account.
150 | # :email = Sends an unlock link to the user email
151 | # :time = Re-enables login after a certain amount of time (see :unlock_in below)
152 | # :both = Enables both strategies
153 | # :none = No unlock strategy. You should handle unlocking by yourself.
154 | # config.unlock_strategy = :both
155 |
156 | # Number of authentication tries before locking an account if lock_strategy
157 | # is failed attempts.
158 | # config.maximum_attempts = 20
159 |
160 | # Time interval to unlock the account if :time is enabled as unlock_strategy.
161 | # config.unlock_in = 1.hour
162 |
163 | # ==> Configuration for :recoverable
164 | #
165 | # Defines which key will be used when recovering the password for an account
166 | # config.reset_password_keys = [ :email ]
167 |
168 | # Time interval you can reset your password with a reset password key.
169 | # Don't put a too small interval or your users won't have the time to
170 | # change their passwords.
171 | config.reset_password_within = 6.hours
172 |
173 | # ==> Configuration for :encryptable
174 | # Allow you to use another encryption algorithm besides bcrypt (default). You can use
175 | # :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
176 | # :authlogic_sha512 (then you should set stretches above to 20 for default behavior)
177 | # and :restful_authentication_sha1 (then you should set stretches to 10, and copy
178 | # REST_AUTH_SITE_KEY to pepper)
179 | # config.encryptor = :sha512
180 |
181 | # ==> Configuration for :token_authenticatable
182 | # Defines name of the authentication token params key
183 | config.token_authentication_key = :authentication_token
184 |
185 | # ==> Scopes configuration
186 | # Turn scoped views on. Before rendering "sessions/new", it will first check for
187 | # "users/sessions/new". It's turned off by default because it's slower if you
188 | # are using only default views.
189 | # config.scoped_views = false
190 |
191 | # Configure the default scope given to Warden. By default it's the first
192 | # devise role declared in your routes (usually :user).
193 | # config.default_scope = :user
194 |
195 | # Set this configuration to false if you want /users/sign_out to sign out
196 | # only the current scope. By default, Devise signs out all scopes.
197 | # config.sign_out_all_scopes = true
198 |
199 | # ==> Navigation configuration
200 | # Lists the formats that should be treated as navigational. Formats like
201 | # :html, should redirect to the sign in page when the user does not have
202 | # access, but formats like :xml or :json, should return 401.
203 | #
204 | # If you have any extra navigational formats, like :iphone or :mobile, you
205 | # should add them to the navigational formats lists.
206 | #
207 | # The "*/*" below is required to match Internet Explorer requests.
208 | # config.navigational_formats = ["*/*", :html]
209 |
210 | # The default HTTP method used to sign out a resource. Default is :delete.
211 | config.sign_out_via = :delete
212 |
213 | # ==> OmniAuth
214 | # Add a new OmniAuth provider. Check the wiki for more information on setting
215 | # up on your models and hooks.
216 | # config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo'
217 |
218 | # ==> Warden configuration
219 | # If you want to use other strategies, that are not supported by Devise, or
220 | # change the failure app, you can configure them inside the config.warden block.
221 | #
222 | # config.warden do |manager|
223 | # manager.intercept_401 = false
224 | # manager.default_strategies(:scope => :user).unshift :some_external_strategy
225 | # end
226 |
227 | # ==> Mountable engine configurations
228 | # When using Devise inside an engine, let's call it `MyEngine`, and this engine
229 | # is mountable, there are some extra configurations to be taken into account.
230 | # The following options are available, assuming the engine is mounted as:
231 | #
232 | # mount MyEngine, at: "/my_engine"
233 | #
234 | # The router that invoked `devise_for`, in the example above, would be:
235 | # config.router_name = :my_engine
236 | #
237 | # When using omniauth, Devise cannot automatically set Omniauth path,
238 | # so you need to do it manually. For the users scope, it would be:
239 | # config.omniauth_path_prefix = "/my_engine/users/auth"
240 | end
241 |
--------------------------------------------------------------------------------