├── .codeclimate.yml
├── .gitignore
├── .rspec
├── .rubocop.yml
├── Dockerfile
├── Gemfile
├── Gemfile.lock
├── README.md
├── Rakefile
├── app
├── channels
│ └── application_cable
│ │ ├── channel.rb
│ │ └── connection.rb
├── controllers
│ ├── application_controller.rb
│ ├── concerns
│ │ └── .keep
│ ├── public_controller.rb
│ └── todos_controller.rb
├── jobs
│ └── application_job.rb
├── mailers
│ └── application_mailer.rb
├── models
│ ├── ability.rb
│ ├── application_record.rb
│ ├── concerns
│ │ └── .keep
│ ├── todo.rb
│ └── user.rb
└── views
│ ├── layouts
│ ├── mailer.html.erb
│ └── mailer.text.erb
│ ├── public
│ └── index.json.jbuilder
│ └── todos
│ ├── index.json.jbuilder
│ └── show.json.jbuilder
├── bin
├── bundle
├── rails
├── rake
├── setup
├── spring
└── update
├── config.ru
├── config
├── application.rb
├── boot.rb
├── cable.yml
├── database.yml
├── environment.rb
├── environments
│ ├── development.rb
│ ├── production.rb
│ └── test.rb
├── initializers
│ ├── active_record_belongs_to_required_by_default.rb
│ ├── application_controller_renderer.rb
│ ├── backtrace_silencers.rb
│ ├── callback_terminator.rb
│ ├── cors.rb
│ ├── devise.rb
│ ├── devise_token_auth.rb
│ ├── filter_parameter_logging.rb
│ ├── inflections.rb
│ ├── mime_types.rb
│ ├── rack_attack.rb
│ ├── rack_timeout.rb
│ ├── readthis.rb
│ ├── sidekiq.rb
│ ├── ssl_options.rb
│ ├── to_time_preserves_timezone.rb
│ └── wrap_parameters.rb
├── locales
│ ├── devise.en.yml
│ └── en.yml
├── puma.rb
├── redis.conf
├── routes.rb
├── secrets.yml
├── sidekiq.yml
└── spring.rb
├── coverage
├── .last_run.json
├── .resultset.json
├── .resultset.json.lock
├── assets
│ └── 0.10.0
│ │ ├── application.css
│ │ ├── application.js
│ │ ├── colorbox
│ │ ├── border.png
│ │ ├── controls.png
│ │ ├── loading.gif
│ │ └── loading_background.png
│ │ ├── favicon_green.png
│ │ ├── favicon_red.png
│ │ ├── favicon_yellow.png
│ │ ├── loading.gif
│ │ ├── magnify.png
│ │ └── smoothness
│ │ └── images
│ │ ├── ui-bg_flat_0_aaaaaa_40x100.png
│ │ ├── ui-bg_flat_75_ffffff_40x100.png
│ │ ├── ui-bg_glass_55_fbf9ee_1x400.png
│ │ ├── ui-bg_glass_65_ffffff_1x400.png
│ │ ├── ui-bg_glass_75_dadada_1x400.png
│ │ ├── ui-bg_glass_75_e6e6e6_1x400.png
│ │ ├── ui-bg_glass_95_fef1ec_1x400.png
│ │ ├── ui-bg_highlight-soft_75_cccccc_1x100.png
│ │ ├── ui-icons_222222_256x240.png
│ │ ├── ui-icons_2e83ff_256x240.png
│ │ ├── ui-icons_454545_256x240.png
│ │ ├── ui-icons_888888_256x240.png
│ │ └── ui-icons_cd0a0a_256x240.png
└── index.html
├── db
├── migrate
│ ├── 20160515174916_create_todos.rb
│ └── 20160517090314_devise_token_auth_create_users.rb
├── schema.rb
└── seeds.rb
├── doc
├── api.raml
└── schemas
│ └── auth
│ └── post.request.json
├── docker-compose.yml
├── lib
└── tasks
│ ├── .keep
│ └── docs_generate.rake
├── log
└── .keep
├── public
├── 404.html
├── 422.html
├── 500.html
├── apple-touch-icon-precomposed.png
├── apple-touch-icon.png
├── favicon.ico
└── robots.txt
├── spec
├── acceptance
│ ├── auth_spec.rb
│ └── todos_spec.rb
├── controllers
│ └── todos_controller_spec.rb
├── factories
│ ├── todos.rb
│ └── user.rb
├── models
│ └── todo_spec.rb
├── rails_helper.rb
├── routing
│ └── todos_routing_spec.rb
├── spec_helper.rb
└── support
│ └── settings
│ └── rspec_api_documentation.rb
└── tmp
└── .keep
/.codeclimate.yml:
--------------------------------------------------------------------------------
1 | ---
2 | engines:
3 | brakeman:
4 | enabled: true
5 | bundler-audit:
6 | enabled: true
7 | duplication:
8 | enabled: true
9 | config:
10 | languages:
11 | - ruby
12 | fixme:
13 | enabled: true
14 | rubocop:
15 | enabled: true
16 | ratings:
17 | paths:
18 | - Gemfile.lock
19 | - "**.erb"
20 | - "**.haml"
21 | - "**.rb"
22 | - "**.module"
23 | exclude_paths:
24 | - config/
25 | - db/
26 | - spec/
27 | - coverage/
28 | - .idea
29 | - .git
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-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 | # Ignore bundler config.
8 | /.bundle
9 |
10 | # Ignore the default SQLite database.
11 | /db/*.sqlite3
12 | /db/*.sqlite3-journal
13 |
14 | # Ignore all logfiles and tempfiles.
15 | /log/*
16 | /tmp/*
17 | !/log/.keep
18 | !/tmp/.keep
19 |
20 | # Ignore Byebug command history file.
21 | .byebug_history
22 |
23 | # Rubymine
24 | /.idea
25 |
26 | # Documentation
27 | /doc/spec_documentation/*
28 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --color
2 | --require spec_helper
3 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ruby:2.3.1
2 |
3 | RUN apt-get update -qq && apt-get install -y build-essential
4 |
5 | ENV APP_HOME /app
6 | RUN mkdir $APP_HOME
7 | WORKDIR $APP_HOME
8 |
9 | ADD Gemfile* $APP_HOME/
10 |
11 | ENV BUNDLE_GEMFILE=$APP_HOME/Gemfile \
12 | BUNDLE_JOBS=2 \
13 | BUNDLE_PATH=/bundle
14 |
15 | RUN bundle install --retry 3
16 |
17 | ADD . $APP_HOME
18 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | # Rails
4 | gem 'rails', '5.0.0'
5 |
6 | # Use sqlite3 as the database for Active Record
7 | gem 'sqlite3'
8 | gem 'pg'
9 |
10 | # Use Puma as the app server
11 | gem 'puma', '~> 3.0'
12 |
13 | # Security, limit number request per second. Read more: https://github.com/kickstarter/rack-attack
14 | gem 'rack-attack'
15 |
16 | # Build JSON APIs with ease.
17 | # Read more: https://github.com/rails/jbuilder
18 | gem 'jbuilder', :git => 'git://github.com/diwaniuk/jbuilder.git'
19 |
20 | # Faster rendering JSON file.
21 | # Read more: https://github.com/brianmario/yajl-ruby
22 | gem 'yajl-ruby', require: 'yajl'
23 |
24 | # Schema validation
25 | # https://github.com/ruby-json-schema/json-schema
26 | gem 'json-schema'
27 |
28 | # Timeout for long-running request
29 | gem 'rack-timeout'
30 |
31 | # Token based authentication for Rails JSON APIs
32 | gem 'devise_token_auth', github: "lynndylanhurley/devise_token_auth", branch: "master"
33 | gem 'omniauth'
34 |
35 | # CanCan is an authorization library for Ruby on Rails which restricts what resources a given user is allowed to access.
36 | gem 'cancancan'
37 |
38 | # Faster & modern implementation of client to integrate Rails with Redis
39 | # configuration in: config/initializers/readthis.rb (Fault Tolerant enable)
40 | # Read more: https://github.com/sorentwo/readthis
41 | gem 'redis'
42 | gem 'readthis'
43 | gem 'hiredis'
44 |
45 | # Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
46 | gem 'rack-cors'
47 |
48 | # Sidekiq as delay job manager
49 | gem 'sidekiq', '~> 4.1.2'
50 |
51 | # Cron for JOBS. Read more: https://github.com/ondrejbartas/sidekiq-cron
52 | gem 'sidekiq-cron', '~> 0.4.0'
53 | gem 'sidekiq-failures', '~> 0.4.5'
54 | gem 'sidekiq-statistic'
55 | gem 'sinatra', github: 'sinatra/sinatra', branch: 'master'
56 |
57 | # Use ActiveModel has_secure_password
58 | # gem 'bcrypt', '~> 3.1.7'
59 |
60 | # Use Capistrano for deployment
61 | # gem 'capistrano-rails', group: :development
62 |
63 | group :development, :test do
64 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console
65 | gem 'pry'
66 | gem 'pry-byebug'
67 | gem 'byebug', platform: :mri
68 |
69 | # Read more: https://github.com/collectiveidea/json_spec
70 | gem 'json_spec'
71 |
72 | # Read more: https://github.com/charliesome/better_errors
73 | # gem "better_errors"
74 | # gem 'binding_of_caller'
75 |
76 | # Read more: https://github.com/awesome-print/awesome_print
77 | # run ap User.all to see afect
78 | gem "awesome_print", require:"ap"
79 |
80 | # Integrate Rails project with Rails Panel (chrome extension)
81 | # Read More: https://github.com/dejan/rails_panel
82 | gem 'meta_request'
83 |
84 | # Use RSpec for specs
85 | gem "rspec-rails"
86 |
87 | # Automatic generate API documentation based on comments in RSpec
88 | gem 'rspec_api_documentation'
89 |
90 | # RSpec coverage
91 | gem 'simplecov', :require => false
92 |
93 | # Faker
94 | gem 'faker'
95 |
96 | # Use Factory Girl for generating random test data
97 | gem 'factory_girl_rails'
98 |
99 | # Fake email
100 | gem "letter_opener",:require => false
101 |
102 | end
103 |
104 | group :development do
105 | gem 'listen', '~> 3.0.5'
106 |
107 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
108 | gem 'spring'
109 | gem 'spring-watcher-listen', '~> 2.0.0'
110 |
111 | # JSON Schema tooling
112 | # Read more:
113 | # - https://github.com/interagent/prmd
114 | # - https://spacetelescope.github.io/understanding-json-schema/index.html
115 | # gem 'prmd'
116 | end
117 |
118 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem
119 | gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
120 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GIT
2 | remote: git://github.com/diwaniuk/jbuilder.git
3 | revision: 50e3ca8e714be7ddca229b3db31c6b43175bbf97
4 | specs:
5 | jbuilder (2.4.1)
6 | activesupport (>= 3.0.0, < 5.1)
7 | multi_json (~> 1.2)
8 |
9 | GIT
10 | remote: git://github.com/lynndylanhurley/devise_token_auth.git
11 | revision: 536911c7d3f178637423b77fe1179388ddf62b9e
12 | branch: master
13 | specs:
14 | devise_token_auth (0.1.39)
15 | devise (> 3.5.2, <= 4.2)
16 | rails (< 6)
17 |
18 | GIT
19 | remote: git://github.com/sinatra/sinatra.git
20 | revision: af6dad2a6c31e31617712b15f455b2a3d3eb1c06
21 | branch: master
22 | specs:
23 | sinatra (2.0.0.beta2)
24 | mustermann (= 1.0.0.beta2)
25 | rack (~> 2.0)
26 | rack-protection (= 2.0.0.beta2)
27 | tilt (~> 2.0)
28 |
29 | GEM
30 | remote: https://rubygems.org/
31 | specs:
32 | actioncable (5.0.0)
33 | actionpack (= 5.0.0)
34 | nio4r (~> 1.2)
35 | websocket-driver (~> 0.6.1)
36 | actionmailer (5.0.0)
37 | actionpack (= 5.0.0)
38 | actionview (= 5.0.0)
39 | activejob (= 5.0.0)
40 | mail (~> 2.5, >= 2.5.4)
41 | rails-dom-testing (~> 2.0)
42 | actionpack (5.0.0)
43 | actionview (= 5.0.0)
44 | activesupport (= 5.0.0)
45 | rack (~> 2.0)
46 | rack-test (~> 0.6.3)
47 | rails-dom-testing (~> 2.0)
48 | rails-html-sanitizer (~> 1.0, >= 1.0.2)
49 | actionview (5.0.0)
50 | activesupport (= 5.0.0)
51 | builder (~> 3.1)
52 | erubis (~> 2.7.0)
53 | rails-dom-testing (~> 2.0)
54 | rails-html-sanitizer (~> 1.0, >= 1.0.2)
55 | activejob (5.0.0)
56 | activesupport (= 5.0.0)
57 | globalid (>= 0.3.6)
58 | activemodel (5.0.0)
59 | activesupport (= 5.0.0)
60 | activerecord (5.0.0)
61 | activemodel (= 5.0.0)
62 | activesupport (= 5.0.0)
63 | arel (~> 7.0)
64 | activesupport (5.0.0)
65 | concurrent-ruby (~> 1.0, >= 1.0.2)
66 | i18n (~> 0.7)
67 | minitest (~> 5.1)
68 | tzinfo (~> 1.1)
69 | addressable (2.4.0)
70 | arel (7.1.2)
71 | awesome_print (1.7.0)
72 | bcrypt (3.1.11)
73 | builder (3.2.2)
74 | byebug (9.0.5)
75 | callsite (0.0.11)
76 | cancancan (1.15.0)
77 | coderay (1.1.1)
78 | concurrent-ruby (1.0.2)
79 | connection_pool (2.2.0)
80 | devise (4.2.0)
81 | bcrypt (~> 3.0)
82 | orm_adapter (~> 0.1)
83 | railties (>= 4.1.0, < 5.1)
84 | responders
85 | warden (~> 1.2.3)
86 | diff-lcs (1.2.5)
87 | docile (1.1.5)
88 | erubis (2.7.0)
89 | factory_girl (4.7.0)
90 | activesupport (>= 3.0.0)
91 | factory_girl_rails (4.7.0)
92 | factory_girl (~> 4.7.0)
93 | railties (>= 3.0.0)
94 | faker (1.6.6)
95 | i18n (~> 0.5)
96 | ffi (1.9.14)
97 | globalid (0.3.7)
98 | activesupport (>= 4.1.0)
99 | hashie (3.4.6)
100 | hiredis (0.6.1)
101 | i18n (0.7.0)
102 | json (2.0.2)
103 | json-schema (2.5.0)
104 | addressable (~> 2.3)
105 | json_spec (1.1.4)
106 | multi_json (~> 1.0)
107 | rspec (>= 2.0, < 4.0)
108 | launchy (2.4.3)
109 | addressable (~> 2.3)
110 | letter_opener (1.4.1)
111 | launchy (~> 2.2)
112 | listen (3.0.8)
113 | rb-fsevent (~> 0.9, >= 0.9.4)
114 | rb-inotify (~> 0.9, >= 0.9.7)
115 | loofah (2.0.3)
116 | nokogiri (>= 1.5.9)
117 | mail (2.6.4)
118 | mime-types (>= 1.16, < 4)
119 | meta_request (0.4.0)
120 | callsite (~> 0.0, >= 0.0.11)
121 | rack-contrib (~> 1.1)
122 | railties (>= 3.0.0, < 5.1.0)
123 | method_source (0.8.2)
124 | mime-types (3.1)
125 | mime-types-data (~> 3.2015)
126 | mime-types-data (3.2016.0521)
127 | mini_portile2 (2.1.0)
128 | minitest (5.9.0)
129 | multi_json (1.12.1)
130 | mustache (1.0.3)
131 | mustermann (1.0.0.beta2)
132 | nio4r (1.2.1)
133 | nokogiri (1.6.8)
134 | mini_portile2 (~> 2.1.0)
135 | pkg-config (~> 1.1.7)
136 | omniauth (1.3.1)
137 | hashie (>= 1.2, < 4)
138 | rack (>= 1.0, < 3)
139 | orm_adapter (0.5.0)
140 | pg (0.18.4)
141 | pkg-config (1.1.7)
142 | pry (0.10.4)
143 | coderay (~> 1.1.0)
144 | method_source (~> 0.8.1)
145 | slop (~> 3.4)
146 | pry-byebug (3.4.0)
147 | byebug (~> 9.0)
148 | pry (~> 0.10)
149 | puma (3.6.0)
150 | rack (2.0.1)
151 | rack-attack (5.0.1)
152 | rack
153 | rack-contrib (1.2.0)
154 | rack (>= 0.9.1)
155 | rack-cors (0.4.0)
156 | rack-protection (2.0.0.beta2)
157 | rack
158 | rack-test (0.6.3)
159 | rack (>= 1.0)
160 | rack-timeout (0.4.2)
161 | rails (5.0.0)
162 | actioncable (= 5.0.0)
163 | actionmailer (= 5.0.0)
164 | actionpack (= 5.0.0)
165 | actionview (= 5.0.0)
166 | activejob (= 5.0.0)
167 | activemodel (= 5.0.0)
168 | activerecord (= 5.0.0)
169 | activesupport (= 5.0.0)
170 | bundler (>= 1.3.0, < 2.0)
171 | railties (= 5.0.0)
172 | sprockets-rails (>= 2.0.0)
173 | rails-dom-testing (2.0.1)
174 | activesupport (>= 4.2.0, < 6.0)
175 | nokogiri (~> 1.6.0)
176 | rails-html-sanitizer (1.0.3)
177 | loofah (~> 2.0)
178 | railties (5.0.0)
179 | actionpack (= 5.0.0)
180 | activesupport (= 5.0.0)
181 | method_source
182 | rake (>= 0.8.7)
183 | thor (>= 0.18.1, < 2.0)
184 | rake (11.3.0)
185 | rb-fsevent (0.9.7)
186 | rb-inotify (0.9.7)
187 | ffi (>= 0.5.0)
188 | readthis (2.0.1)
189 | connection_pool (~> 2.1)
190 | redis (~> 3.0)
191 | redis (3.3.1)
192 | redis-namespace (1.5.2)
193 | redis (~> 3.0, >= 3.0.4)
194 | responders (2.3.0)
195 | railties (>= 4.2.0, < 5.1)
196 | rspec (3.5.0)
197 | rspec-core (~> 3.5.0)
198 | rspec-expectations (~> 3.5.0)
199 | rspec-mocks (~> 3.5.0)
200 | rspec-core (3.5.3)
201 | rspec-support (~> 3.5.0)
202 | rspec-expectations (3.5.0)
203 | diff-lcs (>= 1.2.0, < 2.0)
204 | rspec-support (~> 3.5.0)
205 | rspec-mocks (3.5.0)
206 | diff-lcs (>= 1.2.0, < 2.0)
207 | rspec-support (~> 3.5.0)
208 | rspec-rails (3.5.2)
209 | actionpack (>= 3.0)
210 | activesupport (>= 3.0)
211 | railties (>= 3.0)
212 | rspec-core (~> 3.5.0)
213 | rspec-expectations (~> 3.5.0)
214 | rspec-mocks (~> 3.5.0)
215 | rspec-support (~> 3.5.0)
216 | rspec-support (3.5.0)
217 | rspec_api_documentation (4.8.0)
218 | activesupport (>= 3.0.0)
219 | mustache (~> 1.0, >= 0.99.4)
220 | rspec (~> 3.0, >= 3.0.0)
221 | rufus-scheduler (3.2.2)
222 | sidekiq (4.1.4)
223 | concurrent-ruby (~> 1.0)
224 | connection_pool (~> 2.2, >= 2.2.0)
225 | redis (~> 3.2, >= 3.2.1)
226 | sinatra (>= 1.4.7)
227 | sidekiq-cron (0.4.3)
228 | redis-namespace (>= 1.5.2)
229 | rufus-scheduler (>= 2.0.24)
230 | sidekiq (>= 4.0.0)
231 | sidekiq-failures (0.4.5)
232 | sidekiq (>= 2.16.0)
233 | sidekiq-statistic (1.2.0)
234 | sidekiq (>= 3.3.4, < 5)
235 | simplecov (0.12.0)
236 | docile (~> 1.1.0)
237 | json (>= 1.8, < 3)
238 | simplecov-html (~> 0.10.0)
239 | simplecov-html (0.10.0)
240 | slop (3.6.0)
241 | spring (1.7.2)
242 | spring-watcher-listen (2.0.0)
243 | listen (>= 2.7, < 4.0)
244 | spring (~> 1.2)
245 | sprockets (3.7.0)
246 | concurrent-ruby (~> 1.0)
247 | rack (> 1, < 3)
248 | sprockets-rails (3.2.0)
249 | actionpack (>= 4.0)
250 | activesupport (>= 4.0)
251 | sprockets (>= 3.0.0)
252 | sqlite3 (1.3.11)
253 | thor (0.19.1)
254 | thread_safe (0.3.5)
255 | tilt (2.0.5)
256 | tzinfo (1.2.2)
257 | thread_safe (~> 0.1)
258 | warden (1.2.6)
259 | rack (>= 1.0)
260 | websocket-driver (0.6.4)
261 | websocket-extensions (>= 0.1.0)
262 | websocket-extensions (0.1.2)
263 | yajl-ruby (1.2.1)
264 |
265 | PLATFORMS
266 | ruby
267 |
268 | DEPENDENCIES
269 | awesome_print
270 | byebug
271 | cancancan
272 | devise_token_auth!
273 | factory_girl_rails
274 | faker
275 | hiredis
276 | jbuilder!
277 | json-schema
278 | json_spec
279 | letter_opener
280 | listen (~> 3.0.5)
281 | meta_request
282 | omniauth
283 | pg
284 | pry
285 | pry-byebug
286 | puma (~> 3.0)
287 | rack-attack
288 | rack-cors
289 | rack-timeout
290 | rails (= 5.0.0)
291 | readthis
292 | redis
293 | rspec-rails
294 | rspec_api_documentation
295 | sidekiq (~> 4.1.2)
296 | sidekiq-cron (~> 0.4.0)
297 | sidekiq-failures (~> 0.4.5)
298 | sidekiq-statistic
299 | simplecov
300 | sinatra!
301 | spring
302 | spring-watcher-listen (~> 2.0.0)
303 | sqlite3
304 | tzinfo-data
305 | yajl-ruby
306 |
307 | BUNDLED WITH
308 | 1.12.5
309 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Rails 5 API starter
2 |
3 | Rails 5 API starter is a boilerplate which helps you build fast, secure and efficient API for applications. Template based on automatically generated structure of directory and settings which are default delivered by --api switch. Additional to settings are added and initially configure useful Gems, which are often used in Rails stack application.
4 |
5 |
6 |
7 |
8 |
9 | ## Features
10 |
11 | - [omniauth](https://github.com/intridea/omniauth )
12 | - [devise](https://github.com/plataformatec/devise)
13 | - [devise_token_auth](https://github.com/lynndylanhurley/devise_token_auth)
14 | - [cancancan](https://github.com/CanCanCommunity/cancancan)
15 | - [jbuilder](https://github.com/rails/jbuilder)
16 | - [rspec-api-documentation](https://github.com/zipmark/rspec_api_documentation )
17 | - [yard](https://github.com/lsegal/yard)
18 | - [rspec-rails](https://github.com/rspec/rspec-rails)
19 | - [json_spec](https://github.com/collectiveidea/json_spec)
20 | - [factory-girl](https://github.com/thoughtbot/factory_girl)
21 | - [faker]( https://github.com/stympy/faker)
22 | - [simpleconv](https://github.com/colszowka/simplecov)
23 | - [rack-attacker](https://github.com/kickstarter/rack-attack )
24 | - [rack-timeout]( https://github.com/heroku/rack-timeout)
25 | - [readthis](https://github.com/sorentwo/readthis)
26 | - [hiredis](https://github.com/redis/hiredis)
27 | - [spirng](https://github.com/rails/spring )
28 | - [better_errors](https://github.com/charliesome/better_errors)
29 | - [awesome_print](https://github.com/awesome-print/awesome_print)
30 | - [rails_panel](https://github.com/dejan/rails_panel)
31 | - [pry-byebug](https://github.com/deivid-rodriguez/pry-byebug)
32 | - [sidekiq](https://github.com/mperham/sidekiq)
33 | - [prmd](https://github.com/interagent/prmd)
34 |
35 | ### Installation process
36 |
37 | ##### Requirements
38 |
39 | Boilerplate based on Docker container. To start using them, first, we have to make sure that Docker Engine and Docker compose tool are installed.
40 |
41 | - Compose 1.6.0+
42 | - Docker Engine 1.10.0+
43 |
44 | ##### Build
45 |
46 | ```
47 | $ git git@github.com:Hawatel/rails5-api-starter.git
48 | $ docker-compose build
49 | $ docker-compose run web bundle
50 | $ docker-compose run web rails db:create
51 | $ docker-compose run web rails db:migrate
52 | ```
53 |
54 | ### Getting Started
55 |
56 | To start the server you only need to run the following magic command:
57 |
58 | ```
59 | $ docker-compose up
60 | ```
61 |
62 | #### Rename project
63 |
64 | It is only necessary from the perspective of the framework to change the application name in config/application.rb file.
65 |
66 | ```
67 | ...
68 | module HawatelApi5Starterkit # CHANGE HERE
69 | class Application < Rails::Application
70 | # Settings in config/environments/* take precedence over those specified here.
71 | # Application configuration should go into files in config/initializers
72 | # -- all .rb files in that directory are automatically loaded.
73 |
74 | # Only loads a smaller set of middleware suitable for API only apps.
75 | # Middleware like session, flash, cookies can be added back manually.
76 | # Skip views, helpers and assets when generating a new resource.
77 | config.api_only = true
78 |
79 | # Use Rack Attack
80 | config.middleware.use Rack::Attack
81 | end
82 | end
83 | ```
84 |
85 | #### Update Gemset
86 |
87 | To avoid install gems from scratch in each time when Gemfile will be updated, boilerplate has implemented persistent, cross-container dedicated volume for gems.
88 | Now in case when new entry to Gemfile is added, just run below command to update state:
89 |
90 | ```
91 | $ docker-compose run web bundle
92 | ```
93 |
94 | #### Debugging
95 |
96 | ##### Rails in Chrome
97 |
98 | RailsPanel is a Chrome extension for Rails development that will end your tailing of development.log. Have all information about your Rails app requests right there in the Developer Tools panel.
99 | To use this you will need to install Chrome extension from this [link](https://chrome.google.com/webstore/detail/railspanel/gjpfobpafnhjhbajcjgccbbdofdckggg) .
100 |
101 |
102 | ### RSpec
103 |
104 | Running your test suite is done quite easily. You have to just set RAILS_ENV to test and execute rspec command the same way you would run your tests locally:
105 |
106 | ```
107 | $ docker-compose run -e "RAILS_ENV=test" rspec
108 | ```
109 |
110 | In case when you need initialize or migrate database in test env call rails db:create or db:migrate:
111 |
112 | ```
113 | $ docker-compose run -e "RAILS_ENV=test" web rails db:create
114 | $ docker-compose run -e "RAILS_ENV=test" web rails db:migrate
115 | ```
116 |
117 | #### API Documentation based on rspec-api-documentation
118 |
119 | ```
120 | $ docker-compose run -e "RAILS_ENV=test" web rake docs:generate
121 | ```
122 |
123 |
124 | ## License
125 |
126 | The Starter Kit is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
127 |
128 | ## Useful links
129 |
130 | #### Design API
131 | - https://geemus.gitbooks.io/http-api-design/content/en/
132 | - https://labs.omniti.com/labs/jsend
133 | - http://jsonapi.org/
134 |
135 | ## TODO
136 | - https://github.com/phatworx/devise_security_extension - Add Devise security extension
137 |
138 |
139 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # Add your own tasks in files placed in lib/tasks ending in .rake,
2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3 |
4 | require_relative 'config/application'
5 |
6 | Rails.application.load_tasks
7 |
--------------------------------------------------------------------------------
/app/channels/application_cable/channel.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file. Action Cable runs in a loop that does not support auto reloading.
2 | module ApplicationCable
3 | class Channel < ActionCable::Channel::Base
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/app/channels/application_cable/connection.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file. Action Cable runs in a loop that does not support auto reloading.
2 | module ApplicationCable
3 | class Connection < ActionCable::Connection::Base
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::API
2 | include DeviseTokenAuth::Concerns::SetUserByToken
3 | include ActionController::Caching
4 | include CanCan::ControllerAdditions
5 |
6 | end
7 |
--------------------------------------------------------------------------------
/app/controllers/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/app/controllers/concerns/.keep
--------------------------------------------------------------------------------
/app/controllers/public_controller.rb:
--------------------------------------------------------------------------------
1 | class PublicController < ApplicationController
2 |
3 | def index
4 | authorize! :read, :all
5 |
6 | @msg = "Hello Word"
7 | # Generate uniq key for cache.
8 | @cache_key = "users/#{User.maximum(:updated_at)}"
9 |
10 | #Cache SQL query
11 | # @users = Rails.cache.fetch(@cache_key, expires_in: 10.minutes.to_i) do
12 | # User.all
13 | # end
14 | end
15 |
16 | # only admin can create new stuff
17 | def create
18 | authorize! :manage, :all
19 | end
20 |
21 | end
--------------------------------------------------------------------------------
/app/controllers/todos_controller.rb:
--------------------------------------------------------------------------------
1 | class TodosController < ApplicationController
2 | before_action :set_todo, only: [:show, :update, :destroy]
3 | before_action :authenticate_user!
4 |
5 | # GET /todos
6 | # GET /todos.json
7 | def index
8 | @todos = Todo.all
9 | end
10 |
11 | # GET /todos/1
12 | # GET /todos/1.json
13 | def show
14 | if Todo.cache_find(params[:id])
15 | @todos = Todo.cache_find(params[:id])
16 | end
17 | end
18 |
19 | # POST /todos
20 | # POST /todos.json
21 | def create
22 | @todo = Todo.new(todo_params)
23 | if @todo.save
24 | render :show, status: :created, location: @todo
25 | else
26 | render json: @todo.errors, status: :unprocessable_entity
27 | end
28 | end
29 |
30 | # PATCH/PUT /todos/1
31 | # PATCH/PUT /todos/1.json
32 | def update
33 | if @todo.update(todo_params)
34 | render :show, status: :ok, location: @todo
35 | else
36 | render json: @todo.errors, status: :unprocessable_entity
37 | end
38 | end
39 |
40 |
41 | # DELETE /todos/1
42 | # DELETE /todos/1.json
43 | def destroy
44 | @todo.destroy
45 | end
46 |
47 | private
48 | # Use callbacks to share common setup or constraints between actions.
49 | def set_todo
50 | if Todo.cache_find(params[:id])
51 | @todo = Todo.cache_find(params[:id])
52 | end
53 | end
54 |
55 | # Never trust parameters from the scary internet, only allow the white list through.
56 | def todo_params
57 | params.require(:todo).permit(:title, :completed, :order)
58 | end
59 |
60 | end
61 |
--------------------------------------------------------------------------------
/app/jobs/application_job.rb:
--------------------------------------------------------------------------------
1 | class ApplicationJob < ActiveJob::Base
2 | end
3 |
--------------------------------------------------------------------------------
/app/mailers/application_mailer.rb:
--------------------------------------------------------------------------------
1 | class ApplicationMailer < ActionMailer::Base
2 | default from: 'from@example.com'
3 | layout 'mailer'
4 | end
5 |
--------------------------------------------------------------------------------
/app/models/ability.rb:
--------------------------------------------------------------------------------
1 | class Ability
2 | include CanCan::Ability
3 |
4 | def initialize(user)
5 |
6 | user ||= User.new # guest user (not logged in)
7 |
8 | if user.admin?
9 | can :manage, :all
10 | else
11 | can :read, :all
12 | end
13 |
14 | # Define abilities for the passed in user here. For example:
15 | #
16 | # user ||= User.new # guest user (not logged in)
17 | # if user.admin?
18 | # can :manage, :all
19 | # else
20 | # can :read, :all
21 | # end
22 | #
23 | # The first argument to `can` is the action you are giving the user
24 | # permission to do.
25 | # If you pass :manage it will apply to every action. Other common actions
26 | # here are :read, :create, :update and :destroy.
27 | #
28 | # The second argument is the resource the user can perform the action on.
29 | # If you pass :all it will apply to every resource. Otherwise pass a Ruby
30 | # class of the resource.
31 | #
32 | # The third argument is an optional hash of conditions to further filter the
33 | # objects.
34 | # For example, here the user can only update published articles.
35 | #
36 | # can :update, Article, :published => true
37 | #
38 | # See the wiki for details:
39 | # https://github.com/CanCanCommunity/cancancan/wiki/Defining-Abilities
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/app/models/application_record.rb:
--------------------------------------------------------------------------------
1 | class ApplicationRecord < ActiveRecord::Base
2 | self.abstract_class = true
3 | end
4 |
--------------------------------------------------------------------------------
/app/models/concerns/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/app/models/concerns/.keep
--------------------------------------------------------------------------------
/app/models/todo.rb:
--------------------------------------------------------------------------------
1 | class Todo < ApplicationRecord
2 |
3 | after_commit :flush_cache
4 |
5 | def flush_cache
6 | Rails.cache.delete([self.class.name, id])
7 | end
8 |
9 | def self.cache_find(id)
10 | Rails.cache.fetch([name, id]) { find(id) }
11 | end
12 |
13 | end
14 |
15 |
--------------------------------------------------------------------------------
/app/models/user.rb:
--------------------------------------------------------------------------------
1 | class User < ActiveRecord::Base
2 | # Include default devise modules.
3 | devise :database_authenticatable, :registerable,
4 | :recoverable, :rememberable, :trackable, :validatable,
5 | :confirmable, :omniauthable
6 | include DeviseTokenAuth::Concerns::User
7 | end
8 |
--------------------------------------------------------------------------------
/app/views/layouts/mailer.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
10 |
11 | <%= yield %>
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/views/layouts/mailer.text.erb:
--------------------------------------------------------------------------------
1 | <%= yield %>
2 |
--------------------------------------------------------------------------------
/app/views/public/index.json.jbuilder:
--------------------------------------------------------------------------------
1 | # get json from cache, if doson't exist execute code from bloc do...end and save in cache
2 | json.cache! ["users/#{@cache_key}"], expired_in: 60.minutes.to_i do
3 | json.status "success"
4 | json.data do
5 | json.message @msg
6 | json.array!(User.all) do |user|
7 | json.extract! user, :id, :email, :current_sign_in_ip
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/app/views/todos/index.json.jbuilder:
--------------------------------------------------------------------------------
1 | json.status "success"
2 | json.data do
3 | json.todos do
4 | json.array!(@todos) do |todo|
5 | json.extract! todo, :id, :title, :completed, :order
6 | json.url todo_url(todo, format: :json)
7 | end
8 | end
9 | end
10 |
11 | # json.employess do
12 | #
13 | # @users.each do |data|
14 | # json.data do
15 | # json.name 'Daniel'
16 | # json.surname 'Iwaniuk'
17 | # end
18 | # end
19 | #
20 | #
21 | # json.users do
22 | # json.array! @users.each do |user|
23 | # json.type 'regular'
24 | # json.surname user
25 | # json.role 'admin'
26 | # end
27 | # end
28 | #
29 | # json.users2 do
30 | # json.array! @users2.each do |user2|
31 | # json.type 'regular'
32 | # json.name user2[:name]
33 | # json.surname user2[:surname]
34 | # if user2[:name] == 'Daniel'
35 | # json.role 'admin'
36 | # else
37 | # json.role 'read-only'
38 | # end
39 | # end
40 | # end
41 | #
42 | # # get value from methods
43 | # json.(@article, :id, :name, :published_at)
44 | #
45 | # json.attachments @users.each do |user|
46 | # json.surname user
47 | # json.role 'admin'
48 | # end
49 | #
50 | # end
51 |
52 | # RESPOND
53 | # {
54 | # "status":"success",
55 | # "data": {
56 | # "users":[
57 | # {"type":"regular","surname":"Daniel","role":"admin"},
58 | # {"type":"regular","surname":"Michal","role":"admin"}
59 | # ]
60 | # }
61 | # }
62 |
63 | # GET /users.
64 | # json.status "success"
65 | # json.data do
66 | # json.users do
67 | # json.array! @users.each do |user|
68 | # json.type 'regular'
69 | # json.surname user
70 | # json.role 'admin'
71 | # end
72 | # end
73 | # end
74 |
75 | # RESPOND
76 | # {
77 | # "status":"success",
78 | # "data": {
79 | # "users":[
80 | # {"type":"regular","surname":"Daniel","role":"admin"},
81 | # {"type":"regular","surname":"Michal","role":"admin"}
82 | # ]
83 | # }
84 | # }
85 |
86 |
87 | # # GET /users/1.json
88 | # json.status "success"
89 | # json.data do
90 | # json.users
91 | # json.type 'regular'
92 | # json.surname 'usersname'
93 | # json.role 'admin'
94 | # end
95 | #
96 | # {
97 | # "status": "success",
98 | # "data": {
99 | # "type": "regular",
100 | # "surname": "usersname",
101 | # "role": "admin"
102 | # }
103 | # }
104 |
105 | # DELETE /users/1.json
106 | # json.status "success"
107 | # json.data "null"
108 | #
109 | # {
110 | # "status": "success",
111 | # "data": "null"
112 | # }
113 |
114 |
115 | # == FAIL ===
116 | # json.status "fail"
117 | # json.data do
118 | # json.title "Position is required"
119 | # end
120 | #
121 | # {
122 | # "status": "fail",
123 | # "data": {
124 | # "title": "Position is required"
125 | # }
126 | # }
127 |
--------------------------------------------------------------------------------
/app/views/todos/show.json.jbuilder:
--------------------------------------------------------------------------------
1 | if @todos
2 | json.status "success"
3 | json.data do
4 | json.extract! @todos, :id, :title, :completed, :order, :created_at, :updated_at
5 | end
6 | else
7 | json.status "fail"
8 | json.data do
9 | json.title "Position dosn't exist"
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/bin/bundle:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3 | load Gem.bin_path('bundler', 'bundle')
4 |
--------------------------------------------------------------------------------
/bin/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | begin
3 | load File.expand_path('../spring', __FILE__)
4 | rescue LoadError => e
5 | raise unless e.message.include?('spring')
6 | end
7 | APP_PATH = File.expand_path('../config/application', __dir__)
8 | require_relative '../config/boot'
9 | require 'rails/commands'
10 |
--------------------------------------------------------------------------------
/bin/rake:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | begin
3 | load File.expand_path('../spring', __FILE__)
4 | rescue LoadError => e
5 | raise unless e.message.include?('spring')
6 | end
7 | require_relative '../config/boot'
8 | require 'rake'
9 | Rake.application.run
10 |
--------------------------------------------------------------------------------
/bin/setup:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'pathname'
3 | require 'fileutils'
4 | include FileUtils
5 |
6 | # path to your application root.
7 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
8 |
9 | def system!(*args)
10 | system(*args) || abort("\n== Command #{args} failed ==")
11 | end
12 |
13 | chdir APP_ROOT do
14 | # This script is a starting point to setup your application.
15 | # Add necessary setup steps to this file.
16 |
17 | puts '== Installing dependencies =='
18 | system! 'gem install bundler --conservative'
19 | system('bundle check') || system!('bundle install')
20 |
21 | # puts "\n== Copying sample files =="
22 | # unless File.exist?('config/database.yml')
23 | # cp 'config/database.yml.sample', 'config/database.yml'
24 | # end
25 |
26 | puts "\n== Preparing database =="
27 | system! 'bin/rails db:setup'
28 |
29 | puts "\n== Removing old logs and tempfiles =="
30 | system! 'bin/rails log:clear tmp:clear'
31 |
32 | puts "\n== Restarting application server =="
33 | system! 'bin/rails restart'
34 | end
35 |
--------------------------------------------------------------------------------
/bin/spring:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | # This file loads spring without using Bundler, in order to be fast.
4 | # It gets overwritten when you run the `spring binstub` command.
5 |
6 | unless defined?(Spring)
7 | require 'rubygems'
8 | require 'bundler'
9 |
10 | if (match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m))
11 | Gem.paths = { 'GEM_PATH' => [Bundler.bundle_path.to_s, *Gem.path].uniq.join(Gem.path_separator) }
12 | gem 'spring', match[1]
13 | require 'spring/binstub'
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/bin/update:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'pathname'
3 | require 'fileutils'
4 | include FileUtils
5 |
6 | # path to your application root.
7 | APP_ROOT = Pathname.new File.expand_path('../../', __FILE__)
8 |
9 | def system!(*args)
10 | system(*args) || abort("\n== Command #{args} failed ==")
11 | end
12 |
13 | chdir APP_ROOT do
14 | # This script is a way to update your development environment automatically.
15 | # Add necessary update steps to this file.
16 |
17 | puts '== Installing dependencies =='
18 | system! 'gem install bundler --conservative'
19 | system('bundle check') || system!('bundle install')
20 |
21 | puts "\n== Updating database =="
22 | system! 'bin/rails db:migrate'
23 |
24 | puts "\n== Removing old logs and tempfiles =="
25 | system! 'bin/rails log:clear tmp:clear'
26 |
27 | puts "\n== Restarting application server =="
28 | system! 'bin/rails restart'
29 | end
30 |
--------------------------------------------------------------------------------
/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require_relative 'config/environment'
4 |
5 | run Rails.application
6 |
--------------------------------------------------------------------------------
/config/application.rb:
--------------------------------------------------------------------------------
1 | require_relative 'boot'
2 |
3 | require "rails"
4 | # Pick the frameworks you want:
5 | require "active_model/railtie"
6 | require "active_job/railtie"
7 | require "active_record/railtie"
8 | require "action_controller/railtie"
9 | require "action_mailer/railtie"
10 | require "action_view/railtie"
11 | require "action_cable/engine"
12 | # require "sprockets/railtie"
13 | require "rails/test_unit/railtie"
14 |
15 | # Require the gems listed in Gemfile, including any gems
16 | # you've limited to :test, :development, or :production.
17 | Bundler.require(*Rails.groups)
18 |
19 | module HawatelApi5Starterkit
20 | class Application < Rails::Application
21 | # Settings in config/environments/* take precedence over those specified here.
22 | # Application configuration should go into files in config/initializers
23 | # -- all .rb files in that directory are automatically loaded.
24 |
25 | # Only loads a smaller set of middleware suitable for API only apps.
26 | # Middleware like session, flash, cookies can be added back manually.
27 | # Skip views, helpers and assets when generating a new resource.
28 | config.api_only = true
29 |
30 | # Use Rack Attack
31 | config.middleware.use Rack::Attack
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/config/boot.rb:
--------------------------------------------------------------------------------
1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
2 |
3 | require 'bundler/setup' # Set up gems listed in the Gemfile.
4 |
--------------------------------------------------------------------------------
/config/cable.yml:
--------------------------------------------------------------------------------
1 | # Action Cable uses Redis by default to administer connections, channels, and sending/receiving messages over the WebSocket.
2 | production:
3 | adapter: redis
4 | url: redis://localhost:6379/1
5 |
6 | development:
7 | adapter: async
8 |
9 | test:
10 | adapter: async
11 |
--------------------------------------------------------------------------------
/config/database.yml:
--------------------------------------------------------------------------------
1 | default: &default
2 | adapter: postgresql
3 | encoding: unicode
4 | pool: 5
5 | timeout: 5000
6 | username: postgres
7 | password: SecurePasswordPG
8 | host: postgres
9 | port: 5432
10 |
11 | development:
12 | <<: *default
13 | database: app_development
14 |
15 | # Warning: The database defined as "test" will be erased and
16 | # re-generated from your development database when you run
17 | # "rake". Do not set this db to the same as development or
18 | # production.
19 | test:
20 | <<: *default
21 | database: app_test
--------------------------------------------------------------------------------
/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the Rails application.
2 | require_relative 'application'
3 |
4 | # Initialize the Rails application.
5 | Rails.application.initialize!
6 |
--------------------------------------------------------------------------------
/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | Rails.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 | # Do not eager load code on boot.
10 | config.eager_load = false
11 |
12 | # Show full error reports.
13 | config.consider_all_requests_local = true
14 |
15 | # Show errors is HTML formatl
16 | config.debug_exception_response_format = :default
17 |
18 | # Enable/disable caching. By default caching is disabled.
19 | if Rails.root.join('tmp/caching-dev.txt').exist?
20 | config.action_controller.perform_caching = true
21 | config.cache_store = :readthis_store, {
22 | expires_in: 24.hours.to_i,
23 | redis: { url: "#{ENV['REDIS_URL']}/0/cache", driver: :hiredis }
24 | }
25 | config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=172800' }
26 | else
27 | config.action_controller.perform_caching = false
28 | config.cache_store = [:null_store]
29 | end
30 |
31 | # Fake email server
32 | config.action_mailer.delivery_method = :file
33 | config.action_mailer.file_settings = { :location => Rails.root.join('tmp/mail') }
34 | config.action_mailer.default_url_options = { :host => "http://localhost:3000" }
35 |
36 | # Don't care if the mailer can't send.
37 | config.action_mailer.raise_delivery_errors = false
38 |
39 | config.action_mailer.perform_caching = false
40 |
41 | # Print deprecation notices to the Rails logger.
42 | config.active_support.deprecation = :log
43 |
44 | # Raise an error on page load if there are pending migrations.
45 | config.active_record.migration_error = :page_load
46 |
47 | # Better errors
48 | # TODO fix issue with better error
49 | # BetterErrors::Middleware.allow_ip! "0.0.0.0/0"
50 |
51 | # Raises error for missing translations
52 | # config.action_view.raise_on_missing_translations = true
53 |
54 | # Use an evented file watcher to asynchronously detect changes in source code,
55 | # routes, locales, etc. This feature depends on the listen gem.
56 | config.file_watcher = ActiveSupport::EventedFileUpdateChecker
57 | end
58 |
--------------------------------------------------------------------------------
/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | Rails.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 | # Eager load code on boot. This eager loads most of Rails and
8 | # your application in memory, allowing both threaded web servers
9 | # and those relying on copy on write to perform better.
10 | # Rake tasks automatically ignore this option for performance.
11 | config.eager_load = true
12 |
13 | # Full error reports are disabled and caching is turned on.
14 | config.consider_all_requests_local = false
15 | config.action_controller.perform_caching = true
16 |
17 | # Disable serving static files from the `/public` folder by default since
18 | # Apache or NGINX already handles this.
19 | config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
20 |
21 | # Enable/disable caching. By default caching is disabled.
22 | if Rails.root.join('tmp/caching-prod.txt').exist?
23 | config.action_controller.perform_caching = true
24 | config.cache_store = :readthis_store, {
25 | expires_in: 30.minutes.to_i,
26 | redis: { url: "#{ENV['REDIS_URL']}/0/cache", driver: :hiredis }
27 | }
28 | config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=172800' }
29 | else
30 | config.action_controller.perform_caching = false
31 | config.cache_store = [:null_store]
32 | end
33 | # Enable serving of images, stylesheets, and JavaScripts from an asset server.
34 | # config.action_controller.asset_host = 'http://assets.example.com'
35 |
36 | # Specifies the header that your server uses for sending files.
37 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache
38 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX
39 |
40 | # Action Cable endpoint configuration
41 | # config.action_cable.url = 'wss://example.com/cable'
42 | # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
43 |
44 | # Don't mount Action Cable in the main server process.
45 | # config.action_cable.mount_path = nil
46 |
47 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
48 | # config.force_ssl = true
49 |
50 | # Use the lowest log level to ensure availability of diagnostic information
51 | # when problems arise.
52 | config.log_level = :info
53 |
54 | # Prepend all log lines with the following tags.
55 | config.log_tags = [ :request_id ]
56 |
57 | # Use a different cache store in production.
58 | # config.cache_store = :mem_cache_store
59 |
60 | # Use a real queuing backend for Active Job (and separate queues per environment)
61 | # config.active_job.queue_adapter = :resque
62 | # config.active_job.queue_name_prefix = "hawatel-api5-starterkit_#{Rails.env}"
63 | config.action_mailer.perform_caching = false
64 |
65 | # Ignore bad email addresses and do not raise email delivery errors.
66 | # Set this to true and configure the email server for immediate delivery to raise delivery errors.
67 | # config.action_mailer.raise_delivery_errors = false
68 |
69 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
70 | # the I18n.default_locale when a translation cannot be found).
71 | config.i18n.fallbacks = true
72 |
73 | # Send deprecation notices to registered listeners.
74 | config.active_support.deprecation = :notify
75 |
76 | # Use default logging formatter so that PID and timestamp are not suppressed.
77 | config.log_formatter = ::Logger::Formatter.new
78 |
79 | # Use a different logger for distributed setups.
80 | # require 'syslog/logger'
81 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')
82 |
83 | if ENV["RAILS_LOG_TO_STDOUT"].present?
84 | logger = ActiveSupport::Logger.new(STDOUT)
85 | logger.formatter = config.log_formatter
86 | config.logger = ActiveSupport::TaggedLogging.new(logger)
87 | end
88 |
89 | # Do not dump schema after migrations.
90 | config.active_record.dump_schema_after_migration = false
91 | end
92 |
--------------------------------------------------------------------------------
/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | Rails.application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb.
3 |
4 | # The test environment is used exclusively to run your application's
5 | # test suite. You never need to work with it otherwise. Remember that
6 | # your test database is "scratch space" for the test suite and is wiped
7 | # and recreated between test runs. Don't rely on the data there!
8 | config.cache_classes = true
9 |
10 | # Do not eager load code on boot. This avoids loading your whole application
11 | # just for the purpose of running a single test. If you are using a tool that
12 | # preloads Rails for running tests, you may have to set it to true.
13 | config.eager_load = false
14 |
15 | # Configure public file server for tests with Cache-Control for performance.
16 | config.public_file_server.enabled = true
17 | config.public_file_server.headers = {
18 | 'Cache-Control' => 'public, max-age=3600'
19 | }
20 |
21 | # Show full error reports and disable caching.
22 | config.consider_all_requests_local = true
23 | config.action_controller.perform_caching = false
24 | config.cache_store = [:null_store]
25 |
26 | # Raise exceptions instead of rendering exception templates.
27 | config.action_dispatch.show_exceptions = false
28 |
29 | # Disable request forgery protection in test environment.
30 | config.action_controller.allow_forgery_protection = false
31 | config.action_mailer.perform_caching = false
32 |
33 | # Tell Action Mailer not to deliver emails to the real world.
34 | # The :test delivery method accumulates sent emails in the
35 | # ActionMailer::Base.deliveries array.
36 | config.action_mailer.delivery_method = :test
37 |
38 | # Print deprecation notices to the stderr.
39 | config.active_support.deprecation = :stderr
40 |
41 | # Send test email
42 | config.action_mailer.default_url_options = { :host => "localhost" }
43 |
44 | # Raises error for missing translations
45 | # config.action_view.raise_on_missing_translations = true
46 | end
47 |
--------------------------------------------------------------------------------
/config/initializers/active_record_belongs_to_required_by_default.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Require `belongs_to` associations by default. This is a new Rails 5.0
4 | # default, so it is introduced as a configuration option to ensure that apps
5 | # made on earlier versions of Rails are not affected when upgrading.
6 | Rails.application.config.active_record.belongs_to_required_by_default = true
7 |
--------------------------------------------------------------------------------
/config/initializers/application_controller_renderer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # ApplicationController.renderer.defaults.merge!(
4 | # http_host: 'example.org',
5 | # https: false
6 | # )
7 |
--------------------------------------------------------------------------------
/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7 | # Rails.backtrace_cleaner.remove_silencers!
8 |
--------------------------------------------------------------------------------
/config/initializers/callback_terminator.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Do not halt callback chains when a callback returns false. This is a new
4 | # Rails 5.0 default, so it is introduced as a configuration option to ensure
5 | # that apps made with earlier versions of Rails are not affected when upgrading.
6 | ActiveSupport.halt_callback_chains_on_return_false = false
7 |
--------------------------------------------------------------------------------
/config/initializers/cors.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Avoid CORS issues when API is called from the frontend app.
4 | # Handle Cross-Origin Resource Sharing (CORS) in order to accept cross-origin AJAX requests.
5 |
6 | # Read more: https://github.com/cyu/rack-cors
7 |
8 | Rails.application.config.middleware.insert_before 0, Rack::Cors do
9 | allow do
10 | origins 'localhost.com'
11 |
12 | resource '*',
13 | headers: :any,
14 | methods: [:get, :post, :put, :patch, :delete, :options, :head]
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/config/initializers/devise.rb:
--------------------------------------------------------------------------------
1 | Devise.setup do |config|
2 | # The e-mail address that mail will appear to be sent from
3 | # If absent, mail is sent from "please-change-me-at-config-initializers-devise@example.com"
4 | config.mailer_sender = "support@hawatel.com"
5 |
6 | # If using rails-api, you may want to tell devise to not use ActionDispatch::Flash
7 | # middleware b/c rails-api does not include it.
8 | # See: http://stackoverflow.com/q/19600905/806956
9 | config.navigational_formats = [:json]
10 |
11 | # email regex
12 | config.email_regexp = /\A[^@\s]+@([^@\s]+\.)+[^@\W]+\z/
13 |
14 | end
--------------------------------------------------------------------------------
/config/initializers/devise_token_auth.rb:
--------------------------------------------------------------------------------
1 | DeviseTokenAuth.setup do |config|
2 | # By default the authorization headers will change after each request. The
3 | # client is responsible for keeping track of the changing tokens. Change
4 | # this to false to prevent the Authorization header from changing after
5 | # each request.
6 | config.change_headers_on_each_request = false
7 |
8 | # By default, users will need to re-authenticate after 2 weeks. This setting
9 | # determines how long tokens will remain valid after they are issued.
10 | config.token_lifespan = 2.weeks
11 |
12 | # Sets the max number of concurrent devices per user, which is 10 by default.
13 | # After this limit is reached, the oldest tokens will be removed.
14 | config.max_number_of_devices = 5
15 |
16 | # Sometimes it's necessary to make several requests to the API at the same
17 | # time. In this case, each request in the batch will need to share the same
18 | # auth token. This setting determines how far apart the requests can be while
19 | # still using the same auth token.
20 | # config.batch_request_buffer_throttle = 5.seconds
21 |
22 | # This route will be the prefix for all oauth2 redirect callbacks. For
23 | # example, using the default '/omniauth', the github oauth2 provider will
24 | # redirect successful authentications to '/omniauth/github/callback'
25 | # config.omniauth_prefix = "/omniauth"
26 |
27 | # By default sending current password is not needed for the password update.
28 | # Uncomment to enforce current_password param to be checked before all
29 | # attribute updates. Set it to :password if you want it to be checked only if
30 | # password is updated.
31 | # config.check_current_password_before_update = :attributes
32 |
33 | # By default, only Bearer Token authentication is implemented out of the box.
34 | # If, however, you wish to integrate with legacy Devise authentication, you can
35 | # do so by enabling this flag. NOTE: This feature is highly experimental!
36 | # enable_standard_devise_support = false
37 | end
38 |
--------------------------------------------------------------------------------
/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Configure sensitive parameters which will be filtered from the log file.
4 | Rails.application.config.filter_parameters += [:password]
5 |
--------------------------------------------------------------------------------
/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format. Inflections
4 | # are locale specific, and you may define rules for as many different
5 | # locales as you wish. All of these examples are active by default:
6 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
7 | # inflect.plural /^(ox)$/i, '\1en'
8 | # inflect.singular /^(ox)en/i, '\1'
9 | # inflect.irregular 'person', 'people'
10 | # inflect.uncountable %w( fish sheep )
11 | # end
12 |
13 | # These inflection rules are supported but not enabled by default:
14 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
15 | # inflect.acronym 'RESTful'
16 | # end
17 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/config/initializers/rack_attack.rb:
--------------------------------------------------------------------------------
1 | class Rack::Attack
2 |
3 | ### Configure Cache ###
4 |
5 | # If you don't want to use Rails.cache (Rack::Attack's default), then
6 | # configure it here.
7 | #
8 | # Note: The store is only used for throttling (not blacklisting and
9 | # whitelisting). It must implement .increment and .write like
10 | # ActiveSupport::Cache::Store
11 |
12 | # Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new
13 |
14 | ### Throttle Spammy Clients ###
15 |
16 | # If any single client IP is making tons of requests, then they're
17 | # probably malicious or a poorly-configured scraper. Either way, they
18 | # don't deserve to hog all of the app server's CPU. Cut them off!
19 | #
20 | # Note: If you're serving assets through rack, those requests may be
21 | # counted by rack-attack and this throttle may be activated too
22 | # quickly. If so, enable the condition to exclude them from tracking.
23 |
24 | # Throttle all requests by IP (60rpm)
25 | #
26 | # Key: "rack::attack:#{Time.now.to_i/:period}:req/ip:#{req.ip}"
27 | Rack::Attack.throttle('req/ip', :limit => 10, :period => 1.second) do |req|
28 | req.ip # unless req.path.start_with?('/assets')
29 | end
30 |
31 |
32 | # Add to whitelist - allow for all request
33 | # Rack::Attack.whitelist('allow from localhost') do |req|
34 | # # Requests are allowed if the return value is truthy
35 | # '192.168.52.1' == req.ip
36 | # end
37 |
38 | Rack::Attack.throttled_response = lambda do |env|
39 | # name and other data about the matched throttle
40 | body = '{ "status": "error", "message": "To many request from one IP address" }'
41 | logger.warn = "IP temporary blocket by rack-attack. To many request from one IP address!"
42 | # Using 503 because it may make attacker think that they have successfully
43 | # DOSed the site. Rack::Attack returns 429 for throttling by default
44 | [ 503, {}, [body]]
45 | end
46 |
47 |
48 | # Block specifiec IP
49 | # Rack::Attack.blacklist('block 192.168.52.1') do |req|
50 | # # Requests are blocked if the return value is truthy
51 | # '192.168.52.1' == req.ip
52 | # end
53 |
54 | ### Prevent Brute-Force Login Attacks ###
55 |
56 | # The most common brute-force login attack is a brute-force password
57 | # attack where an attacker simply tries a large number of emails and
58 | # passwords to see if any credentials match.
59 | #
60 | # Another common method of attack is to use a swarm of computers with
61 | # different IPs to try brute-forcing a password for a specific account.
62 |
63 | # Throttle POST requests to /login by IP address
64 | #
65 | # Key: "rack::attack:#{Time.now.to_i/:period}:logins/ip:#{req.ip}"
66 | # throttle('logins/ip', :limit => 5, :period => 20.seconds) do |req|
67 | # if req.path == '/login' && req.post?
68 | # req.ip
69 | # end
70 | # end
71 |
72 | # Throttle POST requests to /login by email param
73 | #
74 | # Key: "rack::attack:#{Time.now.to_i/:period}:logins/email:#{req.email}"
75 | #
76 | # Note: This creates a problem where a malicious user could intentionally
77 | # throttle logins for another user and force their login requests to be
78 | # denied, but that's not very common and shouldn't happen to you. (Knock
79 | # on wood!)
80 | # throttle("logins/email", :limit => 5, :period => 20.seconds) do |req|
81 | # if req.path == '/login' && req.post?
82 | # # return the email if present, nil otherwise
83 | # req.params['email'].presence
84 | # end
85 | # end
86 |
87 | ### Custom Throttle Response ###
88 |
89 | # By default, Rack::Attack returns an HTTP 429 for throttled responses,
90 | # which is just fine.
91 | #
92 | # If you want to return 503 so that the attacker might be fooled into
93 | # believing that they've successfully broken your app (or you just want to
94 | # customize the response), then uncomment these lines.
95 | # self.throttled_response = lambda do |env|
96 | # [ 503, # status
97 | # {}, # headers
98 | # ['']] # body
99 | # end
100 | end
--------------------------------------------------------------------------------
/config/initializers/rack_timeout.rb:
--------------------------------------------------------------------------------
1 | # For more information please read https://github.com/heroku/rack-timeout
2 | Rack::Timeout.service_timeout = 30
--------------------------------------------------------------------------------
/config/initializers/readthis.rb:
--------------------------------------------------------------------------------
1 | # In some situations it is desirable to keep serving requests from disk or the database if Redis crashes. This can be achieved with connection fault tolerance by enabling it at the top leve
2 | # The default value is false, because while it may work for fetch operations, it isn't compatible with other state-based commands like increment
3 | Readthis.fault_tolerant = true
--------------------------------------------------------------------------------
/config/initializers/sidekiq.rb:
--------------------------------------------------------------------------------
1 | include Sidekiq::Worker
2 |
3 | # Configuratopn for Sidekiq Server
4 | Sidekiq.configure_server do |config|
5 | config.redis = { url: "#{ENV['REDIS_URL']}/12" }
6 | end
7 |
8 | # Configuration for Sidekiq client
9 | Sidekiq.configure_client do |config|
10 | config.redis = { url: "#{ENV['REDIS_URL']}/12" }
11 | end
12 |
13 | # Configure Sidekiq cron jobs. Load data from external, YML file
14 | schedule_file = "config/cron_jobs.yml"
15 | if File.exists?(schedule_file) && Sidekiq.server?
16 | Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file)
17 | end
--------------------------------------------------------------------------------
/config/initializers/ssl_options.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Configure SSL options to enable HSTS with subdomains.
4 | Rails.application.config.ssl_options = { hsts: { subdomains: true } }
5 |
--------------------------------------------------------------------------------
/config/initializers/to_time_preserves_timezone.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Preserve the timezone of the receiver when calling to `to_time`.
4 | # Ruby 2.4 will change the behavior of `to_time` to preserve the timezone
5 | # when converting to an instance of `Time` instead of the previous behavior
6 | # of converting to the local system timezone.
7 | #
8 | # Rails 5.0 introduced this config option so that apps made with earlier
9 | # versions of Rails are not affected when upgrading.
10 | ActiveSupport.to_time_preserves_timezone = true
11 |
--------------------------------------------------------------------------------
/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json]
9 | end
10 |
11 | # To enable root element in JSON for ActiveRecord objects.
12 | # ActiveSupport.on_load(:active_record) do
13 | # self.include_root_in_json = true
14 | # end
15 |
--------------------------------------------------------------------------------
/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 email address has been successfully confirmed."
7 | send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
8 | send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
9 | failure:
10 | already_authenticated: "You are already signed in."
11 | inactive: "Your account is not activated yet."
12 | invalid: "Invalid %{authentication_keys} or password."
13 | locked: "Your account is locked."
14 | last_attempt: "You have one more attempt before your account is locked."
15 | not_found_in_database: "Invalid %{authentication_keys} 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 email address 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 | password_change:
27 | subject: "Password Changed"
28 | omniauth_callbacks:
29 | failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
30 | success: "Successfully authenticated from %{kind} account."
31 | passwords:
32 | 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."
33 | send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
34 | 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."
35 | updated: "Your password has been changed successfully. You are now signed in."
36 | updated_not_active: "Your password has been changed successfully."
37 | registrations:
38 | destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
39 | signed_up: "Welcome! You have signed up successfully."
40 | signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
41 | signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
42 | signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
43 | update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address."
44 | updated: "Your account has been updated successfully."
45 | sessions:
46 | signed_in: "Signed in successfully."
47 | signed_out: "Signed out successfully."
48 | already_signed_out: "Signed out successfully."
49 | unlocks:
50 | send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
51 | send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
52 | unlocked: "Your account has been unlocked successfully. Please sign in to continue."
53 | errors:
54 | messages:
55 | already_confirmed: "was already confirmed, please try signing in"
56 | confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
57 | expired: "has expired, please request a new one"
58 | not_found: "not found"
59 | not_locked: "was not locked"
60 | not_saved:
61 | one: "1 error prohibited this %{resource} from being saved:"
62 | other: "%{count} errors prohibited this %{resource} from being saved:"
63 |
--------------------------------------------------------------------------------
/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Files in the config/locales directory are used for internationalization
2 | # and are automatically loaded by Rails. If you want to use locales other
3 | # than English, add the necessary files in this directory.
4 | #
5 | # To use the locales, use `I18n.t`:
6 | #
7 | # I18n.t 'hello'
8 | #
9 | # In views, this is aliased to just `t`:
10 | #
11 | # <%= t('hello') %>
12 | #
13 | # To use a different locale, set it with `I18n.locale`:
14 | #
15 | # I18n.locale = :es
16 | #
17 | # This would use the information in config/locales/es.yml.
18 | #
19 | # To learn more, please read the Rails Internationalization guide
20 | # available at http://guides.rubyonrails.org/i18n.html.
21 |
22 | en:
23 | hello: "Hello world"
24 |
--------------------------------------------------------------------------------
/config/puma.rb:
--------------------------------------------------------------------------------
1 | # Puma can serve each request in a thread from an internal thread pool.
2 | # The `threads` method setting takes two numbers a minimum and maximum.
3 | # Any libraries that use thread pools should be configured to match
4 | # the maximum value specified for Puma. Default is set to 5 threads for minimum
5 | # and maximum, this matches the default thread size of Active Record.
6 | #
7 | threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }.to_i
8 | threads threads_count, threads_count
9 |
10 | # Specifies the `port` that Puma will listen on to receive requests, default is 3000.
11 | #
12 | port ENV.fetch("PORT") { 3000 }
13 |
14 | # Specifies the `environment` that Puma will run in.
15 | #
16 | environment ENV.fetch("RAILS_ENV") { "development" }
17 |
18 | # Specifies the number of `workers` to boot in clustered mode.
19 | # Workers are forked webserver processes. If using threads and workers together
20 | # the concurrency of the application would be max `threads` * `workers`.
21 | # Workers do not work on JRuby or Windows (both of which do not support
22 | # processes).
23 | #
24 | # workers ENV.fetch("WEB_CONCURRENCY") { 2 }
25 |
26 | # Use the `preload_app!` method when specifying a `workers` number.
27 | # This directive tells Puma to first boot the application and load code
28 | # before forking the application. This takes advantage of Copy On Write
29 | # process behavior so workers use less memory. If you use this option
30 | # you need to make sure to reconnect any threads in the `on_worker_boot`
31 | # block.
32 | #
33 | # preload_app!
34 |
35 | # The code in the `on_worker_boot` will be called if you are using
36 | # clustered mode by specifying a number of `workers`. After each worker
37 | # process is booted this block will be run, if you are using `preload_app!`
38 | # option you will want to use this block to reconnect to any threads
39 | # or connections that may have been created at application boot, Ruby
40 | # cannot share connections between processes.
41 | #
42 | # on_worker_boot do
43 | # ActiveRecord::Base.establish_connection if defined?(ActiveRecord)
44 | # end
45 |
46 | # Allow puma to be restarted by `rails restart` command.
47 | plugin :tmp_restart
48 |
--------------------------------------------------------------------------------
/config/routes.rb:
--------------------------------------------------------------------------------
1 | Rails.application.routes.draw do
2 | ## For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
3 |
4 | mount_devise_token_auth_for 'User', at: 'auth'
5 |
6 | get '/', to: 'public#index', :defaults => { :format => 'json' }
7 | post '/', to: 'public#create', :defaults => { :format => 'json' }
8 |
9 | resources :todos, :defaults => { :format => 'json' }
10 |
11 | ## Secure access to sidekiq Web Interface by username and passwod
12 | Sidekiq::Web.use Rack::Auth::Basic do |username, password|
13 | username == ENV["SIDEKIQ_USERNAME"] && password == ENV["SIDEKIQ_PASSWORD"]
14 | end if Rails.env.production?
15 | mount Sidekiq::Web => '/sidekiq'
16 | end
17 |
--------------------------------------------------------------------------------
/config/secrets.yml:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Your secret key is used for verifying the integrity of signed cookies.
4 | # If you change this key, all old signed cookies will become invalid!
5 |
6 | # Make sure the secret is at least 30 characters and all random,
7 | # no regular words or you'll be exposed to dictionary attacks.
8 | # You can use `rails secret` to generate a secure secret key.
9 |
10 | # Make sure the secrets in this file are kept private
11 | # if you're sharing your code publicly.
12 |
13 | development:
14 | secret_key_base: f1a430c1a22d04648fe4a71363479a8c1e72194672bbab87c69fcf3bfbe1c86bbe96c76cfa115b9731af20bfeba3ae0a178853fa1672b038794a23dcd55c7077
15 |
16 | test:
17 | secret_key_base: c3a7257938b60f57b7586a3b0e4641ae747661720af6abab679ff89762da0379a96fd6374f18ab35f291b7286998b66629ad310155241924bd6147a9bff341b6
18 |
19 | # Do not keep production secrets in the repository,
20 | # instead read values from the environment.
21 | production:
22 | secret_key_base: f1a430c1a22d04648fe4a71363479a8c1e72194672bbab87c69fcf3bfbe1c86bbe96c76cfa115b9731af20bfeba3ae0a178853fa1672b038794a23dcd55c7088
23 |
--------------------------------------------------------------------------------
/config/sidekiq.yml:
--------------------------------------------------------------------------------
1 | ---
2 | :concurrency: 5
3 | :pidfile: tmp/pids/sidekiq.pid
4 | staging:
5 | :concurrency: 10
6 | production:
7 | :concurrency: 20
8 | :queues:
9 | - default
--------------------------------------------------------------------------------
/config/spring.rb:
--------------------------------------------------------------------------------
1 | %w(
2 | .ruby-version
3 | .rbenv-vars
4 | tmp/restart.txt
5 | tmp/caching-dev.txt
6 | ).each { |path| Spring.watch(path) }
7 |
--------------------------------------------------------------------------------
/coverage/.last_run.json:
--------------------------------------------------------------------------------
1 | {
2 | "result": {
3 | "covered_percent": 78.79
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/coverage/.resultset.json:
--------------------------------------------------------------------------------
1 | {
2 | "RSpec": {
3 | "coverage": {
4 | "/app/spec/support/settings/rspec_api_documentation.rb": [
5 | 1,
6 | null,
7 | 1,
8 | null
9 | ],
10 | "/app/spec/acceptance/todos_spec.rb": [
11 | 1,
12 | 1,
13 | 1,
14 | null,
15 | null,
16 | 1,
17 | 1,
18 | 1,
19 | 1,
20 | null,
21 | null,
22 | 1,
23 | null,
24 | 1,
25 | null,
26 | 1,
27 | null,
28 | null,
29 | 1,
30 | null,
31 | 1,
32 | 1,
33 | null,
34 | null,
35 | null,
36 | 1,
37 | 1,
38 | 1,
39 | null,
40 | 1,
41 | 1,
42 | 1,
43 | 1,
44 | 1,
45 | 1,
46 | null,
47 | null,
48 | null,
49 | null,
50 | null,
51 | null,
52 | 1,
53 | 2,
54 | 2,
55 | 2,
56 | 2,
57 | 2,
58 | null
59 | ],
60 | "/app/app/controllers/application_controller.rb": [
61 | 1,
62 | 1,
63 | 1,
64 | null,
65 | null
66 | ],
67 | "/app/app/models/todo.rb": [
68 | 1,
69 | null,
70 | 1,
71 | null,
72 | 1,
73 | 1,
74 | null,
75 | null,
76 | 1,
77 | 0,
78 | null,
79 | null,
80 | null,
81 | null
82 | ],
83 | "/app/app/models/application_record.rb": [
84 | 1,
85 | 1,
86 | null
87 | ],
88 | "/app/app/controllers/todos_controller.rb": [
89 | 1,
90 | 1,
91 | 1,
92 | null,
93 | null,
94 | null,
95 | 1,
96 | 1,
97 | null,
98 | null,
99 | null,
100 | null,
101 | 1,
102 | 0,
103 | 0,
104 | null,
105 | null,
106 | null,
107 | null,
108 | null,
109 | 1,
110 | 0,
111 | 0,
112 | 0,
113 | null,
114 | 0,
115 | null,
116 | null,
117 | null,
118 | null,
119 | null,
120 | 1,
121 | 0,
122 | 0,
123 | null,
124 | 0,
125 | null,
126 | null,
127 | null,
128 | null,
129 | null,
130 | null,
131 | 1,
132 | 0,
133 | null,
134 | null,
135 | 1,
136 | null,
137 | 1,
138 | 0,
139 | 0,
140 | null,
141 | null,
142 | null,
143 | null,
144 | 1,
145 | 0,
146 | null,
147 | null,
148 | null
149 | ]
150 | },
151 | "timestamp": 1474980334
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/coverage/.resultset.json.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/.resultset.json.lock
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/application.css:
--------------------------------------------------------------------------------
1 | /* -----------------------------------------------------------------------
2 |
3 |
4 | Blueprint CSS Framework 0.9
5 | http://blueprintcss.org
6 |
7 | * Copyright (c) 2007-Present. See LICENSE for more info.
8 | * See README for instructions on how to use Blueprint.
9 | * For credits and origins, see AUTHORS.
10 | * This is a compressed file. See the sources in the 'src' directory.
11 |
12 | ----------------------------------------------------------------------- */
13 |
14 | /* reset.css */
15 |
16 | html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, code, del, dfn, em, img, q, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, dialog, figure, footer, header, hgroup, nav, section {margin:0;padding:0;border:0;font-weight:inherit;font-style:inherit;font-size:100%;font-family:inherit;vertical-align:baseline;}
17 | article, aside, dialog, figure, footer, header, hgroup, nav, section {display:block;}
18 | body {line-height:1.5;}
19 | table {border-collapse:separate;border-spacing:0;}
20 | caption, th, td {text-align:left;font-weight:normal;}
21 | table, td, th {vertical-align:middle;}
22 | blockquote:before, blockquote:after, q:before, q:after {content:"";}
23 | blockquote, q {quotes:"" "";}
24 | a img {border:none;}
25 |
26 | /* typography.css */
27 | html {font-size:100.01%;}
28 | body {font-size:82%;color:#222;background:#fff;font-family:"Helvetica Neue", Arial, Helvetica, sans-serif;}
29 | h1, h2, h3, h4, h5, h6 {font-weight:normal;color:#111;}
30 | h1 {font-size:3em;line-height:1;margin-bottom:0.5em;}
31 | h2 {font-size:2em;margin-bottom:0.75em;}
32 | h3 {font-size:1.5em;line-height:1;margin-bottom:1em;}
33 | h4 {font-size:1.2em;line-height:1.25;margin-bottom:1.25em;}
34 | h5 {font-size:1em;font-weight:bold;margin-bottom:1.5em;}
35 | h6 {font-size:1em;font-weight:bold;}
36 | h1 img, h2 img, h3 img, h4 img, h5 img, h6 img {margin:0;}
37 | p {margin:0 0 1.5em;}
38 | p img.left {float:left;margin:1.5em 1.5em 1.5em 0;padding:0;}
39 | p img.right {float:right;margin:1.5em 0 1.5em 1.5em;}
40 | a:focus, a:hover {color:#000;}
41 | a {color:#009;text-decoration:underline;}
42 | blockquote {margin:1.5em;color:#666;font-style:italic;}
43 | strong {font-weight:bold;}
44 | em, dfn {font-style:italic;}
45 | dfn {font-weight:bold;}
46 | sup, sub {line-height:0;}
47 | abbr, acronym {border-bottom:1px dotted #666;}
48 | address {margin:0 0 1.5em;font-style:italic;}
49 | del {color:#666;}
50 | pre {margin:1.5em 0;white-space:pre;}
51 | pre, code, tt {font:1em 'andale mono', 'lucida console', monospace;line-height:1.5;}
52 | li ul, li ol {margin:0;}
53 | ul, ol {margin:0 1.5em 1.5em 0;padding-left:3.333em;}
54 | ul {list-style-type:disc;}
55 | ol {list-style-type:decimal;}
56 | dl {margin:0 0 1.5em 0;}
57 | dl dt {font-weight:bold;}
58 | dd {margin-left:1.5em;}
59 | table {margin-bottom:1.4em;width:100%;}
60 | th {font-weight:bold;}
61 | thead th {background:#c3d9ff;}
62 | th, td, caption {padding:4px 10px 4px 5px;}
63 | tr.even td {background:#efefef;}
64 | tfoot {font-style:italic;}
65 | caption {background:#eee;}
66 | .small {font-size:.8em;margin-bottom:1.875em;line-height:1.875em;}
67 | .large {font-size:1.2em;line-height:2.5em;margin-bottom:1.25em;}
68 | .hide {display:none;}
69 | .quiet {color:#666;}
70 | .loud {color:#000;}
71 | .highlight {background:#ff0;}
72 | .added {background:#060;color:#fff;}
73 | .removed {background:#900;color:#fff;}
74 | .first {margin-left:0;padding-left:0;}
75 | .last {margin-right:0;padding-right:0;}
76 | .top {margin-top:0;padding-top:0;}
77 | .bottom {margin-bottom:0;padding-bottom:0;}
78 |
79 | /* forms.css */
80 | label {font-weight:bold;}
81 | fieldset {padding:1.4em;margin:0 0 1.5em 0;border:1px solid #ccc;}
82 | legend {font-weight:bold;font-size:1.2em;}
83 | input[type=text], input[type=password], input.text, input.title, textarea, select {background-color:#fff;border:1px solid #bbb;}
84 | input[type=text]:focus, input[type=password]:focus, input.text:focus, input.title:focus, textarea:focus, select:focus {border-color:#666;}
85 | input[type=text], input[type=password], input.text, input.title, textarea, select {margin:0.5em 0;}
86 | input.text, input.title {width:300px;padding:5px;}
87 | input.title {font-size:1.5em;}
88 | textarea {width:390px;height:250px;padding:5px;}
89 | input[type=checkbox], input[type=radio], input.checkbox, input.radio {position:relative;top:.25em;}
90 | form.inline {line-height:3;}
91 | form.inline p {margin-bottom:0;}
92 | .error, .notice, .success {padding:.8em;margin-bottom:1em;border:2px solid #ddd;}
93 | .error {background:#FBE3E4;color:#8a1f11;border-color:#FBC2C4;}
94 | .notice {background:#FFF6BF;color:#514721;border-color:#FFD324;}
95 | .success {background:#E6EFC2;color:#264409;border-color:#C6D880;}
96 | .error a {color:#8a1f11;}
97 | .notice a {color:#514721;}
98 | .success a {color:#264409;}
99 | .box {padding:1.5em;margin-bottom:1.5em;background:#E5ECF9;}
100 | hr {background:#ddd;color:#ddd;clear:both;float:none;width:100%;height:.1em;margin:0 0 1.45em;border:none;}
101 | hr.space {background:#fff;color:#fff;visibility:hidden;}
102 | .clearfix:after, .container:after {content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden;}
103 | .clearfix, .container {display:block;}
104 | .clear {clear:both;}
105 | /*
106 | github.com style (c) Vasily Polovnyov
107 | */
108 |
109 |
110 | pre code {
111 | }
112 |
113 | pre .comment,
114 | pre .template_comment,
115 | pre .diff .header,
116 | pre .javadoc {
117 | color: #998;
118 | font-style: italic
119 | }
120 |
121 | pre .keyword,
122 | pre .css .rule .keyword,
123 | pre .winutils,
124 | pre .javascript .title,
125 | pre .lisp .title {
126 | color: #000;
127 | font-weight: bold
128 | }
129 |
130 | pre .number,
131 | pre .hexcolor {
132 | color: #458
133 | }
134 |
135 |
136 | pre .string,
137 | pre .tag .value,
138 | pre .phpdoc,
139 | pre .tex .formula {
140 | color: #d14
141 | }
142 |
143 | pre .subst {
144 | color: #712;
145 | }
146 |
147 | pre .constant,
148 | pre .title,
149 | pre .id {
150 | color: #900;
151 | font-weight: bold
152 | }
153 |
154 | pre .javascript .title,
155 | pre .lisp .title,
156 | pre .subst {
157 | font-weight: normal
158 | }
159 |
160 | pre .class .title,
161 | pre .haskell .label,
162 | pre .tex .command {
163 | color: #458;
164 | font-weight: bold
165 | }
166 |
167 | pre .tag,
168 | pre .tag .title,
169 | pre .rules .property,
170 | pre .django .tag .keyword {
171 | color: #000080;
172 | font-weight: normal
173 | }
174 |
175 | pre .attribute,
176 | pre .variable,
177 | pre .instancevar,
178 | pre .lisp .body {
179 | color: #008080
180 | }
181 |
182 | pre .regexp {
183 | color: #009926
184 | }
185 |
186 | pre .class {
187 | color: #458;
188 | font-weight: bold
189 | }
190 |
191 | pre .symbol,
192 | pre .ruby .symbol .string,
193 | pre .ruby .symbol .keyword,
194 | pre .ruby .symbol .keymethods,
195 | pre .lisp .keyword,
196 | pre .tex .special,
197 | pre .input_number {
198 | color: #990073
199 | }
200 |
201 | pre .builtin,
202 | pre .built_in,
203 | pre .lisp .title {
204 | color: #0086b3
205 | }
206 |
207 | pre .preprocessor,
208 | pre .pi,
209 | pre .doctype,
210 | pre .shebang,
211 | pre .cdata {
212 | color: #999;
213 | font-weight: bold
214 | }
215 |
216 | pre .deletion {
217 | background: #fdd
218 | }
219 |
220 | pre .addition {
221 | background: #dfd
222 | }
223 |
224 | pre .diff .change {
225 | background: #0086b3
226 | }
227 |
228 | pre .chunk {
229 | color: #aaa
230 | }
231 |
232 | pre .tex .formula {
233 | opacity: 0.5;
234 | }
235 | /*
236 | * jQuery UI CSS Framework @VERSION
237 | *
238 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
239 | * Dual licensed under the MIT or GPL Version 2 licenses.
240 | * http://jquery.org/license
241 | *
242 | * http://docs.jquery.com/UI/Theming/API
243 | */
244 |
245 | /* Layout helpers
246 | ----------------------------------*/
247 |
248 | .ui-helper-hidden { display: none; }
249 | .ui-helper-hidden-accessible { position: absolute; left: -99999999px; }
250 | .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
251 | .ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; }
252 | .ui-helper-clearfix { display: inline-block; }
253 | /* required comment for clearfix to work in Opera \*/
254 | * html .ui-helper-clearfix { height:1%; }
255 | .ui-helper-clearfix { display:block; }
256 | /* end clearfix */
257 | .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
258 |
259 |
260 | /* Interaction Cues
261 | ----------------------------------*/
262 | .ui-state-disabled { cursor: default !important; }
263 |
264 |
265 | /* Icons
266 | ----------------------------------*/
267 |
268 | /* states and images */
269 | .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
270 |
271 |
272 | /* Misc visuals
273 | ----------------------------------*/
274 |
275 | /* Overlays */
276 | .ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
277 |
278 |
279 | /*
280 | * jQuery UI CSS Framework @VERSION
281 | *
282 | * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
283 | * Dual licensed under the MIT or GPL Version 2 licenses.
284 | * http://jquery.org/license
285 | *
286 | * http://docs.jquery.com/UI/Theming/API
287 | *
288 | * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
289 | */
290 |
291 |
292 | /* Component containers
293 | ----------------------------------*/
294 | .ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
295 | .ui-widget .ui-widget { font-size: 1em; }
296 | .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
297 | .ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
298 | .ui-widget-content a { color: #222222; }
299 | .ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
300 | .ui-widget-header a { color: #222222; }
301 |
302 | /* Interaction states
303 | ----------------------------------*/
304 | .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
305 | .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
306 | .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
307 | .ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; }
308 | .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
309 | .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
310 | .ui-widget :active { outline: none; }
311 |
312 | /* Interaction Cues
313 | ----------------------------------*/
314 | .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
315 | .ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
316 | .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
317 | .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
318 | .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
319 | .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
320 | .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
321 | .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
322 |
323 | /* Icons
324 | ----------------------------------*/
325 |
326 | /* states and images */
327 | .ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
328 | .ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
329 | .ui-widget-header .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
330 | .ui-state-default .ui-icon { background-image: url(images/ui-icons_888888_256x240.png); }
331 | .ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
332 | .ui-state-active .ui-icon {background-image: url(images/ui-icons_454545_256x240.png); }
333 | .ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); }
334 | .ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); }
335 |
336 | /* positioning */
337 | .ui-icon-carat-1-n { background-position: 0 0; }
338 | .ui-icon-carat-1-ne { background-position: -16px 0; }
339 | .ui-icon-carat-1-e { background-position: -32px 0; }
340 | .ui-icon-carat-1-se { background-position: -48px 0; }
341 | .ui-icon-carat-1-s { background-position: -64px 0; }
342 | .ui-icon-carat-1-sw { background-position: -80px 0; }
343 | .ui-icon-carat-1-w { background-position: -96px 0; }
344 | .ui-icon-carat-1-nw { background-position: -112px 0; }
345 | .ui-icon-carat-2-n-s { background-position: -128px 0; }
346 | .ui-icon-carat-2-e-w { background-position: -144px 0; }
347 | .ui-icon-triangle-1-n { background-position: 0 -16px; }
348 | .ui-icon-triangle-1-ne { background-position: -16px -16px; }
349 | .ui-icon-triangle-1-e { background-position: -32px -16px; }
350 | .ui-icon-triangle-1-se { background-position: -48px -16px; }
351 | .ui-icon-triangle-1-s { background-position: -64px -16px; }
352 | .ui-icon-triangle-1-sw { background-position: -80px -16px; }
353 | .ui-icon-triangle-1-w { background-position: -96px -16px; }
354 | .ui-icon-triangle-1-nw { background-position: -112px -16px; }
355 | .ui-icon-triangle-2-n-s { background-position: -128px -16px; }
356 | .ui-icon-triangle-2-e-w { background-position: -144px -16px; }
357 | .ui-icon-arrow-1-n { background-position: 0 -32px; }
358 | .ui-icon-arrow-1-ne { background-position: -16px -32px; }
359 | .ui-icon-arrow-1-e { background-position: -32px -32px; }
360 | .ui-icon-arrow-1-se { background-position: -48px -32px; }
361 | .ui-icon-arrow-1-s { background-position: -64px -32px; }
362 | .ui-icon-arrow-1-sw { background-position: -80px -32px; }
363 | .ui-icon-arrow-1-w { background-position: -96px -32px; }
364 | .ui-icon-arrow-1-nw { background-position: -112px -32px; }
365 | .ui-icon-arrow-2-n-s { background-position: -128px -32px; }
366 | .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
367 | .ui-icon-arrow-2-e-w { background-position: -160px -32px; }
368 | .ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
369 | .ui-icon-arrowstop-1-n { background-position: -192px -32px; }
370 | .ui-icon-arrowstop-1-e { background-position: -208px -32px; }
371 | .ui-icon-arrowstop-1-s { background-position: -224px -32px; }
372 | .ui-icon-arrowstop-1-w { background-position: -240px -32px; }
373 | .ui-icon-arrowthick-1-n { background-position: 0 -48px; }
374 | .ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
375 | .ui-icon-arrowthick-1-e { background-position: -32px -48px; }
376 | .ui-icon-arrowthick-1-se { background-position: -48px -48px; }
377 | .ui-icon-arrowthick-1-s { background-position: -64px -48px; }
378 | .ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
379 | .ui-icon-arrowthick-1-w { background-position: -96px -48px; }
380 | .ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
381 | .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
382 | .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
383 | .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
384 | .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
385 | .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
386 | .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
387 | .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
388 | .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
389 | .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
390 | .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
391 | .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
392 | .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
393 | .ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
394 | .ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
395 | .ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
396 | .ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
397 | .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
398 | .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
399 | .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
400 | .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
401 | .ui-icon-arrow-4 { background-position: 0 -80px; }
402 | .ui-icon-arrow-4-diag { background-position: -16px -80px; }
403 | .ui-icon-extlink { background-position: -32px -80px; }
404 | .ui-icon-newwin { background-position: -48px -80px; }
405 | .ui-icon-refresh { background-position: -64px -80px; }
406 | .ui-icon-shuffle { background-position: -80px -80px; }
407 | .ui-icon-transfer-e-w { background-position: -96px -80px; }
408 | .ui-icon-transferthick-e-w { background-position: -112px -80px; }
409 | .ui-icon-folder-collapsed { background-position: 0 -96px; }
410 | .ui-icon-folder-open { background-position: -16px -96px; }
411 | .ui-icon-document { background-position: -32px -96px; }
412 | .ui-icon-document-b { background-position: -48px -96px; }
413 | .ui-icon-note { background-position: -64px -96px; }
414 | .ui-icon-mail-closed { background-position: -80px -96px; }
415 | .ui-icon-mail-open { background-position: -96px -96px; }
416 | .ui-icon-suitcase { background-position: -112px -96px; }
417 | .ui-icon-comment { background-position: -128px -96px; }
418 | .ui-icon-person { background-position: -144px -96px; }
419 | .ui-icon-print { background-position: -160px -96px; }
420 | .ui-icon-trash { background-position: -176px -96px; }
421 | .ui-icon-locked { background-position: -192px -96px; }
422 | .ui-icon-unlocked { background-position: -208px -96px; }
423 | .ui-icon-bookmark { background-position: -224px -96px; }
424 | .ui-icon-tag { background-position: -240px -96px; }
425 | .ui-icon-home { background-position: 0 -112px; }
426 | .ui-icon-flag { background-position: -16px -112px; }
427 | .ui-icon-calendar { background-position: -32px -112px; }
428 | .ui-icon-cart { background-position: -48px -112px; }
429 | .ui-icon-pencil { background-position: -64px -112px; }
430 | .ui-icon-clock { background-position: -80px -112px; }
431 | .ui-icon-disk { background-position: -96px -112px; }
432 | .ui-icon-calculator { background-position: -112px -112px; }
433 | .ui-icon-zoomin { background-position: -128px -112px; }
434 | .ui-icon-zoomout { background-position: -144px -112px; }
435 | .ui-icon-search { background-position: -160px -112px; }
436 | .ui-icon-wrench { background-position: -176px -112px; }
437 | .ui-icon-gear { background-position: -192px -112px; }
438 | .ui-icon-heart { background-position: -208px -112px; }
439 | .ui-icon-star { background-position: -224px -112px; }
440 | .ui-icon-link { background-position: -240px -112px; }
441 | .ui-icon-cancel { background-position: 0 -128px; }
442 | .ui-icon-plus { background-position: -16px -128px; }
443 | .ui-icon-plusthick { background-position: -32px -128px; }
444 | .ui-icon-minus { background-position: -48px -128px; }
445 | .ui-icon-minusthick { background-position: -64px -128px; }
446 | .ui-icon-close { background-position: -80px -128px; }
447 | .ui-icon-closethick { background-position: -96px -128px; }
448 | .ui-icon-key { background-position: -112px -128px; }
449 | .ui-icon-lightbulb { background-position: -128px -128px; }
450 | .ui-icon-scissors { background-position: -144px -128px; }
451 | .ui-icon-clipboard { background-position: -160px -128px; }
452 | .ui-icon-copy { background-position: -176px -128px; }
453 | .ui-icon-contact { background-position: -192px -128px; }
454 | .ui-icon-image { background-position: -208px -128px; }
455 | .ui-icon-video { background-position: -224px -128px; }
456 | .ui-icon-script { background-position: -240px -128px; }
457 | .ui-icon-alert { background-position: 0 -144px; }
458 | .ui-icon-info { background-position: -16px -144px; }
459 | .ui-icon-notice { background-position: -32px -144px; }
460 | .ui-icon-help { background-position: -48px -144px; }
461 | .ui-icon-check { background-position: -64px -144px; }
462 | .ui-icon-bullet { background-position: -80px -144px; }
463 | .ui-icon-radio-off { background-position: -96px -144px; }
464 | .ui-icon-radio-on { background-position: -112px -144px; }
465 | .ui-icon-pin-w { background-position: -128px -144px; }
466 | .ui-icon-pin-s { background-position: -144px -144px; }
467 | .ui-icon-play { background-position: 0 -160px; }
468 | .ui-icon-pause { background-position: -16px -160px; }
469 | .ui-icon-seek-next { background-position: -32px -160px; }
470 | .ui-icon-seek-prev { background-position: -48px -160px; }
471 | .ui-icon-seek-end { background-position: -64px -160px; }
472 | .ui-icon-seek-start { background-position: -80px -160px; }
473 | /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
474 | .ui-icon-seek-first { background-position: -80px -160px; }
475 | .ui-icon-stop { background-position: -96px -160px; }
476 | .ui-icon-eject { background-position: -112px -160px; }
477 | .ui-icon-volume-off { background-position: -128px -160px; }
478 | .ui-icon-volume-on { background-position: -144px -160px; }
479 | .ui-icon-power { background-position: 0 -176px; }
480 | .ui-icon-signal-diag { background-position: -16px -176px; }
481 | .ui-icon-signal { background-position: -32px -176px; }
482 | .ui-icon-battery-0 { background-position: -48px -176px; }
483 | .ui-icon-battery-1 { background-position: -64px -176px; }
484 | .ui-icon-battery-2 { background-position: -80px -176px; }
485 | .ui-icon-battery-3 { background-position: -96px -176px; }
486 | .ui-icon-circle-plus { background-position: 0 -192px; }
487 | .ui-icon-circle-minus { background-position: -16px -192px; }
488 | .ui-icon-circle-close { background-position: -32px -192px; }
489 | .ui-icon-circle-triangle-e { background-position: -48px -192px; }
490 | .ui-icon-circle-triangle-s { background-position: -64px -192px; }
491 | .ui-icon-circle-triangle-w { background-position: -80px -192px; }
492 | .ui-icon-circle-triangle-n { background-position: -96px -192px; }
493 | .ui-icon-circle-arrow-e { background-position: -112px -192px; }
494 | .ui-icon-circle-arrow-s { background-position: -128px -192px; }
495 | .ui-icon-circle-arrow-w { background-position: -144px -192px; }
496 | .ui-icon-circle-arrow-n { background-position: -160px -192px; }
497 | .ui-icon-circle-zoomin { background-position: -176px -192px; }
498 | .ui-icon-circle-zoomout { background-position: -192px -192px; }
499 | .ui-icon-circle-check { background-position: -208px -192px; }
500 | .ui-icon-circlesmall-plus { background-position: 0 -208px; }
501 | .ui-icon-circlesmall-minus { background-position: -16px -208px; }
502 | .ui-icon-circlesmall-close { background-position: -32px -208px; }
503 | .ui-icon-squaresmall-plus { background-position: -48px -208px; }
504 | .ui-icon-squaresmall-minus { background-position: -64px -208px; }
505 | .ui-icon-squaresmall-close { background-position: -80px -208px; }
506 | .ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
507 | .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
508 | .ui-icon-grip-solid-vertical { background-position: -32px -224px; }
509 | .ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
510 | .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
511 | .ui-icon-grip-diagonal-se { background-position: -80px -224px; }
512 |
513 |
514 | /* Misc visuals
515 | ----------------------------------*/
516 |
517 | /* Corner radius */
518 | .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; }
519 | .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
520 | .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
521 | .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
522 | .ui-corner-top { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; }
523 | .ui-corner-bottom { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
524 | .ui-corner-right { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; border-top-right-radius: 4px; -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
525 | .ui-corner-left { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; border-top-left-radius: 4px; -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
526 | .ui-corner-all { -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; }
527 |
528 | /* Overlays */
529 | .ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
530 | .ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
531 | /*
532 | ColorBox Core Style:
533 | The following CSS is consistent between example themes and should not be altered.
534 | */
535 | #colorbox, #cboxOverlay, #cboxWrapper{position:absolute; top:0; left:0; z-index:9999; overflow:hidden;}
536 | #cboxOverlay{position:fixed; width:100%; height:100%;}
537 | #cboxMiddleLeft, #cboxBottomLeft{clear:left;}
538 | #cboxContent{position:relative;}
539 | #cboxLoadedContent{overflow:auto;}
540 | #cboxTitle{margin:0;}
541 | #cboxLoadingOverlay, #cboxLoadingGraphic{position:absolute; top:0; left:0; width:100%; height:100%;}
542 | #cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{cursor:pointer;}
543 | .cboxPhoto{float:left; margin:auto; border:0; display:block; max-width:none;}
544 | .cboxIframe{width:100%; height:100%; display:block; border:0;}
545 | #colorbox, #cboxContent, #cboxLoadedContent{box-sizing:content-box;}
546 |
547 | /*
548 | User Style:
549 | Change the following styles to modify the appearance of ColorBox. They are
550 | ordered & tabbed in a way that represents the nesting of the generated HTML.
551 | */
552 | #cboxOverlay{background:#000;}
553 | #colorbox{}
554 | #cboxTopLeft{width:14px; height:14px; background:url(colorbox/controls.png) no-repeat 0 0;}
555 | #cboxTopCenter{height:14px; background:url(colorbox/border.png) repeat-x top left;}
556 | #cboxTopRight{width:14px; height:14px; background:url(colorbox/controls.png) no-repeat -36px 0;}
557 | #cboxBottomLeft{width:14px; height:43px; background:url(colorbox/controls.png) no-repeat 0 -32px;}
558 | #cboxBottomCenter{height:43px; background:url(colorbox/border.png) repeat-x bottom left;}
559 | #cboxBottomRight{width:14px; height:43px; background:url(colorbox/controls.png) no-repeat -36px -32px;}
560 | #cboxMiddleLeft{width:14px; background:url(colorbox/controls.png) repeat-y -175px 0;}
561 | #cboxMiddleRight{width:14px; background:url(colorbox/controls.png) repeat-y -211px 0;}
562 | #cboxContent{background:#fff; overflow:visible;}
563 | .cboxIframe{background:#fff;}
564 | #cboxError{padding:50px; border:1px solid #ccc;}
565 | #cboxLoadedContent{margin-bottom:5px;}
566 | #cboxLoadingOverlay{background:url(colorbox/loading_background.png) no-repeat center center;}
567 | #cboxLoadingGraphic{background:url(colorbox/loading.gif) no-repeat center center;}
568 | #cboxTitle{position:absolute; bottom:-25px; left:0; text-align:center; width:100%; font-weight:bold; color:#7C7C7C;}
569 | #cboxCurrent{position:absolute; bottom:-25px; left:58px; font-weight:bold; color:#7C7C7C;}
570 |
571 | #cboxPrevious, #cboxNext, #cboxClose, #cboxSlideshow{position:absolute; bottom:-29px; background:url(colorbox/controls.png) no-repeat 0px 0px; width:23px; height:23px; text-indent:-9999px;}
572 | #cboxPrevious{left:0px; background-position: -51px -25px;}
573 | #cboxPrevious:hover{background-position:-51px 0px;}
574 | #cboxNext{left:27px; background-position:-75px -25px;}
575 | #cboxNext:hover{background-position:-75px 0px;}
576 | #cboxClose{right:0; background-position:-100px -25px;}
577 | #cboxClose:hover{background-position:-100px 0px;}
578 |
579 | .cboxSlideshow_on #cboxSlideshow{background-position:-125px 0px; right:27px;}
580 | .cboxSlideshow_on #cboxSlideshow:hover{background-position:-150px 0px;}
581 | .cboxSlideshow_off #cboxSlideshow{background-position:-150px -25px; right:27px;}
582 | .cboxSlideshow_off #cboxSlideshow:hover{background-position:-125px 0px;}
583 | #loading {
584 | position: fixed;
585 | left: 40%;
586 | top: 50%; }
587 |
588 | a {
589 | color: #333333;
590 | text-decoration: none; }
591 | a:hover {
592 | color: black;
593 | text-decoration: underline; }
594 |
595 | body {
596 | font-family: "Lucida Grande", Helvetica, "Helvetica Neue", Arial, sans-serif;
597 | padding: 12px;
598 | background-color: #333333; }
599 |
600 | h1, h2, h3, h4 {
601 | color: #1c2324;
602 | margin: 0;
603 | padding: 0;
604 | margin-bottom: 12px; }
605 |
606 | table {
607 | width: 100%; }
608 |
609 | #content {
610 | clear: left;
611 | background-color: white;
612 | border: 2px solid #dddddd;
613 | border-top: 8px solid #dddddd;
614 | padding: 18px;
615 | -webkit-border-bottom-left-radius: 5px;
616 | -webkit-border-bottom-right-radius: 5px;
617 | -webkit-border-top-right-radius: 5px;
618 | -moz-border-radius-bottomleft: 5px;
619 | -moz-border-radius-bottomright: 5px;
620 | -moz-border-radius-topright: 5px;
621 | border-bottom-left-radius: 5px;
622 | border-bottom-right-radius: 5px;
623 | border-top-right-radius: 5px; }
624 |
625 | .dataTables_filter, .dataTables_info {
626 | padding: 2px 6px; }
627 |
628 | abbr.timeago {
629 | text-decoration: none;
630 | border: none;
631 | font-weight: bold; }
632 |
633 | .timestamp {
634 | float: right;
635 | color: #dddddd; }
636 |
637 | .group_tabs {
638 | list-style: none;
639 | float: left;
640 | margin: 0;
641 | padding: 0; }
642 | .group_tabs li {
643 | display: inline;
644 | float: left; }
645 | .group_tabs li a {
646 | font-family: Helvetica, Arial, sans-serif;
647 | display: block;
648 | float: left;
649 | text-decoration: none;
650 | padding: 4px 8px;
651 | background-color: #aaaaaa;
652 | background: -webkit-gradient(linear, 0 0, 0 bottom, from(#dddddd), to(#aaaaaa));
653 | background: -moz-linear-gradient(#dddddd, #aaaaaa);
654 | background: linear-gradient(#dddddd, #aaaaaa);
655 | text-shadow: #e5e5e5 1px 1px 0px;
656 | border-bottom: none;
657 | color: #333333;
658 | font-weight: bold;
659 | margin-right: 8px;
660 | border-top: 1px solid #efefef;
661 | -webkit-border-top-left-radius: 2px;
662 | -webkit-border-top-right-radius: 2px;
663 | -moz-border-radius-topleft: 2px;
664 | -moz-border-radius-topright: 2px;
665 | border-top-left-radius: 2px;
666 | border-top-right-radius: 2px; }
667 | .group_tabs li a:hover {
668 | background-color: #cccccc;
669 | background: -webkit-gradient(linear, 0 0, 0 bottom, from(#eeeeee), to(#aaaaaa));
670 | background: -moz-linear-gradient(#eeeeee, #aaaaaa);
671 | background: linear-gradient(#eeeeee, #aaaaaa); }
672 | .group_tabs li a:active {
673 | padding-top: 5px;
674 | padding-bottom: 3px; }
675 | .group_tabs li.active a {
676 | color: black;
677 | text-shadow: white 1px 1px 0px;
678 | background-color: #dddddd;
679 | background: -webkit-gradient(linear, 0 0, 0 bottom, from(white), to(#dddddd));
680 | background: -moz-linear-gradient(white, #dddddd);
681 | background: linear-gradient(white, #dddddd); }
682 |
683 | .file_list {
684 | margin-bottom: 18px; }
685 |
686 | a.src_link {
687 | background: url("./magnify.png") no-repeat left 50%;
688 | padding-left: 18px; }
689 |
690 | tr, td {
691 | margin: 0;
692 | padding: 0; }
693 |
694 | th {
695 | white-space: nowrap; }
696 | th.ui-state-default {
697 | cursor: pointer; }
698 | th span.ui-icon {
699 | float: left; }
700 |
701 | td {
702 | padding: 4px 8px; }
703 | td.strong {
704 | font-weight: bold; }
705 |
706 | .source_table h3, .source_table h4 {
707 | padding: 0;
708 | margin: 0;
709 | margin-bottom: 4px; }
710 | .source_table .header {
711 | padding: 10px; }
712 | .source_table pre {
713 | margin: 0;
714 | padding: 0;
715 | white-space: normal;
716 | color: black;
717 | font-family: "Monaco", "Inconsolata", "Consolas", monospace; }
718 | .source_table code {
719 | color: black;
720 | font-family: "Monaco", "Inconsolata", "Consolas", monospace; }
721 | .source_table pre {
722 | background-color: #333333; }
723 | .source_table pre ol {
724 | margin: 0px;
725 | padding: 0px;
726 | margin-left: 45px;
727 | font-size: 12px;
728 | color: white; }
729 | .source_table pre li {
730 | margin: 0px;
731 | padding: 2px 6px;
732 | border-left: 5px solid white; }
733 | .source_table pre li code {
734 | white-space: pre;
735 | white-space: pre-wrap; }
736 | .source_table pre .hits {
737 | float: right;
738 | margin-left: 10px;
739 | padding: 2px 4px;
740 | background-color: #444444;
741 | background: -webkit-gradient(linear, 0 0, 0 bottom, from(#222222), to(#666666));
742 | background: -moz-linear-gradient(#222222, #666666);
743 | background: linear-gradient(#222222, #666666);
744 | color: white;
745 | font-family: Helvetica, "Helvetica Neue", Arial, sans-serif;
746 | font-size: 10px;
747 | font-weight: bold;
748 | text-align: center;
749 | border-radius: 6px; }
750 |
751 | #footer {
752 | color: #dddddd;
753 | font-size: 12px;
754 | font-weight: bold;
755 | margin-top: 12px;
756 | text-align: right; }
757 | #footer a {
758 | color: #eeeeee;
759 | text-decoration: underline; }
760 | #footer a:hover {
761 | color: white;
762 | text-decoration: none; }
763 |
764 | .green {
765 | color: #009900; }
766 |
767 | .red {
768 | color: #990000; }
769 |
770 | .yellow {
771 | color: #ddaa00; }
772 |
773 | .source_table .covered {
774 | border-color: #009900; }
775 | .source_table .missed {
776 | border-color: #990000; }
777 | .source_table .never {
778 | border-color: black; }
779 | .source_table .skipped {
780 | border-color: #ffcc00; }
781 | .source_table .covered:nth-child(odd) {
782 | background-color: #cdf2cd; }
783 | .source_table .covered:nth-child(even) {
784 | background-color: #dbf2db; }
785 | .source_table .missed:nth-child(odd) {
786 | background-color: #f7c0c0; }
787 | .source_table .missed:nth-child(even) {
788 | background-color: #f7cfcf; }
789 | .source_table .never:nth-child(odd) {
790 | background-color: #efefef; }
791 | .source_table .never:nth-child(even) {
792 | background-color: #f4f4f4; }
793 | .source_table .skipped:nth-child(odd) {
794 | background-color: #fbf0c0; }
795 | .source_table .skipped:nth-child(even) {
796 | background-color: #fbffcf; }
797 |
798 |
799 |
800 |
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/colorbox/border.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/colorbox/border.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/colorbox/controls.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/colorbox/controls.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/colorbox/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/colorbox/loading.gif
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/colorbox/loading_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/colorbox/loading_background.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/favicon_green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/favicon_green.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/favicon_red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/favicon_red.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/favicon_yellow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/favicon_yellow.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/loading.gif
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/magnify.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/magnify.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/smoothness/images/ui-icons_222222_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/smoothness/images/ui-icons_222222_256x240.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/smoothness/images/ui-icons_2e83ff_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/smoothness/images/ui-icons_2e83ff_256x240.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/smoothness/images/ui-icons_454545_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/smoothness/images/ui-icons_454545_256x240.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/smoothness/images/ui-icons_888888_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/smoothness/images/ui-icons_888888_256x240.png
--------------------------------------------------------------------------------
/coverage/assets/0.10.0/smoothness/images/ui-icons_cd0a0a_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/coverage/assets/0.10.0/smoothness/images/ui-icons_cd0a0a_256x240.png
--------------------------------------------------------------------------------
/coverage/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Code coverage for App
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
Generated
2016-09-27T12:45:34+00:00
18 |
19 |
20 |
21 |
22 |
23 | All Files
24 | (78.79%
25 | covered at
26 |
27 |
28 | 0.88
29 |
30 | hits/line)
31 |
32 |
33 |
34 | 6 files in total.
35 | 66 relevant lines.
36 | 52 lines covered and
37 | 14 lines missed
38 |
39 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
126 |
127 |
128 |
129 |
130 |
139 |
140 |
141 |
142 |
143 |
144 | 1
145 |
146 | class ApplicationController < ActionController::API
147 |
148 |
149 |
150 | 1
151 |
152 | include DeviseTokenAuth::Concerns::SetUserByToken
153 |
154 |
155 |
156 | 1
157 |
158 | include ActionController::Caching
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 | end
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
187 |
188 |
189 |
190 |
191 |
192 | 1
193 |
194 | class TodosController < ApplicationController
195 |
196 |
197 |
198 | 1
199 |
200 | before_action :set_todo, only: [:show, :update, :destroy]
201 |
202 |
203 |
204 | 1
205 |
206 | before_action :authenticate_user!
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 | # GET /todos
219 |
220 |
221 |
222 |
223 |
224 | # GET /todos.json
225 |
226 |
227 |
228 | 1
229 |
230 | def index
231 |
232 |
233 |
234 | 1
235 |
236 | @todos = Todo.all
237 |
238 |
239 |
240 |
241 |
242 | end
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 | # GET /todos/1
255 |
256 |
257 |
258 |
259 |
260 | # GET /todos/1.json
261 |
262 |
263 |
264 | 1
265 |
266 | def show
267 |
268 |
269 |
270 |
271 |
272 | if Todo.cache_find(params[:id])
273 |
274 |
275 |
276 |
277 |
278 | @todos = Todo.cache_find(params[:id])
279 |
280 |
281 |
282 |
283 |
284 | end
285 |
286 |
287 |
288 |
289 |
290 | end
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 | # POST /todos
303 |
304 |
305 |
306 |
307 |
308 | # POST /todos.json
309 |
310 |
311 |
312 | 1
313 |
314 | def create
315 |
316 |
317 |
318 |
319 |
320 | @todo = Todo.new(todo_params)
321 |
322 |
323 |
324 |
325 |
326 | if @todo.save
327 |
328 |
329 |
330 |
331 |
332 | render :show, status: :created, location: @todo
333 |
334 |
335 |
336 |
337 |
338 | else
339 |
340 |
341 |
342 |
343 |
344 | render json: @todo.errors, status: :unprocessable_entity
345 |
346 |
347 |
348 |
349 |
350 | end
351 |
352 |
353 |
354 |
355 |
356 | end
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 | # PATCH/PUT /todos/1
369 |
370 |
371 |
372 |
373 |
374 | # PATCH/PUT /todos/1.json
375 |
376 |
377 |
378 | 1
379 |
380 | def update
381 |
382 |
383 |
384 |
385 |
386 | if @todo.update(todo_params)
387 |
388 |
389 |
390 |
391 |
392 | render :show, status: :ok, location: @todo
393 |
394 |
395 |
396 |
397 |
398 | else
399 |
400 |
401 |
402 |
403 |
404 | render json: @todo.errors, status: :unprocessable_entity
405 |
406 |
407 |
408 |
409 |
410 | end
411 |
412 |
413 |
414 |
415 |
416 | end
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 | # DELETE /todos/1
435 |
436 |
437 |
438 |
439 |
440 | # DELETE /todos/1.json
441 |
442 |
443 |
444 | 1
445 |
446 | def destroy
447 |
448 |
449 |
450 |
451 |
452 | @todo.destroy
453 |
454 |
455 |
456 |
457 |
458 | end
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 | 1
469 |
470 | private
471 |
472 |
473 |
474 |
475 |
476 | # Use callbacks to share common setup or constraints between actions.
477 |
478 |
479 |
480 | 1
481 |
482 | def set_todo
483 |
484 |
485 |
486 |
487 |
488 | if Todo.cache_find(params[:id])
489 |
490 |
491 |
492 |
493 |
494 | @todo = Todo.cache_find(params[:id])
495 |
496 |
497 |
498 |
499 |
500 | end
501 |
502 |
503 |
504 |
505 |
506 | end
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 | # Never trust parameters from the scary internet, only allow the white list through.
519 |
520 |
521 |
522 | 1
523 |
524 | def todo_params
525 |
526 |
527 |
528 |
529 |
530 | params.require(:todo).permit(:title, :completed, :order)
531 |
532 |
533 |
534 |
535 |
536 | end
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 | end
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
565 |
566 |
567 |
568 |
569 |
570 | 1
571 |
572 | class ApplicationRecord < ActiveRecord::Base
573 |
574 |
575 |
576 | 1
577 |
578 | self.abstract_class = true
579 |
580 |
581 |
582 |
583 |
584 | end
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
601 |
602 |
603 |
604 |
605 |
606 | 1
607 |
608 | class Todo < ApplicationRecord
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 | 1
619 |
620 | after_commit :flush_cache
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 | 1
631 |
632 | def flush_cache
633 |
634 |
635 |
636 | 1
637 |
638 | Rails.cache.delete([self.class.name, id])
639 |
640 |
641 |
642 |
643 |
644 | end
645 |
646 |
647 |
648 |
649 |
650 |
651 |
652 |
653 |
654 | 1
655 |
656 | def self.cache_find(id)
657 |
658 |
659 |
660 |
661 |
662 | Rails.cache.fetch([name, id]) { find(id) }
663 |
664 |
665 |
666 |
667 |
668 | end
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 | end
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
703 |
704 |
705 |
706 |
707 |
708 | 1
709 |
710 | require 'rails_helper'
711 |
712 |
713 |
714 | 1
715 |
716 | require 'rspec_api_documentation/dsl'
717 |
718 |
719 |
720 | 1
721 |
722 | require 'factory_girl'
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 | 1
739 |
740 | RspecApiDocumentation.configure do |config|
741 |
742 |
743 |
744 | 1
745 |
746 | config.format = [:json, :combined_text, :html]
747 |
748 |
749 |
750 | 1
751 |
752 | config.curl_host = 'http://localhost:3000'
753 |
754 |
755 |
756 | 1
757 |
758 | config.api_name = "Example App API"
759 |
760 |
761 |
762 |
763 |
764 | end
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 | 1
775 |
776 | resource "TODO" do
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 | 1
787 |
788 | before do
789 |
790 |
791 |
792 |
793 |
794 | # create fake element in TODOs list
795 |
796 |
797 |
798 | 1
799 |
800 | Todo.create(:title => 'This is Fake data which is put to TO', )
801 |
802 |
803 |
804 |
805 |
806 | end
807 |
808 |
809 |
810 |
811 |
812 |
813 |
814 |
815 |
816 | 1
817 |
818 | before (:each) do
819 |
820 |
821 |
822 |
823 |
824 | # create fake user
825 |
826 |
827 |
828 | 1
829 |
830 | user = FactoryGirl.build(:user)
831 |
832 |
833 |
834 | 1
835 |
836 | set_header(user.create_new_auth_token)
837 |
838 |
839 |
840 |
841 |
842 | end
843 |
844 |
845 |
846 |
847 |
848 |
849 |
850 |
851 |
852 |
853 |
854 | # GET /todos
855 |
856 |
857 |
858 | 1
859 |
860 | get "/todos.json" do
861 |
862 |
863 |
864 | 1
865 |
866 | parameter :parameter1, "The thing you want to greet"
867 |
868 |
869 |
870 | 1
871 |
872 | parameter :parameter2, "The thing you want to greet"
873 |
874 |
875 |
876 |
877 |
878 |
879 |
880 |
881 |
882 | 1
883 |
884 | it "Name showed on index page" do
885 |
886 |
887 |
888 | 1
889 |
890 | explanation "This is example comment which is added to documentation"
891 |
892 |
893 |
894 | 1
895 |
896 | do_request
897 |
898 |
899 |
900 | 1
901 |
902 | expect(response_headers["Content-Type"]).to eq("application/json; charset=utf-8")
903 |
904 |
905 |
906 | 1
907 |
908 | expect(status).to eq(200)
909 |
910 |
911 |
912 | 1
913 |
914 | expect(response_body).to include('success')
915 |
916 |
917 |
918 |
919 |
920 | end
921 |
922 |
923 |
924 |
925 |
926 | end
927 |
928 |
929 |
930 |
931 |
932 |
933 |
934 |
935 |
936 |
937 |
938 | end
939 |
940 |
941 |
942 |
943 |
944 |
945 |
946 |
947 |
948 |
949 |
950 | # Before each call, set key value to header. Required by auth
951 |
952 |
953 |
954 | 1
955 |
956 | def set_header(auth_headers)
957 |
958 |
959 |
960 | 2
961 |
962 | header 'access-token', auth_headers['access-token']
963 |
964 |
965 |
966 | 2
967 |
968 | header 'token-type', auth_headers['token-type']
969 |
970 |
971 |
972 | 2
973 |
974 | header 'client', auth_headers['client']
975 |
976 |
977 |
978 | 2
979 |
980 | header 'expiry', auth_headers['expiry']
981 |
982 |
983 |
984 | 2
985 |
986 | header 'uid', auth_headers['uid']
987 |
988 |
989 |
990 |
991 |
992 | end
993 |
994 |
995 |
996 |
997 |
998 |
999 |
1000 |
1009 |
1010 |
1011 |
1012 |
1013 |
1014 | 1
1015 |
1016 | RspecApiDocumentation.configure do |config|
1017 |
1018 |
1019 |
1020 |
1021 |
1022 | # Output folder
1023 |
1024 |
1025 |
1026 | 1
1027 |
1028 | config.docs_dir = Rails.root.join("doc", "spec_documentation")
1029 |
1030 |
1031 |
1032 |
1033 |
1034 | end
1035 |
1036 |
1037 |
1038 |
1039 |
1040 |
1041 |
1042 |
1043 |
1044 |
1045 |
--------------------------------------------------------------------------------
/db/migrate/20160515174916_create_todos.rb:
--------------------------------------------------------------------------------
1 | class CreateTodos < ActiveRecord::Migration[5.0]
2 | def change
3 | create_table :todos do |t|
4 | t.string :title
5 | t.boolean :completed
6 | t.integer :order
7 | t.timestamps
8 | end
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20160517090314_devise_token_auth_create_users.rb:
--------------------------------------------------------------------------------
1 | class DeviseTokenAuthCreateUsers < ActiveRecord::Migration
2 | def change
3 | create_table(:users) do |t|
4 | ## Required
5 | t.string :provider, :null => false, :default => "email"
6 | t.string :uid, :null => false, :default => ""
7 |
8 | ## Database authenticatable
9 | t.string :encrypted_password, :null => false, :default => ""
10 |
11 | ## Recoverable
12 | t.string :reset_password_token
13 | t.datetime :reset_password_sent_at
14 |
15 | ## Rememberable
16 | t.datetime :remember_created_at
17 |
18 | ## Trackable
19 | t.integer :sign_in_count, :default => 0, :null => false
20 | t.datetime :current_sign_in_at
21 | t.datetime :last_sign_in_at
22 | t.string :current_sign_in_ip
23 | t.string :last_sign_in_ip
24 |
25 | ## Confirmable
26 | t.string :confirmation_token
27 | t.datetime :confirmed_at
28 | t.datetime :confirmation_sent_at
29 | t.string :unconfirmed_email # Only if using reconfirmable
30 |
31 | ## Lockable
32 | # t.integer :failed_attempts, :default => 0, :null => false # Only if lock strategy is :failed_attempts
33 | # t.string :unlock_token # Only if unlock strategy is :email or :both
34 | # t.datetime :locked_at
35 |
36 | ## User Info
37 | t.string :name
38 | t.string :nickname
39 | t.string :image
40 | t.string :email
41 |
42 | ## Roles
43 | t.boolean :admin
44 |
45 | ## Tokens
46 | t.text :tokens
47 |
48 | t.timestamps
49 | end
50 |
51 | add_index :users, :email
52 | add_index :users, [:uid, :provider], :unique => true
53 | add_index :users, :reset_password_token, :unique => true
54 | # add_index :users, :confirmation_token, :unique => true
55 | # add_index :users, :unlock_token, :unique => true
56 | end
57 | end
58 |
--------------------------------------------------------------------------------
/db/schema.rb:
--------------------------------------------------------------------------------
1 | # This file is auto-generated from the current state of the database. Instead
2 | # of editing this file, please use the migrations feature of Active Record to
3 | # incrementally modify your database, and then regenerate this schema definition.
4 | #
5 | # Note that this schema.rb definition is the authoritative source for your
6 | # database schema. If you need to create the application database on another
7 | # system, you should be using db:schema:load, not running all the migrations
8 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 | # you'll amass, the slower it'll run and the greater likelihood for issues).
10 | #
11 | # It's strongly recommended that you check this file into your version control system.
12 |
13 | ActiveRecord::Schema.define(version: 20160517090314) do
14 |
15 | # These are extensions that must be enabled in order to support this database
16 | enable_extension "plpgsql"
17 |
18 | create_table "todos", force: :cascade do |t|
19 | t.string "title"
20 | t.boolean "completed"
21 | t.integer "order"
22 | t.datetime "created_at", null: false
23 | t.datetime "updated_at", null: false
24 | end
25 |
26 | create_table "users", force: :cascade do |t|
27 | t.string "provider", default: "email", null: false
28 | t.string "uid", default: "", null: false
29 | t.string "encrypted_password", default: "", null: false
30 | t.string "reset_password_token"
31 | t.datetime "reset_password_sent_at"
32 | t.datetime "remember_created_at"
33 | t.integer "sign_in_count", default: 0, null: false
34 | t.datetime "current_sign_in_at"
35 | t.datetime "last_sign_in_at"
36 | t.string "current_sign_in_ip"
37 | t.string "last_sign_in_ip"
38 | t.string "confirmation_token"
39 | t.datetime "confirmed_at"
40 | t.datetime "confirmation_sent_at"
41 | t.string "unconfirmed_email"
42 | t.string "name"
43 | t.string "nickname"
44 | t.string "image"
45 | t.string "email"
46 | t.boolean "admin"
47 | t.text "tokens"
48 | t.datetime "created_at"
49 | t.datetime "updated_at"
50 | t.index ["email"], name: "index_users_on_email", using: :btree
51 | t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
52 | t.index ["uid", "provider"], name: "index_users_on_uid_and_provider", unique: true, using: :btree
53 | end
54 |
55 | end
56 |
--------------------------------------------------------------------------------
/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 rails db:seed command (or created alongside the database with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
7 | # Character.create(name: 'Luke', movie: movies.first)
8 |
9 | 100.times do |number|
10 | User.create(:email => "test_#{number}@example.com", :password => 'examplPass123', :password_confirmation => 'examplPass123')
11 | end
--------------------------------------------------------------------------------
/doc/api.raml:
--------------------------------------------------------------------------------
1 | #%RAML 1.0
2 | title: New API
3 | version: v1
4 | protocols: [ HTTP, HTTPS ]
5 | baseUri: https://api.starterkit.hawatel.com
6 | mediaType: application/json
7 | /auth:
8 | get:
9 | responses:
10 | 200:
11 | body:
12 | application/json:
13 | example: |
14 | {
15 | "message" : "Hello World"
16 | }
17 | post:
18 | description: "Create new user"
19 | body:
20 | application/json:
21 | schema: !include schemas/auth/post.request.json
22 | example: |
23 | {
24 | "id": 123233,
25 | "name": "example"
26 | }
27 | responses:
28 | 200:
29 | body:
30 | application/json:
31 | example: |
32 | {
33 | "message" : "Hello World"
34 | }
35 |
--------------------------------------------------------------------------------
/doc/schemas/auth/post.request.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/draft-04/hyper-schema",
3 | "title": "FIXME - Auth",
4 | "description": "FIXME",
5 | "stability": "prototype",
6 | "strictProperties": true,
7 | "type": [
8 | "object"
9 | ],
10 | "properties": {
11 | "id": {
12 | "description": "unique identifier of auth",
13 | "readOnly": true,
14 | "type": [
15 | "integer"
16 | ]
17 | },
18 | "email": {
19 | "description": "unique name of auth",
20 | "type": [
21 | "string"
22 | ]
23 | },
24 | "password": {
25 | "description": "password for user",
26 | "type": [
27 | "string"
28 | ]
29 | },
30 | "password_confirmation": {
31 | "description": "confirm password for user",
32 | "type": [
33 | "string"
34 | ]
35 | },
36 | "created_at": {
37 | "description": "when auth was created",
38 | "format": "date-time",
39 | "type": [
40 | "string"
41 | ]
42 | },
43 | "updated_at": {
44 | "description": "when auth was updated",
45 | "format": "date-time",
46 | "type": [
47 | "string"
48 | ]
49 | }
50 | },
51 | "required": ["email", "password", "password_confirmation"]
52 | }
53 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 | web:
4 | environment:
5 | - REDIS_URL=redis://redis:6379
6 | build: .
7 | command: bin/rails server --port 3000 --binding 0.0.0.0
8 | ports:
9 | - "3000:3000"
10 | volumes:
11 | - .:/app
12 | volumes_from:
13 | - bundle
14 | links:
15 | - redis
16 | - postgres
17 | depends_on:
18 | - redis
19 |
20 | postgres:
21 | image: postgres:9.4
22 | environment:
23 | - POSTGRES_PASSWORD=SecurePasswordPG
24 | ports:
25 | - "5432:5432"
26 | volumes:
27 | - /tmp/rails5apistarter/postgresql:/var/lib/postgresql/data
28 |
29 | redis:
30 | image: redis
31 | command: redis-server /app/config/redis.conf
32 | volumes:
33 | - .:/app
34 | ports:
35 | - "6379"
36 |
37 | sidekiq:
38 | image: rails5apistarter_web
39 | environment:
40 | - REDIS_URL=redis://redis:6379/12
41 | links:
42 | - redis
43 | - postgres
44 | depends_on:
45 | - redis
46 | volumes:
47 | - '.:/app'
48 | volumes_from:
49 | - bundle
50 | command: sidekiq -c 25 -q default
51 |
52 | bundle:
53 | image: rails5apistarter_web
54 | volumes:
55 | - /tmp/bundle:/bundle
56 |
--------------------------------------------------------------------------------
/lib/tasks/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/lib/tasks/.keep
--------------------------------------------------------------------------------
/lib/tasks/docs_generate.rake:
--------------------------------------------------------------------------------
1 | require 'rspec/core/rake_task'
2 |
3 | desc 'Run API specs test in spec/requests'
4 | RSpec::Core::RakeTask.new('spec:docs') do |t|
5 | t.pattern = 'spec/requests/**/*_spec.rb'
6 | t.rspec_opts = ["--format RspecApiDocumentation::ApiFormatter"]
7 | end
--------------------------------------------------------------------------------
/log/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/log/.keep
--------------------------------------------------------------------------------
/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The page you were looking for doesn't exist.
62 |
You may have mistyped the address or the page may have moved.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/public/422.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
The change you wanted was rejected.
62 |
Maybe you tried to change something you didn't have access to.
63 |
64 |
If you are the application owner check the logs for more information.
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
6 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
We're sorry, but something went wrong.
62 |
63 |
If you are the application owner check the logs for more information.
64 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/public/apple-touch-icon-precomposed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/public/apple-touch-icon-precomposed.png
--------------------------------------------------------------------------------
/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/public/favicon.ico
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See http://www.robotstxt.org/robotstxt.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/acceptance/auth_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 | require 'rspec_api_documentation/dsl'
3 | require 'factory_girl'
4 |
5 | RspecApiDocumentation.configure do |config|
6 | config.format = [:json, :combined_text, :html]
7 | config.curl_host = 'http://localhost:3000'
8 | end
9 |
10 | resource "Authentication" do
11 |
12 | before(:each) do
13 | @user = FactoryGirl.build(:user)
14 | @user.create_new_auth_token
15 | end
16 |
17 | post "/auth/sign_in" do
18 | parameter :email, 'Email address'
19 | parameter :password, 'Password for user'
20 |
21 | it "incorrect login and password" do
22 | do_request(:email => 'user@dontexistr.com', :password => 'wrong_password')
23 | expect(status).to eq(401)
24 | expect(response_body).to include('Invalid login credentials')
25 | end
26 |
27 | it "user dosn't confirm registration process" do
28 | do_request(:email => @user.email, :password => @user.password) # send post data
29 | expect(status).to eq(401)
30 | expect(response_body).to include('A confirmation email was sent to your account at')
31 | end
32 |
33 | it "correct login and password" do
34 | @user.skip_confirmation!
35 | @user.save!
36 | do_request(:email => @user.email, :password => @user.password)
37 | expect(status).to eq(200)
38 | expect(response_body).to include(@user.email)
39 | end
40 | end
41 |
42 |
43 | post "/auth/" do
44 | parameter :email, 'Email address'
45 | parameter :password, 'User password'
46 | parameter :password_confirmation, 'Confirmation password'
47 | parameter :confirm_success_url, 'Redirect URL'
48 |
49 | it "user already exist" do
50 | do_request(:email => @user.email, :password => @user.password, :password_confirmation => @user.password, :confirm_success_url => 'localhost:3000')
51 | expect(status).to eq(422)
52 | expect(response_body).to include('Email already in use')
53 | end
54 |
55 | it "create new user" do
56 | @user = FactoryGirl.build(:user)
57 | do_request(:email => @user.email, :password => @user.password, :password_confirmation => @user.password, :confirm_success_url => 'localhost:3000')
58 | expect(status).to eq(200)
59 | expect(response_body).to include(@user.email)
60 | end
61 | end
62 |
63 |
64 | delete '/auth/sign_out' do
65 | it "logout current logged user" do
66 | user = FactoryGirl.build(:user)
67 | set_header(user.create_new_auth_token)
68 | do_request
69 | expect(status).to eq(200)
70 | end
71 | end
72 |
73 | end
74 |
75 | # Before each call, set key value to header. Required by auth
76 | def set_header(auth_headers)
77 | header 'access-token', auth_headers['access-token']
78 | header 'token-type', auth_headers['token-type']
79 | header 'client', auth_headers['client']
80 | header 'expiry', auth_headers['expiry']
81 | header 'uid', auth_headers['uid']
82 | end
--------------------------------------------------------------------------------
/spec/acceptance/todos_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 | require 'rspec_api_documentation/dsl'
3 | require 'factory_girl'
4 |
5 |
6 | RspecApiDocumentation.configure do |config|
7 | config.format = [:json, :combined_text, :html]
8 | config.curl_host = 'http://localhost:3000'
9 | config.api_name = "Example App API"
10 | end
11 |
12 | resource "TODO" do
13 |
14 | before do
15 | # create fake element in TODOs list
16 | Todo.create(:title => 'This is Fake data which is put to TO', )
17 | end
18 |
19 | before (:each) do
20 | # create fake user
21 | user = FactoryGirl.build(:user)
22 | set_header(user.create_new_auth_token)
23 | end
24 |
25 | # GET /todos
26 | get "/todos.json" do
27 | parameter :parameter1, "The thing you want to greet"
28 | parameter :parameter2, "The thing you want to greet"
29 |
30 | it "Name showed on index page" do
31 | explanation "This is example comment which is added to documentation"
32 | do_request
33 | expect(response_headers["Content-Type"]).to eq("application/json; charset=utf-8")
34 | expect(status).to eq(200)
35 | expect(response_body).to include('success')
36 | end
37 | end
38 |
39 | end
40 |
41 | # Before each call, set key value to header. Required by auth
42 | def set_header(auth_headers)
43 | header 'access-token', auth_headers['access-token']
44 | header 'token-type', auth_headers['token-type']
45 | header 'client', auth_headers['client']
46 | header 'expiry', auth_headers['expiry']
47 | header 'uid', auth_headers['uid']
48 | end
--------------------------------------------------------------------------------
/spec/controllers/todos_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | # This spec was generated by rspec-rails when you ran the scaffold generator.
4 | # It demonstrates how one might use RSpec to specify the controller code that
5 | # was generated by Rails when you ran the scaffold generator.
6 | #
7 | # It assumes that the implementation code is generated by the rails scaffold
8 | # generator. If you are using any extension libraries to generate different
9 | # controller code, this generated spec may or may not pass.
10 | #
11 | # It only uses APIs available in rails and/or rspec-rails. There are a number
12 | # of tools you can use to make these specs even more expressive, but we're
13 | # sticking to rails and rspec-rails APIs to keep things simple and stable.
14 | #
15 | # Compared to earlier versions of this generator, there is very limited use of
16 | # stubs and message expectations in this spec. Stubs are only used when there
17 | # is no simpler way to get a handle on the object needed for the example.
18 | # Message expectations are only used when there is no simpler way to specify
19 | # that an instance is receiving a specific message.
20 |
21 | RSpec.describe TodosController, :type => :controller do
22 |
23 | # This should return the minimal set of attributes required to create a valid
24 | # Todo. As you add validations to Todo, be sure to
25 | # adjust the attributes here as well.
26 | let(:valid_attributes) {
27 | skip("Add a hash of attributes valid for your model")
28 | }
29 |
30 | let(:invalid_attributes) {
31 | skip("Add a hash of attributes invalid for your model")
32 | }
33 |
34 | # This should return the minimal set of values that should be in the session
35 | # in order to pass any filters (e.g. authentication) defined in
36 | # TodosController. Be sure to keep this updated too.
37 | let(:valid_session) { {} }
38 |
39 | describe "GET index" do
40 | it "assigns all todos as @todos" do
41 | todo = Todo.create! valid_attributes
42 | get :public, {}, valid_session
43 | expect(assigns(:todos)).to eq([todo])
44 | end
45 | end
46 |
47 | describe "GET show" do
48 | it "assigns the requested todo as @todo" do
49 | todo = Todo.create! valid_attributes
50 | get :show, {:id => todo.to_param}, valid_session
51 | expect(assigns(:todo)).to eq(todo)
52 | end
53 | end
54 |
55 |
56 | describe "GET edit" do
57 | it "assigns the requested todo as @todo" do
58 | todo = Todo.create! valid_attributes
59 | get :edit, {:id => todo.to_param}, valid_session
60 | expect(assigns(:todo)).to eq(todo)
61 | end
62 | end
63 |
64 | describe "POST create" do
65 | describe "with valid params" do
66 | it "creates a new Todo" do
67 | expect {
68 | post :create, {:todo => valid_attributes}, valid_session
69 | }.to change(Todo, :count).by(1)
70 | end
71 |
72 | it "assigns a newly created todo as @todo" do
73 | post :create, {:todo => valid_attributes}, valid_session
74 | expect(assigns(:todo)).to be_a(Todo)
75 | expect(assigns(:todo)).to be_persisted
76 | end
77 |
78 | it "redirects to the created todo" do
79 | post :create, {:todo => valid_attributes}, valid_session
80 | expect(response).to redirect_to(Todo.last)
81 | end
82 | end
83 |
84 | describe "with invalid params" do
85 | it "assigns a newly created but unsaved todo as @todo" do
86 | post :create, {:todo => invalid_attributes}, valid_session
87 | expect(assigns(:todo)).to be_a_new(Todo)
88 | end
89 |
90 | it "re-renders the 'new' template" do
91 | post :create, {:todo => invalid_attributes}, valid_session
92 | expect(response).to render_template("new")
93 | end
94 | end
95 | end
96 |
97 | describe "PUT update" do
98 | describe "with valid params" do
99 | let(:new_attributes) {
100 | skip("Add a hash of attributes valid for your model")
101 | }
102 |
103 | it "updates the requested todo" do
104 | todo = Todo.create! valid_attributes
105 | put :update, {:id => todo.to_param, :todo => new_attributes}, valid_session
106 | todo.reload
107 | skip("Add assertions for updated state")
108 | end
109 |
110 | it "assigns the requested todo as @todo" do
111 | todo = Todo.create! valid_attributes
112 | put :update, {:id => todo.to_param, :todo => valid_attributes}, valid_session
113 | expect(assigns(:todo)).to eq(todo)
114 | end
115 |
116 | it "redirects to the todo" do
117 | todo = Todo.create! valid_attributes
118 | put :update, {:id => todo.to_param, :todo => valid_attributes}, valid_session
119 | expect(response).to redirect_to(todo)
120 | end
121 | end
122 |
123 | describe "with invalid params" do
124 | it "assigns the todo as @todo" do
125 | todo = Todo.create! valid_attributes
126 | put :update, {:id => todo.to_param, :todo => invalid_attributes}, valid_session
127 | expect(assigns(:todo)).to eq(todo)
128 | end
129 |
130 | it "re-renders the 'edit' template" do
131 | todo = Todo.create! valid_attributes
132 | put :update, {:id => todo.to_param, :todo => invalid_attributes}, valid_session
133 | expect(response).to render_template("edit")
134 | end
135 | end
136 | end
137 |
138 | describe "DELETE destroy" do
139 | it "destroys the requested todo" do
140 | todo = Todo.create! valid_attributes
141 | expect {
142 | delete :destroy, {:id => todo.to_param}, valid_session
143 | }.to change(Todo, :count).by(-1)
144 | end
145 |
146 | it "redirects to the todos list" do
147 | todo = Todo.create! valid_attributes
148 | delete :destroy, {:id => todo.to_param}, valid_session
149 | expect(response).to redirect_to(todos_url)
150 | end
151 | end
152 |
153 | end
154 |
--------------------------------------------------------------------------------
/spec/factories/todos.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :todo do
3 | title "MyString"
4 | completed false
5 | order 1
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/spec/factories/user.rb:
--------------------------------------------------------------------------------
1 | FactoryGirl.define do
2 | factory :user do
3 | name "RSpec Account"
4 | email { Faker::Internet.email }
5 | password "abc123456"
6 | password_confirmation "abc123456"
7 | end
8 | end
--------------------------------------------------------------------------------
/spec/models/todo_spec.rb:
--------------------------------------------------------------------------------
1 | require 'rails_helper'
2 |
3 | RSpec.describe Todo, :type => :model do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/spec/rails_helper.rb:
--------------------------------------------------------------------------------
1 | # This file is copied to spec/ when you run 'rails generate rspec:install'
2 | ENV["RAILS_ENV"] ||= 'test'
3 | require 'spec_helper'
4 | require File.expand_path("../../config/environment", __FILE__)
5 | require 'rspec/rails'
6 | require 'devise'
7 | require 'factory_girl_rails'
8 | require 'simplecov'
9 | SimpleCov.start
10 |
11 | # Load external settings
12 | require 'support/settings/rspec_api_documentation'
13 |
14 |
15 | # Add additional requires below this line. Rails is not loaded until this point!
16 |
17 | # Requires supporting ruby files with custom matchers and macros, etc, in
18 | # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
19 | # run as spec files by default. This means that files in spec/support that end
20 | # in _spec.rb will both be required and run as specs, causing the specs to be
21 | # run twice. It is recommended that you do not name files matching this glob to
22 | # end with _spec.rb. You can configure this pattern with the --pattern
23 | # option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
24 | #
25 | # The following line is provided for convenience purposes. It has the downside
26 | # of increasing the boot-up time by auto-requiring all files in the support
27 | # directory. Alternatively, in the individual `*_spec.rb` files, manually
28 | # require only the support files necessary.
29 | #
30 | # Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
31 |
32 | # Checks for pending migrations before tests are run.
33 | # If you are not using ActiveRecord, you can remove this line.
34 | ActiveRecord::Migration.maintain_test_schema!
35 |
36 | RSpec.configure do |config|
37 | # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
38 | config.fixture_path = "#{::Rails.root}/spec/fixtures"
39 |
40 | # If you're not using ActiveRecord, or you'd prefer not to run each of your
41 | # examples within a transaction, remove the following line or assign false
42 | # instead of true.
43 | config.use_transactional_fixtures = true
44 |
45 | # Include JSON helper.
46 | # https://github.com/collectiveidea/json_spec
47 | config.include JsonSpec::Helpers
48 |
49 | # RSpec Rails can automatically mix in different behaviours to your tests
50 | # based on their file location, for example enabling you to call `get` and
51 | # `post` in specs under `spec/controllers`.
52 | #
53 | # You can disable this behaviour by removing the line below, and instead
54 | # explicitly tag your specs with their type, e.g.:
55 | #
56 | # RSpec.describe UsersController, :type => :controller do
57 | # # ...
58 | # end
59 | #
60 | # The different available types are documented in the features, such as in
61 | # https://relishapp.com/rspec/rspec-rails/docs
62 | config.infer_spec_type_from_file_location!
63 |
64 | # Devise
65 | config.include Devise::TestHelpers, type: :controller
66 | config.include FactoryGirl::Syntax::Methods
67 |
68 | end
69 |
--------------------------------------------------------------------------------
/spec/routing/todos_routing_spec.rb:
--------------------------------------------------------------------------------
1 | require "rails_helper"
2 |
3 | RSpec.describe TodosController, :type => :routing do
4 | describe "routing" do
5 |
6 | it "routes to #index" do
7 | expect(:get => "/todos").to route_to(:format=>"json", :controller=>"todos", :action=>"index")
8 | end
9 |
10 | it "routes to #new" do
11 | expect(:get => "/todos/new").to route_to(:format=>"json", :controller=>"todos", :action=>"show", :id=>"new")
12 | end
13 |
14 | it "routes to #show" do
15 | expect(:get => "/todos/1").to route_to(:format=>"json", :controller=>"todos", :action=>"show", :id=>"1")
16 | end
17 |
18 | it "routes to #create" do
19 | expect(:post => "/todos").to route_to(:format=>"json", :controller=>"todos", :action=>"create")
20 | end
21 |
22 | it "routes to #update" do
23 | expect(:put => "/todos/1").to route_to(:format=>"json", :controller=>"todos", :action=>"update", :id=>"1")
24 | end
25 |
26 | it "routes to #destroy" do
27 | expect(:delete => "/todos/1").to route_to(:format=>"json", :controller=>"todos", :action=>"destroy", :id=>"1")
28 | end
29 |
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # This file was generated by the `rails generate rspec:install` command. Conventionally, all
2 | # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3 | # The generated `.rspec` file contains `--require spec_helper` which will cause this
4 | # file to always be loaded, without a need to explicitly require it in any files.
5 | #
6 | # Given that it is always loaded, you are encouraged to keep this file as
7 | # light-weight as possible. Requiring heavyweight dependencies from this file
8 | # will add to the boot time of your test suite on EVERY test run, even for an
9 | # individual file that may not need all of that loaded. Instead, consider making
10 | # a separate helper file that requires the additional dependencies and performs
11 | # the additional setup, and require it from the spec files that actually need it.
12 | #
13 | # The `.rspec` file also contains a few flags that are not defaults but that
14 | # users commonly want.
15 | #
16 | # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
17 | #
18 | RSpec.configure do |config|
19 | # rspec-expectations config goes here. You can use an alternate
20 | # assertion/expectation library such as wrong or the stdlib/minitest
21 | # assertions if you prefer.
22 | config.expect_with :rspec do |expectations|
23 | # This option will default to `true` in RSpec 4. It makes the `description`
24 | # and `failure_message` of custom matchers include text for helper methods
25 | # defined using `chain`, e.g.:
26 | # be_bigger_than(2).and_smaller_than(4).description
27 | # # => "be bigger than 2 and smaller than 4"
28 | # ...rather than:
29 | # # => "be bigger than 2"
30 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true
31 | end
32 |
33 | # rspec-mocks config goes here. You can use an alternate test double
34 | # library (such as bogus or mocha) by changing the `mock_with` option here.
35 | config.mock_with :rspec do |mocks|
36 | # Prevents you from mocking or stubbing a method that does not exist on
37 | # a real object. This is generally recommended, and will default to
38 | # `true` in RSpec 4.
39 | mocks.verify_partial_doubles = true
40 | end
41 |
42 | # The settings below are suggested to provide a good initial experience
43 | # with RSpec, but feel free to customize to your heart's content.
44 | =begin
45 | # These two settings work together to allow you to limit a spec run
46 | # to individual examples or groups you care about by tagging them with
47 | # `:focus` metadata. When nothing is tagged with `:focus`, all examples
48 | # get run.
49 | config.filter_run :focus
50 | config.run_all_when_everything_filtered = true
51 |
52 | # Limits the available syntax to the non-monkey patched syntax that is recommended.
53 | # For more details, see:
54 | # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
55 | # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
56 | # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
57 | config.disable_monkey_patching!
58 |
59 | # Many RSpec users commonly either run the entire suite or an individual
60 | # file, and it's useful to allow more verbose output when running an
61 | # individual spec file.
62 | if config.files_to_run.one?
63 | # Use the documentation formatter for detailed output,
64 | # unless a formatter has already been configured
65 | # (e.g. via a command-line flag).
66 | config.default_formatter = 'doc'
67 | end
68 |
69 | # Print the 10 slowest examples and example groups at the
70 | # end of the spec run, to help surface which specs are running
71 | # particularly slow.
72 | config.profile_examples = 10
73 |
74 | # Run specs in random order to surface order dependencies. If you find an
75 | # order dependency and want to debug it, you can fix the order by providing
76 | # the seed, which is printed after each run.
77 | # --seed 1234
78 | config.order = :random
79 |
80 | # Seed global randomization in this process using the `--seed` CLI option.
81 | # Setting this allows you to use `--seed` to deterministically reproduce
82 | # test failures related to randomization by passing the same `--seed` value
83 | # as the one that triggered the failure.
84 | Kernel.srand config.seed
85 | =end
86 | end
87 |
--------------------------------------------------------------------------------
/spec/support/settings/rspec_api_documentation.rb:
--------------------------------------------------------------------------------
1 | RspecApiDocumentation.configure do |config|
2 | # Output folder
3 | config.docs_dir = Rails.root.join("doc", "spec_documentation")
4 |
5 | # Output format
6 | config.format = [:html]
7 |
8 | # Change the name of the API on index pages
9 | config.api_name = "API Documentation"
10 | end
11 |
--------------------------------------------------------------------------------
/tmp/.keep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hawatel/rails5-api-starter/abd21c252aa844be9d5abe8418b12ab40bb1f9d9/tmp/.keep
--------------------------------------------------------------------------------