├── .gitignore ├── .rspec ├── .ruby-version ├── Gemfile ├── Gemfile.lock ├── README.md ├── Rakefile ├── app ├── assets │ ├── images │ │ └── .keep │ ├── javascripts │ │ └── application.js │ └── stylesheets │ │ ├── _helpers.sass │ │ ├── _media.sass │ │ ├── application.css.sass │ │ ├── bourbon │ │ ├── _bourbon-deprecated-upcoming.scss │ │ ├── _bourbon.scss │ │ ├── addons │ │ │ ├── _button.scss │ │ │ ├── _clearfix.scss │ │ │ ├── _directional-values.scss │ │ │ ├── _ellipsis.scss │ │ │ ├── _font-family.scss │ │ │ ├── _hide-text.scss │ │ │ ├── _html5-input-types.scss │ │ │ ├── _position.scss │ │ │ ├── _prefixer.scss │ │ │ ├── _retina-image.scss │ │ │ ├── _size.scss │ │ │ ├── _timing-functions.scss │ │ │ ├── _triangle.scss │ │ │ └── _word-wrap.scss │ │ ├── css3 │ │ │ ├── _animation.scss │ │ │ ├── _appearance.scss │ │ │ ├── _backface-visibility.scss │ │ │ ├── _background-image.scss │ │ │ ├── _background.scss │ │ │ ├── _border-image.scss │ │ │ ├── _border-radius.scss │ │ │ ├── _box-sizing.scss │ │ │ ├── _calc.scss │ │ │ ├── _columns.scss │ │ │ ├── _filter.scss │ │ │ ├── _flex-box.scss │ │ │ ├── _font-face.scss │ │ │ ├── _font-feature-settings.scss │ │ │ ├── _hidpi-media-query.scss │ │ │ ├── _hyphens.scss │ │ │ ├── _image-rendering.scss │ │ │ ├── _inline-block.scss │ │ │ ├── _keyframes.scss │ │ │ ├── _linear-gradient.scss │ │ │ ├── _perspective.scss │ │ │ ├── _placeholder.scss │ │ │ ├── _radial-gradient.scss │ │ │ ├── _transform.scss │ │ │ ├── _transition.scss │ │ │ └── _user-select.scss │ │ ├── functions │ │ │ ├── _color-lightness.scss │ │ │ ├── _flex-grid.scss │ │ │ ├── _golden-ratio.scss │ │ │ ├── _grid-width.scss │ │ │ ├── _linear-gradient.scss │ │ │ ├── _modular-scale.scss │ │ │ ├── _px-to-em.scss │ │ │ ├── _px-to-rem.scss │ │ │ ├── _radial-gradient.scss │ │ │ ├── _strip-units.scss │ │ │ ├── _tint-shade.scss │ │ │ ├── _transition-property-name.scss │ │ │ └── _unpack.scss │ │ ├── helpers │ │ │ ├── _gradient-positions-parser.scss │ │ │ ├── _linear-positions-parser.scss │ │ │ ├── _radial-arg-parser.scss │ │ │ ├── _radial-positions-parser.scss │ │ │ ├── _render-gradients.scss │ │ │ └── _shape-size-stripper.scss │ │ └── settings │ │ │ ├── _asset-pipeline.scss │ │ │ ├── _prefixer.scss │ │ │ └── _px-to-em.scss │ │ ├── devise.css.sass │ │ └── normalize.scss ├── controllers │ ├── admin │ │ ├── confirmations_controller.rb │ │ ├── omniauth_callbacks_controller.rb │ │ ├── passwords_controller.rb │ │ ├── registrations_controller.rb │ │ ├── sessions_controller.rb │ │ └── unlocks_controller.rb │ ├── api │ │ └── hotels_controller.rb │ ├── application_controller.rb │ ├── concerns │ │ └── .keep │ └── home_controller.rb ├── helpers │ └── application_helper.rb ├── mailers │ ├── .gitkeep │ └── .keep ├── models │ ├── .keep │ ├── admin.rb │ ├── concerns │ │ └── .keep │ └── hotel.rb └── views │ ├── home │ └── index.html.erb │ └── layouts │ ├── admin.html.erb │ └── application.html.erb ├── bin ├── bundle ├── rails ├── rake └── spring ├── config.ru ├── config ├── application.rb ├── boot.rb ├── database.yml ├── deploy.rb ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── assets.rb │ ├── backtrace_silencers.rb │ ├── cookies_serializer.rb │ ├── devise.rb │ ├── filter_parameter_logging.rb │ ├── inflections.rb │ ├── locale.rb │ ├── mime_types.rb │ ├── rails_admin.rb │ ├── session_store.rb │ └── wrap_parameters.rb ├── locales │ ├── devise.en.yml │ └── en.yml ├── routes.rb └── secrets.yml ├── contributors.txt ├── db ├── migrate │ ├── 20160218131223_devise_create_admins.rb │ └── 20160308164308_create_hotels.rb ├── schema.rb └── seeds.rb ├── lib ├── assets │ └── .keep └── tasks │ └── .keep ├── log └── .keep ├── public ├── 404.html ├── 422.html ├── 500.html ├── favicon.ico ├── index.html ├── js │ ├── app.js │ ├── controllers.js │ └── services.js ├── lib │ ├── angular-resource.min.js │ ├── angular-ui-router.min.js │ └── angular.min.js ├── partials │ ├── _form.html │ ├── edit.html │ ├── index.html │ ├── new.html │ ├── search.html │ └── show.html └── robots.txt ├── spec ├── controllers │ └── api │ │ └── hotels_controller_spec.rb ├── factories.rb ├── models │ └── hotel_spec.rb ├── rails_helper.rb ├── spec_helper.rb └── support │ ├── api │ └── schemas │ │ ├── hotel.json │ │ ├── hotels.json │ │ └── missing_required_fields.json │ ├── api_helper.rb │ ├── api_schema_matcher.rb │ ├── database_cleaner.rb │ └── factory_girl.rb └── vendor └── assets ├── javascripts └── .keep └── stylesheets └── .keep /.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/*.log 16 | /tmp 17 | 18 | .DS_Store 19 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require spec_helper 3 | --format documentation 4 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.2.2@hotels 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'rails', '4.2.3' 4 | gem 'pg', '0.18.4' 5 | gem 'search_cop' 6 | 7 | gem 'inherited_resources','1.6' 8 | gem 'rack-cors', require: 'rack/cors' 9 | 10 | gem 'rails_admin', '0.8.1' 11 | gem 'devise','~> 3.4.1' 12 | 13 | group :development do 14 | gem 'better_errors', group: :development 15 | gem 'binding_of_caller', group: :development 16 | gem 'mina','0.3.8', group: :development 17 | end 18 | 19 | 20 | 21 | group :development, :test do 22 | gem 'pry', group: :development 23 | gem 'pry-nav', group: :development 24 | end 25 | 26 | group :test do 27 | gem 'factory_girl_rails' 28 | gem 'rspec-rails', '~> 3.0' 29 | gem 'shoulda-matchers', '~> 3.1' 30 | gem 'database_cleaner' 31 | gem 'json-schema' 32 | end 33 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | actionmailer (4.2.3) 5 | actionpack (= 4.2.3) 6 | actionview (= 4.2.3) 7 | activejob (= 4.2.3) 8 | mail (~> 2.5, >= 2.5.4) 9 | rails-dom-testing (~> 1.0, >= 1.0.5) 10 | actionpack (4.2.3) 11 | actionview (= 4.2.3) 12 | activesupport (= 4.2.3) 13 | rack (~> 1.6) 14 | rack-test (~> 0.6.2) 15 | rails-dom-testing (~> 1.0, >= 1.0.5) 16 | rails-html-sanitizer (~> 1.0, >= 1.0.2) 17 | actionview (4.2.3) 18 | activesupport (= 4.2.3) 19 | builder (~> 3.1) 20 | erubis (~> 2.7.0) 21 | rails-dom-testing (~> 1.0, >= 1.0.5) 22 | rails-html-sanitizer (~> 1.0, >= 1.0.2) 23 | activejob (4.2.3) 24 | activesupport (= 4.2.3) 25 | globalid (>= 0.3.0) 26 | activemodel (4.2.3) 27 | activesupport (= 4.2.3) 28 | builder (~> 3.1) 29 | activerecord (4.2.3) 30 | activemodel (= 4.2.3) 31 | activesupport (= 4.2.3) 32 | arel (~> 6.0) 33 | activesupport (4.2.3) 34 | i18n (~> 0.7) 35 | json (~> 1.7, >= 1.7.7) 36 | minitest (~> 5.1) 37 | thread_safe (~> 0.3, >= 0.3.4) 38 | tzinfo (~> 1.1) 39 | addressable (2.3.8) 40 | arel (6.0.3) 41 | bcrypt (3.1.11) 42 | better_errors (2.1.1) 43 | coderay (>= 1.0.0) 44 | erubis (>= 2.6.6) 45 | rack (>= 0.9.0) 46 | binding_of_caller (0.7.2) 47 | debug_inspector (>= 0.0.1) 48 | builder (3.2.2) 49 | coderay (1.1.1) 50 | coffee-rails (4.1.1) 51 | coffee-script (>= 2.2.0) 52 | railties (>= 4.0.0, < 5.1.x) 53 | coffee-script (2.4.1) 54 | coffee-script-source 55 | execjs 56 | coffee-script-source (1.10.0) 57 | concurrent-ruby (1.0.1) 58 | database_cleaner (1.5.1) 59 | debug_inspector (0.0.2) 60 | devise (3.4.1) 61 | bcrypt (~> 3.0) 62 | orm_adapter (~> 0.1) 63 | railties (>= 3.2.6, < 5) 64 | responders 65 | thread_safe (~> 0.1) 66 | warden (~> 1.2.3) 67 | diff-lcs (1.2.5) 68 | erubis (2.7.0) 69 | execjs (2.6.0) 70 | factory_girl (4.5.0) 71 | activesupport (>= 3.0.0) 72 | factory_girl_rails (4.6.0) 73 | factory_girl (~> 4.5.0) 74 | railties (>= 3.0.0) 75 | font-awesome-rails (4.5.0.1) 76 | railties (>= 3.2, < 5.1) 77 | globalid (0.3.6) 78 | activesupport (>= 4.1.0) 79 | haml (4.0.7) 80 | tilt 81 | has_scope (0.6.0) 82 | actionpack (>= 3.2, < 5) 83 | activesupport (>= 3.2, < 5) 84 | i18n (0.7.0) 85 | inherited_resources (1.6.0) 86 | actionpack (>= 3.2, < 5) 87 | has_scope (~> 0.6.0.rc) 88 | railties (>= 3.2, < 5) 89 | responders 90 | jquery-rails (4.1.0) 91 | rails-dom-testing (~> 1.0) 92 | railties (>= 4.2.0) 93 | thor (>= 0.14, < 2.0) 94 | jquery-ui-rails (5.0.5) 95 | railties (>= 3.2.16) 96 | json (1.8.3) 97 | json-schema (2.6.1) 98 | addressable (~> 2.3.8) 99 | kaminari (0.16.3) 100 | actionpack (>= 3.0.0) 101 | activesupport (>= 3.0.0) 102 | loofah (2.0.3) 103 | nokogiri (>= 1.5.9) 104 | mail (2.6.3) 105 | mime-types (>= 1.16, < 3) 106 | method_source (0.8.2) 107 | mime-types (2.99.1) 108 | mina (0.3.8) 109 | open4 (~> 1.3.4) 110 | rake 111 | mini_portile2 (2.0.0) 112 | minitest (5.8.4) 113 | nested_form (0.3.2) 114 | nokogiri (1.6.7.2) 115 | mini_portile2 (~> 2.0.0.rc2) 116 | open4 (1.3.4) 117 | orm_adapter (0.5.0) 118 | pg (0.18.4) 119 | polyglot (0.3.5) 120 | pry (0.10.3) 121 | coderay (~> 1.1.0) 122 | method_source (~> 0.8.1) 123 | slop (~> 3.4) 124 | pry-nav (0.2.4) 125 | pry (>= 0.9.10, < 0.11.0) 126 | rack (1.6.4) 127 | rack-cors (0.4.0) 128 | rack-pjax (0.8.0) 129 | nokogiri (~> 1.5) 130 | rack (~> 1.1) 131 | rack-test (0.6.3) 132 | rack (>= 1.0) 133 | rails (4.2.3) 134 | actionmailer (= 4.2.3) 135 | actionpack (= 4.2.3) 136 | actionview (= 4.2.3) 137 | activejob (= 4.2.3) 138 | activemodel (= 4.2.3) 139 | activerecord (= 4.2.3) 140 | activesupport (= 4.2.3) 141 | bundler (>= 1.3.0, < 2.0) 142 | railties (= 4.2.3) 143 | sprockets-rails 144 | rails-deprecated_sanitizer (1.0.3) 145 | activesupport (>= 4.2.0.alpha) 146 | rails-dom-testing (1.0.7) 147 | activesupport (>= 4.2.0.beta, < 5.0) 148 | nokogiri (~> 1.6.0) 149 | rails-deprecated_sanitizer (>= 1.0.1) 150 | rails-html-sanitizer (1.0.3) 151 | loofah (~> 2.0) 152 | rails_admin (0.8.1) 153 | builder (~> 3.1) 154 | coffee-rails (~> 4.0) 155 | font-awesome-rails (>= 3.0, < 5) 156 | haml (~> 4.0) 157 | jquery-rails (>= 3.0, < 5) 158 | jquery-ui-rails (~> 5.0) 159 | kaminari (~> 0.14) 160 | nested_form (~> 0.3) 161 | rack-pjax (~> 0.7) 162 | rails (~> 4.0) 163 | remotipart (~> 1.0) 164 | safe_yaml (~> 1.0) 165 | sass-rails (>= 4.0, < 6) 166 | railties (4.2.3) 167 | actionpack (= 4.2.3) 168 | activesupport (= 4.2.3) 169 | rake (>= 0.8.7) 170 | thor (>= 0.18.1, < 2.0) 171 | rake (10.5.0) 172 | remotipart (1.2.1) 173 | responders (2.1.1) 174 | railties (>= 4.2.0, < 5.1) 175 | rspec-core (3.4.3) 176 | rspec-support (~> 3.4.0) 177 | rspec-expectations (3.4.0) 178 | diff-lcs (>= 1.2.0, < 2.0) 179 | rspec-support (~> 3.4.0) 180 | rspec-mocks (3.4.1) 181 | diff-lcs (>= 1.2.0, < 2.0) 182 | rspec-support (~> 3.4.0) 183 | rspec-rails (3.4.2) 184 | actionpack (>= 3.0, < 4.3) 185 | activesupport (>= 3.0, < 4.3) 186 | railties (>= 3.0, < 4.3) 187 | rspec-core (~> 3.4.0) 188 | rspec-expectations (~> 3.4.0) 189 | rspec-mocks (~> 3.4.0) 190 | rspec-support (~> 3.4.0) 191 | rspec-support (3.4.1) 192 | safe_yaml (1.0.4) 193 | sass (3.4.21) 194 | sass-rails (5.0.4) 195 | railties (>= 4.0.0, < 5.0) 196 | sass (~> 3.1) 197 | sprockets (>= 2.8, < 4.0) 198 | sprockets-rails (>= 2.0, < 4.0) 199 | tilt (>= 1.1, < 3) 200 | search_cop (1.0.6) 201 | treetop 202 | shoulda-matchers (3.1.1) 203 | activesupport (>= 4.0.0) 204 | slop (3.6.0) 205 | sprockets (3.5.2) 206 | concurrent-ruby (~> 1.0) 207 | rack (> 1, < 3) 208 | sprockets-rails (3.0.4) 209 | actionpack (>= 4.0) 210 | activesupport (>= 4.0) 211 | sprockets (>= 3.0.0) 212 | thor (0.19.1) 213 | thread_safe (0.3.5) 214 | tilt (2.0.2) 215 | treetop (1.6.5) 216 | polyglot (~> 0.3) 217 | tzinfo (1.2.2) 218 | thread_safe (~> 0.1) 219 | warden (1.2.6) 220 | rack (>= 1.0) 221 | 222 | PLATFORMS 223 | ruby 224 | 225 | DEPENDENCIES 226 | better_errors 227 | binding_of_caller 228 | database_cleaner 229 | devise (~> 3.4.1) 230 | factory_girl_rails 231 | inherited_resources (= 1.6) 232 | json-schema 233 | mina (= 0.3.8) 234 | pg (= 0.18.4) 235 | pry 236 | pry-nav 237 | rack-cors 238 | rails (= 4.2.3) 239 | rails_admin (= 0.8.1) 240 | rspec-rails (~> 3.0) 241 | search_cop 242 | shoulda-matchers (~> 3.1) 243 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular JS + Rails Crud Example 2 | 3 | ## Run 4 | 5 | ### 1. Install Postgres 6 | 7 | brew update 8 | brew install postgres 9 | 10 | #### 1.1 Run PG 11 | 12 | postgres -D /usr/local/var/postgres 13 | 14 | #### 1.2 Create a new User 15 | 16 | createuser --interactive 17 | 18 | And add it as superuser, just to run locally (never do that in production!) 19 | 20 | Enter name of role to add: hotels 21 | Shall the new role be a superuser? (y/n) Y 22 | 23 | ### 2. Install RVM 24 | 25 | curl -sSL https://get.rvm.io | bash -s stable 26 | 27 | #### 2.1 Export RVM to PATH and reload the bashrc 28 | 29 | export PATH="$PATH:$HOME/.rvm/bin" 30 | source ~/.bashrc 31 | 32 | #### 2.2. Test the RVM 33 | 34 | type rvm | head -n 1 35 | 36 | The terminal should show something like "rvm is a shell function". 37 | 38 | #### 3. Install Ruby 39 | 40 | rvm install ruby-2.2.2 41 | 42 | #### 4. Install the project dependencies (inside the project folder) 43 | 44 | bundle install 45 | 46 | #### 5. Create the database and migrations 47 | 48 | bundle exec rake db:create db:migrate db:seed 49 | 50 | #### 6. Run the tests 51 | 52 | rspec 53 | 54 | #### 7. Run the server 55 | 56 | rails s -p 3000 57 | 58 | Now you enviorement is read to use and you can find all hotels at: * http://localhost:3000/api/hotels * 59 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require File.expand_path('../config/application', __FILE__) 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zekitow/rails-api-and-angularjs/46f50e9d6c80071dd89f2c7557c80e3ced8e9003/app/assets/images/.keep -------------------------------------------------------------------------------- /app/assets/javascripts/application.js: -------------------------------------------------------------------------------- 1 | //= require jquery 2 | //= require jquery_ujs -------------------------------------------------------------------------------- /app/assets/stylesheets/_helpers.sass: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zekitow/rails-api-and-angularjs/46f50e9d6c80071dd89f2c7557c80e3ced8e9003/app/assets/stylesheets/_helpers.sass -------------------------------------------------------------------------------- /app/assets/stylesheets/_media.sass: -------------------------------------------------------------------------------- 1 | @media (min-width: 768px) // Tablet 2 | 3 | @media (min-width: 992px) // Tablet land 4 | 5 | @media (min-width: 1200px) // Full HD -------------------------------------------------------------------------------- /app/assets/stylesheets/application.css.sass: -------------------------------------------------------------------------------- 1 | @import 'bourbon/bourbon' 2 | @import 'helpers' 3 | 4 | // content 5 | 6 | @import 'media' 7 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/_bourbon-deprecated-upcoming.scss: -------------------------------------------------------------------------------- 1 | //************************************************************************// 2 | // These mixins/functions are deprecated 3 | // They will be removed in the next MAJOR version release 4 | //************************************************************************// 5 | @mixin box-shadow ($shadows...) { 6 | @include prefixer(box-shadow, $shadows, spec); 7 | @warn "box-shadow is deprecated and will be removed in the next major version release"; 8 | } 9 | 10 | @mixin background-size ($lengths...) { 11 | @include prefixer(background-size, $lengths, spec); 12 | @warn "background-size is deprecated and will be removed in the next major version release"; 13 | } 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/_bourbon.scss: -------------------------------------------------------------------------------- 1 | // Bourbon 3.2.4 2 | // http://bourbon.io 3 | // Copyright 2011-2015 thoughtbot, inc. 4 | // MIT License 5 | 6 | // Settings 7 | @import "settings/prefixer"; 8 | @import "settings/px-to-em"; 9 | @import "settings/asset-pipeline"; 10 | 11 | // Custom Helpers 12 | @import "helpers/gradient-positions-parser"; 13 | @import "helpers/linear-positions-parser"; 14 | @import "helpers/radial-arg-parser"; 15 | @import "helpers/radial-positions-parser"; 16 | @import "helpers/render-gradients"; 17 | @import "helpers/shape-size-stripper"; 18 | 19 | // Custom Functions 20 | @import "functions/color-lightness"; 21 | @import "functions/flex-grid"; 22 | @import "functions/golden-ratio"; 23 | @import "functions/grid-width"; 24 | @import "functions/linear-gradient"; 25 | @import "functions/modular-scale"; 26 | @import "functions/px-to-em"; 27 | @import "functions/px-to-rem"; 28 | @import "functions/radial-gradient"; 29 | @import "functions/strip-units"; 30 | @import "functions/tint-shade"; 31 | @import "functions/transition-property-name"; 32 | @import "functions/unpack"; 33 | 34 | // CSS3 Mixins 35 | @import "css3/animation"; 36 | @import "css3/appearance"; 37 | @import "css3/backface-visibility"; 38 | @import "css3/background"; 39 | @import "css3/background-image"; 40 | @import "css3/border-image"; 41 | @import "css3/border-radius"; 42 | @import "css3/box-sizing"; 43 | @import "css3/calc"; 44 | @import "css3/columns"; 45 | @import "css3/filter"; 46 | @import "css3/flex-box"; 47 | @import "css3/font-face"; 48 | @import "css3/font-feature-settings"; 49 | @import "css3/hyphens"; 50 | @import "css3/hidpi-media-query"; 51 | @import "css3/image-rendering"; 52 | @import "css3/inline-block"; 53 | @import "css3/keyframes"; 54 | @import "css3/linear-gradient"; 55 | @import "css3/perspective"; 56 | @import "css3/radial-gradient"; 57 | @import "css3/transform"; 58 | @import "css3/transition"; 59 | @import "css3/user-select"; 60 | @import "css3/placeholder"; 61 | 62 | // Addons & other mixins 63 | @import "addons/button"; 64 | @import "addons/clearfix"; 65 | @import "addons/directional-values"; 66 | @import "addons/ellipsis"; 67 | @import "addons/font-family"; 68 | @import "addons/hide-text"; 69 | @import "addons/html5-input-types"; 70 | @import "addons/position"; 71 | @import "addons/prefixer"; 72 | @import "addons/retina-image"; 73 | @import "addons/size"; 74 | @import "addons/timing-functions"; 75 | @import "addons/triangle"; 76 | @import "addons/word-wrap"; 77 | 78 | // Soon to be deprecated Mixins 79 | @import "bourbon-deprecated-upcoming"; 80 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_button.scss: -------------------------------------------------------------------------------- 1 | @mixin button ($style: simple, $base-color: #4294f0, $text-size: inherit, $padding: 7px 18px) { 2 | 3 | @if type-of($style) == string and type-of($base-color) == color { 4 | @include buttonstyle($style, $base-color, $text-size, $padding); 5 | } 6 | 7 | @if type-of($style) == string and type-of($base-color) == number { 8 | $padding: $text-size; 9 | $text-size: $base-color; 10 | $base-color: #4294f0; 11 | 12 | @if $padding == inherit { 13 | $padding: 7px 18px; 14 | } 15 | 16 | @include buttonstyle($style, $base-color, $text-size, $padding); 17 | } 18 | 19 | @if type-of($style) == color and type-of($base-color) == color { 20 | $base-color: $style; 21 | $style: simple; 22 | @include buttonstyle($style, $base-color, $text-size, $padding); 23 | } 24 | 25 | @if type-of($style) == color and type-of($base-color) == number { 26 | $padding: $text-size; 27 | $text-size: $base-color; 28 | $base-color: $style; 29 | $style: simple; 30 | 31 | @if $padding == inherit { 32 | $padding: 7px 18px; 33 | } 34 | 35 | @include buttonstyle($style, $base-color, $text-size, $padding); 36 | } 37 | 38 | @if type-of($style) == number { 39 | $padding: $base-color; 40 | $text-size: $style; 41 | $base-color: #4294f0; 42 | $style: simple; 43 | 44 | @if $padding == #4294f0 { 45 | $padding: 7px 18px; 46 | } 47 | 48 | @include buttonstyle($style, $base-color, $text-size, $padding); 49 | } 50 | 51 | &:disabled { 52 | opacity: 0.5; 53 | cursor: not-allowed; 54 | } 55 | } 56 | 57 | 58 | // Selector Style Button 59 | //************************************************************************// 60 | @mixin buttonstyle($type, $b-color, $t-size, $pad) { 61 | // Grayscale button 62 | @if $type == simple and $b-color == grayscale($b-color) { 63 | @include simple($b-color, true, $t-size, $pad); 64 | } 65 | 66 | @if $type == shiny and $b-color == grayscale($b-color) { 67 | @include shiny($b-color, true, $t-size, $pad); 68 | } 69 | 70 | @if $type == pill and $b-color == grayscale($b-color) { 71 | @include pill($b-color, true, $t-size, $pad); 72 | } 73 | 74 | @if $type == flat and $b-color == grayscale($b-color) { 75 | @include flat($b-color, true, $t-size, $pad); 76 | } 77 | 78 | // Colored button 79 | @if $type == simple { 80 | @include simple($b-color, false, $t-size, $pad); 81 | } 82 | 83 | @else if $type == shiny { 84 | @include shiny($b-color, false, $t-size, $pad); 85 | } 86 | 87 | @else if $type == pill { 88 | @include pill($b-color, false, $t-size, $pad); 89 | } 90 | 91 | @else if $type == flat { 92 | @include flat($b-color, false, $t-size, $pad); 93 | } 94 | } 95 | 96 | 97 | // Simple Button 98 | //************************************************************************// 99 | @mixin simple($base-color, $grayscale: false, $textsize: inherit, $padding: 7px 18px) { 100 | $color: hsl(0, 0, 100%); 101 | $border: adjust-color($base-color, $saturation: 9%, $lightness: -14%); 102 | $inset-shadow: adjust-color($base-color, $saturation: -8%, $lightness: 15%); 103 | $stop-gradient: adjust-color($base-color, $saturation: 9%, $lightness: -11%); 104 | $text-shadow: adjust-color($base-color, $saturation: 15%, $lightness: -18%); 105 | 106 | @if is-light($base-color) { 107 | $color: hsl(0, 0, 20%); 108 | $text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%); 109 | } 110 | 111 | @if $grayscale == true { 112 | $border: grayscale($border); 113 | $inset-shadow: grayscale($inset-shadow); 114 | $stop-gradient: grayscale($stop-gradient); 115 | $text-shadow: grayscale($text-shadow); 116 | } 117 | 118 | border: 1px solid $border; 119 | border-radius: 3px; 120 | box-shadow: inset 0 1px 0 0 $inset-shadow; 121 | color: $color; 122 | display: inline-block; 123 | font-size: $textsize; 124 | font-weight: bold; 125 | @include linear-gradient ($base-color, $stop-gradient); 126 | padding: $padding; 127 | text-decoration: none; 128 | text-shadow: 0 1px 0 $text-shadow; 129 | background-clip: padding-box; 130 | 131 | &:hover:not(:disabled) { 132 | $base-color-hover: adjust-color($base-color, $saturation: -4%, $lightness: -5%); 133 | $inset-shadow-hover: adjust-color($base-color, $saturation: -7%, $lightness: 5%); 134 | $stop-gradient-hover: adjust-color($base-color, $saturation: 8%, $lightness: -14%); 135 | 136 | @if $grayscale == true { 137 | $base-color-hover: grayscale($base-color-hover); 138 | $inset-shadow-hover: grayscale($inset-shadow-hover); 139 | $stop-gradient-hover: grayscale($stop-gradient-hover); 140 | } 141 | 142 | box-shadow: inset 0 1px 0 0 $inset-shadow-hover; 143 | cursor: pointer; 144 | @include linear-gradient ($base-color-hover, $stop-gradient-hover); 145 | } 146 | 147 | &:active:not(:disabled), 148 | &:focus:not(:disabled) { 149 | $border-active: adjust-color($base-color, $saturation: 9%, $lightness: -14%); 150 | $inset-shadow-active: adjust-color($base-color, $saturation: 7%, $lightness: -17%); 151 | 152 | @if $grayscale == true { 153 | $border-active: grayscale($border-active); 154 | $inset-shadow-active: grayscale($inset-shadow-active); 155 | } 156 | 157 | border: 1px solid $border-active; 158 | box-shadow: inset 0 0 8px 4px $inset-shadow-active, inset 0 0 8px 4px $inset-shadow-active; 159 | } 160 | } 161 | 162 | 163 | // Shiny Button 164 | //************************************************************************// 165 | @mixin shiny($base-color, $grayscale: false, $textsize: inherit, $padding: 7px 18px) { 166 | $color: hsl(0, 0, 100%); 167 | $border: adjust-color($base-color, $red: -117, $green: -111, $blue: -81); 168 | $border-bottom: adjust-color($base-color, $red: -126, $green: -127, $blue: -122); 169 | $fourth-stop: adjust-color($base-color, $red: -79, $green: -70, $blue: -46); 170 | $inset-shadow: adjust-color($base-color, $red: 37, $green: 29, $blue: 12); 171 | $second-stop: adjust-color($base-color, $red: -56, $green: -50, $blue: -33); 172 | $text-shadow: adjust-color($base-color, $red: -140, $green: -141, $blue: -114); 173 | $third-stop: adjust-color($base-color, $red: -86, $green: -75, $blue: -48); 174 | 175 | @if is-light($base-color) { 176 | $color: hsl(0, 0, 20%); 177 | $text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%); 178 | } 179 | 180 | @if $grayscale == true { 181 | $border: grayscale($border); 182 | $border-bottom: grayscale($border-bottom); 183 | $fourth-stop: grayscale($fourth-stop); 184 | $inset-shadow: grayscale($inset-shadow); 185 | $second-stop: grayscale($second-stop); 186 | $text-shadow: grayscale($text-shadow); 187 | $third-stop: grayscale($third-stop); 188 | } 189 | 190 | border: 1px solid $border; 191 | border-bottom: 1px solid $border-bottom; 192 | border-radius: 5px; 193 | box-shadow: inset 0 1px 0 0 $inset-shadow; 194 | color: $color; 195 | display: inline-block; 196 | font-size: $textsize; 197 | font-weight: bold; 198 | @include linear-gradient(top, $base-color 0%, $second-stop 50%, $third-stop 50%, $fourth-stop 100%); 199 | padding: $padding; 200 | text-align: center; 201 | text-decoration: none; 202 | text-shadow: 0 -1px 1px $text-shadow; 203 | 204 | &:hover:not(:disabled) { 205 | $first-stop-hover: adjust-color($base-color, $red: -13, $green: -15, $blue: -18); 206 | $second-stop-hover: adjust-color($base-color, $red: -66, $green: -62, $blue: -51); 207 | $third-stop-hover: adjust-color($base-color, $red: -93, $green: -85, $blue: -66); 208 | $fourth-stop-hover: adjust-color($base-color, $red: -86, $green: -80, $blue: -63); 209 | 210 | @if $grayscale == true { 211 | $first-stop-hover: grayscale($first-stop-hover); 212 | $second-stop-hover: grayscale($second-stop-hover); 213 | $third-stop-hover: grayscale($third-stop-hover); 214 | $fourth-stop-hover: grayscale($fourth-stop-hover); 215 | } 216 | 217 | cursor: pointer; 218 | @include linear-gradient(top, $first-stop-hover 0%, 219 | $second-stop-hover 50%, 220 | $third-stop-hover 50%, 221 | $fourth-stop-hover 100%); 222 | } 223 | 224 | &:active:not(:disabled), 225 | &:focus:not(:disabled) { 226 | $inset-shadow-active: adjust-color($base-color, $red: -111, $green: -116, $blue: -122); 227 | 228 | @if $grayscale == true { 229 | $inset-shadow-active: grayscale($inset-shadow-active); 230 | } 231 | 232 | box-shadow: inset 0 0 20px 0 $inset-shadow-active; 233 | } 234 | } 235 | 236 | 237 | // Pill Button 238 | //************************************************************************// 239 | @mixin pill($base-color, $grayscale: false, $textsize: inherit, $padding: 7px 18px) { 240 | $color: hsl(0, 0, 100%); 241 | $border-bottom: adjust-color($base-color, $hue: 8, $saturation: -11%, $lightness: -26%); 242 | $border-sides: adjust-color($base-color, $hue: 4, $saturation: -21%, $lightness: -21%); 243 | $border-top: adjust-color($base-color, $hue: -1, $saturation: -30%, $lightness: -15%); 244 | $inset-shadow: adjust-color($base-color, $hue: -1, $saturation: -1%, $lightness: 7%); 245 | $stop-gradient: adjust-color($base-color, $hue: 8, $saturation: 14%, $lightness: -10%); 246 | $text-shadow: adjust-color($base-color, $hue: 5, $saturation: -19%, $lightness: -15%); 247 | 248 | @if is-light($base-color) { 249 | $color: hsl(0, 0, 20%); 250 | $text-shadow: adjust-color($base-color, $saturation: 10%, $lightness: 4%); 251 | } 252 | 253 | @if $grayscale == true { 254 | $border-bottom: grayscale($border-bottom); 255 | $border-sides: grayscale($border-sides); 256 | $border-top: grayscale($border-top); 257 | $inset-shadow: grayscale($inset-shadow); 258 | $stop-gradient: grayscale($stop-gradient); 259 | $text-shadow: grayscale($text-shadow); 260 | } 261 | 262 | border: 1px solid $border-top; 263 | border-color: $border-top $border-sides $border-bottom; 264 | border-radius: 16px; 265 | box-shadow: inset 0 1px 0 0 $inset-shadow; 266 | color: $color; 267 | display: inline-block; 268 | font-size: $textsize; 269 | font-weight: normal; 270 | line-height: 1; 271 | @include linear-gradient ($base-color, $stop-gradient); 272 | padding: $padding; 273 | text-align: center; 274 | text-decoration: none; 275 | text-shadow: 0 -1px 1px $text-shadow; 276 | background-clip: padding-box; 277 | 278 | &:hover:not(:disabled) { 279 | $base-color-hover: adjust-color($base-color, $lightness: -4.5%); 280 | $border-bottom: adjust-color($base-color, $hue: 8, $saturation: 13.5%, $lightness: -32%); 281 | $border-sides: adjust-color($base-color, $hue: 4, $saturation: -2%, $lightness: -27%); 282 | $border-top: adjust-color($base-color, $hue: -1, $saturation: -17%, $lightness: -21%); 283 | $inset-shadow-hover: adjust-color($base-color, $saturation: -1%, $lightness: 3%); 284 | $stop-gradient-hover: adjust-color($base-color, $hue: 8, $saturation: -4%, $lightness: -15.5%); 285 | $text-shadow-hover: adjust-color($base-color, $hue: 5, $saturation: -5%, $lightness: -22%); 286 | 287 | @if $grayscale == true { 288 | $base-color-hover: grayscale($base-color-hover); 289 | $border-bottom: grayscale($border-bottom); 290 | $border-sides: grayscale($border-sides); 291 | $border-top: grayscale($border-top); 292 | $inset-shadow-hover: grayscale($inset-shadow-hover); 293 | $stop-gradient-hover: grayscale($stop-gradient-hover); 294 | $text-shadow-hover: grayscale($text-shadow-hover); 295 | } 296 | 297 | border: 1px solid $border-top; 298 | border-color: $border-top $border-sides $border-bottom; 299 | box-shadow: inset 0 1px 0 0 $inset-shadow-hover; 300 | cursor: pointer; 301 | @include linear-gradient ($base-color-hover, $stop-gradient-hover); 302 | text-shadow: 0 -1px 1px $text-shadow-hover; 303 | background-clip: padding-box; 304 | } 305 | 306 | &:active:not(:disabled), 307 | &:focus:not(:disabled) { 308 | $active-color: adjust-color($base-color, $hue: 4, $saturation: -12%, $lightness: -10%); 309 | $border-active: adjust-color($base-color, $hue: 6, $saturation: -2.5%, $lightness: -30%); 310 | $border-bottom-active: adjust-color($base-color, $hue: 11, $saturation: 6%, $lightness: -31%); 311 | $inset-shadow-active: adjust-color($base-color, $hue: 9, $saturation: 2%, $lightness: -21.5%); 312 | $text-shadow-active: adjust-color($base-color, $hue: 5, $saturation: -12%, $lightness: -21.5%); 313 | 314 | @if $grayscale == true { 315 | $active-color: grayscale($active-color); 316 | $border-active: grayscale($border-active); 317 | $border-bottom-active: grayscale($border-bottom-active); 318 | $inset-shadow-active: grayscale($inset-shadow-active); 319 | $text-shadow-active: grayscale($text-shadow-active); 320 | } 321 | 322 | background: $active-color; 323 | border: 1px solid $border-active; 324 | border-bottom: 1px solid $border-bottom-active; 325 | box-shadow: inset 0 0 6px 3px $inset-shadow-active; 326 | text-shadow: 0 -1px 1px $text-shadow-active; 327 | } 328 | } 329 | 330 | 331 | 332 | // Flat Button 333 | //************************************************************************// 334 | @mixin flat($base-color, $grayscale: false, $textsize: inherit, $padding: 7px 18px) { 335 | $color: hsl(0, 0, 100%); 336 | 337 | @if is-light($base-color) { 338 | $color: hsl(0, 0, 20%); 339 | } 340 | 341 | background-color: $base-color; 342 | border-radius: 3px; 343 | border: none; 344 | color: $color; 345 | display: inline-block; 346 | font-size: inherit; 347 | font-weight: bold; 348 | padding: 7px 18px; 349 | text-decoration: none; 350 | background-clip: padding-box; 351 | 352 | &:hover:not(:disabled){ 353 | $base-color-hover: adjust-color($base-color, $saturation: 4%, $lightness: 5%); 354 | 355 | @if $grayscale == true { 356 | $base-color-hover: grayscale($base-color-hover); 357 | } 358 | 359 | background-color: $base-color-hover; 360 | cursor: pointer; 361 | } 362 | 363 | &:active:not(:disabled), 364 | &:focus:not(:disabled) { 365 | $base-color-active: adjust-color($base-color, $saturation: -4%, $lightness: -5%); 366 | 367 | @if $grayscale == true { 368 | $base-color-active: grayscale($base-color-active); 369 | } 370 | 371 | background-color: $base-color-active; 372 | cursor: pointer; 373 | } 374 | } 375 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_clearfix.scss: -------------------------------------------------------------------------------- 1 | // Modern micro clearfix provides an easy way to contain floats without adding additional markup. 2 | // 3 | // Example usage: 4 | // 5 | // // Contain all floats within .wrapper 6 | // .wrapper { 7 | // @include clearfix; 8 | // .content, 9 | // .sidebar { 10 | // float : left; 11 | // } 12 | // } 13 | 14 | @mixin clearfix { 15 | &:after { 16 | content:""; 17 | display:table; 18 | clear:both; 19 | } 20 | } 21 | 22 | // Acknowledgements 23 | // Beat *that* clearfix: [Thierry Koblentz](http://www.css-101.org/articles/clearfix/latest-new-clearfix-so-far.php) 24 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_directional-values.scss: -------------------------------------------------------------------------------- 1 | // directional-property mixins are shorthands 2 | // for writing properties like the following 3 | // 4 | // @include margin(null 0 10px); 5 | // ------ 6 | // margin-right: 0; 7 | // margin-bottom: 10px; 8 | // margin-left: 0; 9 | // 10 | // - or - 11 | // 12 | // @include border-style(dotted null); 13 | // ------ 14 | // border-top-style: dotted; 15 | // border-bottom-style: dotted; 16 | // 17 | // ------ 18 | // 19 | // Note: You can also use false instead of null 20 | 21 | @function collapse-directionals($vals) { 22 | $output: null; 23 | 24 | $A: nth( $vals, 1 ); 25 | $B: if( length($vals) < 2, $A, nth($vals, 2)); 26 | $C: if( length($vals) < 3, $A, nth($vals, 3)); 27 | $D: if( length($vals) < 2, $A, nth($vals, if( length($vals) < 4, 2, 4) )); 28 | 29 | @if $A == 0 { $A: 0 } 30 | @if $B == 0 { $B: 0 } 31 | @if $C == 0 { $C: 0 } 32 | @if $D == 0 { $D: 0 } 33 | 34 | @if $A == $B and $A == $C and $A == $D { $output: $A } 35 | @else if $A == $C and $B == $D { $output: $A $B } 36 | @else if $B == $D { $output: $A $B $C } 37 | @else { $output: $A $B $C $D } 38 | 39 | @return $output; 40 | } 41 | 42 | @function contains-falsy($list) { 43 | @each $item in $list { 44 | @if not $item { 45 | @return true; 46 | } 47 | } 48 | 49 | @return false; 50 | } 51 | 52 | @mixin directional-property($pre, $suf, $vals) { 53 | // Property Names 54 | $top: $pre + "-top" + if($suf, "-#{$suf}", ""); 55 | $bottom: $pre + "-bottom" + if($suf, "-#{$suf}", ""); 56 | $left: $pre + "-left" + if($suf, "-#{$suf}", ""); 57 | $right: $pre + "-right" + if($suf, "-#{$suf}", ""); 58 | $all: $pre + if($suf, "-#{$suf}", ""); 59 | 60 | $vals: collapse-directionals($vals); 61 | 62 | @if contains-falsy($vals) { 63 | @if nth($vals, 1) { #{$top}: nth($vals, 1); } 64 | 65 | @if length($vals) == 1 { 66 | @if nth($vals, 1) { #{$right}: nth($vals, 1); } 67 | } @else { 68 | @if nth($vals, 2) { #{$right}: nth($vals, 2); } 69 | } 70 | 71 | // prop: top/bottom right/left 72 | @if length($vals) == 2 { 73 | @if nth($vals, 1) { #{$bottom}: nth($vals, 1); } 74 | @if nth($vals, 2) { #{$left}: nth($vals, 2); } 75 | 76 | // prop: top right/left bottom 77 | } @else if length($vals) == 3 { 78 | @if nth($vals, 3) { #{$bottom}: nth($vals, 3); } 79 | @if nth($vals, 2) { #{$left}: nth($vals, 2); } 80 | 81 | // prop: top right bottom left 82 | } @else if length($vals) == 4 { 83 | @if nth($vals, 3) { #{$bottom}: nth($vals, 3); } 84 | @if nth($vals, 4) { #{$left}: nth($vals, 4); } 85 | } 86 | 87 | // prop: top/right/bottom/left 88 | } @else { 89 | #{$all}: $vals; 90 | } 91 | } 92 | 93 | @mixin margin($vals...) { 94 | @include directional-property(margin, false, $vals...); 95 | } 96 | 97 | @mixin padding($vals...) { 98 | @include directional-property(padding, false, $vals...); 99 | } 100 | 101 | @mixin border-style($vals...) { 102 | @include directional-property(border, style, $vals...); 103 | } 104 | 105 | @mixin border-color($vals...) { 106 | @include directional-property(border, color, $vals...); 107 | } 108 | 109 | @mixin border-width($vals...) { 110 | @include directional-property(border, width, $vals...); 111 | } 112 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_ellipsis.scss: -------------------------------------------------------------------------------- 1 | @mixin ellipsis($width: 100%) { 2 | display: inline-block; 3 | max-width: $width; 4 | overflow: hidden; 5 | text-overflow: ellipsis; 6 | white-space: nowrap; 7 | } 8 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_font-family.scss: -------------------------------------------------------------------------------- 1 | $georgia: Georgia, Cambria, "Times New Roman", Times, serif; 2 | $helvetica: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; 3 | $lucida-grande: "Lucida Grande", Tahoma, Verdana, Arial, sans-serif; 4 | $monospace: "Bitstream Vera Sans Mono", Consolas, Courier, monospace; 5 | $verdana: Verdana, Geneva, sans-serif; 6 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_hide-text.scss: -------------------------------------------------------------------------------- 1 | @mixin hide-text { 2 | overflow: hidden; 3 | 4 | &:before { 5 | content: ""; 6 | display: block; 7 | width: 0; 8 | height: 100%; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_html5-input-types.scss: -------------------------------------------------------------------------------- 1 | //************************************************************************// 2 | // Generate a variable ($all-text-inputs) with a list of all html5 3 | // input types that have a text-based input, excluding textarea. 4 | // http://diveintohtml5.org/forms.html 5 | //************************************************************************// 6 | $inputs-list: 'input[type="email"]', 7 | 'input[type="number"]', 8 | 'input[type="password"]', 9 | 'input[type="search"]', 10 | 'input[type="tel"]', 11 | 'input[type="text"]', 12 | 'input[type="url"]', 13 | 14 | // Webkit & Gecko may change the display of these in the future 15 | 'input[type="color"]', 16 | 'input[type="date"]', 17 | 'input[type="datetime"]', 18 | 'input[type="datetime-local"]', 19 | 'input[type="month"]', 20 | 'input[type="time"]', 21 | 'input[type="week"]'; 22 | 23 | $unquoted-inputs-list: (); 24 | @each $input-type in $inputs-list { 25 | $unquoted-inputs-list: append($unquoted-inputs-list, unquote($input-type), comma); 26 | } 27 | 28 | $all-text-inputs: $unquoted-inputs-list; 29 | 30 | 31 | // Hover Pseudo-class 32 | //************************************************************************// 33 | $all-text-inputs-hover: (); 34 | @each $input-type in $unquoted-inputs-list { 35 | $input-type-hover: $input-type + ":hover"; 36 | $all-text-inputs-hover: append($all-text-inputs-hover, $input-type-hover, comma); 37 | } 38 | 39 | // Focus Pseudo-class 40 | //************************************************************************// 41 | $all-text-inputs-focus: (); 42 | @each $input-type in $unquoted-inputs-list { 43 | $input-type-focus: $input-type + ":focus"; 44 | $all-text-inputs-focus: append($all-text-inputs-focus, $input-type-focus, comma); 45 | } 46 | 47 | // You must use interpolation on the variable: 48 | // #{$all-text-inputs} 49 | // #{$all-text-inputs-hover} 50 | // #{$all-text-inputs-focus} 51 | 52 | // Example 53 | //************************************************************************// 54 | // #{$all-text-inputs}, textarea { 55 | // border: 1px solid red; 56 | // } 57 | 58 | 59 | 60 | //************************************************************************// 61 | // Generate a variable ($all-button-inputs) with a list of all html5 62 | // input types that have a button-based input, excluding button. 63 | //************************************************************************// 64 | $inputs-button-list: 'input[type="button"]', 65 | 'input[type="reset"]', 66 | 'input[type="submit"]'; 67 | 68 | $unquoted-inputs-button-list: (); 69 | @each $input-type in $inputs-button-list { 70 | $unquoted-inputs-button-list: append($unquoted-inputs-button-list, unquote($input-type), comma); 71 | } 72 | 73 | $all-button-inputs: $unquoted-inputs-button-list; 74 | 75 | 76 | // Hover Pseudo-class 77 | //************************************************************************// 78 | $all-button-inputs-hover: (); 79 | @each $input-type in $unquoted-inputs-button-list { 80 | $input-type-hover: $input-type + ":hover"; 81 | $all-button-inputs-hover: append($all-button-inputs-hover, $input-type-hover, comma); 82 | } 83 | 84 | // Focus Pseudo-class 85 | //************************************************************************// 86 | $all-button-inputs-focus: (); 87 | @each $input-type in $unquoted-inputs-button-list { 88 | $input-type-focus: $input-type + ":focus"; 89 | $all-button-inputs-focus: append($all-button-inputs-focus, $input-type-focus, comma); 90 | } 91 | 92 | // Active Pseudo-class 93 | //************************************************************************// 94 | $all-button-inputs-active: (); 95 | @each $input-type in $unquoted-inputs-button-list { 96 | $input-type-active: $input-type + ":active"; 97 | $all-button-inputs-active: append($all-button-inputs-active, $input-type-active, comma); 98 | } 99 | 100 | // You must use interpolation on the variable: 101 | // #{$all-button-inputs} 102 | // #{$all-button-inputs-hover} 103 | // #{$all-button-inputs-focus} 104 | // #{$all-button-inputs-active} 105 | 106 | // Example 107 | //************************************************************************// 108 | // #{$all-button-inputs}, button { 109 | // border: 1px solid red; 110 | // } 111 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_position.scss: -------------------------------------------------------------------------------- 1 | @mixin position ($position: relative, $coordinates: 0 0 0 0) { 2 | 3 | @if type-of($position) == list { 4 | $coordinates: $position; 5 | $position: relative; 6 | } 7 | 8 | $coordinates: unpack($coordinates); 9 | 10 | $top: nth($coordinates, 1); 11 | $right: nth($coordinates, 2); 12 | $bottom: nth($coordinates, 3); 13 | $left: nth($coordinates, 4); 14 | 15 | position: $position; 16 | 17 | @if ($top and $top == auto) or (type-of($top) == number and not(unitless($top))) { 18 | top: $top; 19 | } 20 | 21 | @if ($right and $right == auto) or (type-of($right) == number and not(unitless($right))) { 22 | right: $right; 23 | } 24 | 25 | @if ($bottom and $bottom == auto) or (type-of($bottom) == number and not(unitless($bottom))) { 26 | bottom: $bottom; 27 | } 28 | 29 | @if ($left and $left == auto) or (type-of($left) == number and not(unitless($left))) { 30 | left: $left; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_prefixer.scss: -------------------------------------------------------------------------------- 1 | //************************************************************************// 2 | // Example: @include prefixer(border-radius, $radii, webkit ms spec); 3 | //************************************************************************// 4 | // Variables located in /settings/_prefixer.scss 5 | 6 | @mixin prefixer ($property, $value, $prefixes) { 7 | @each $prefix in $prefixes { 8 | @if $prefix == webkit { 9 | @if $prefix-for-webkit { 10 | -webkit-#{$property}: $value; 11 | } 12 | } 13 | @else if $prefix == moz { 14 | @if $prefix-for-mozilla { 15 | -moz-#{$property}: $value; 16 | } 17 | } 18 | @else if $prefix == ms { 19 | @if $prefix-for-microsoft { 20 | -ms-#{$property}: $value; 21 | } 22 | } 23 | @else if $prefix == o { 24 | @if $prefix-for-opera { 25 | -o-#{$property}: $value; 26 | } 27 | } 28 | @else if $prefix == spec { 29 | @if $prefix-for-spec { 30 | #{$property}: $value; 31 | } 32 | } 33 | @else { 34 | @warn "Unrecognized prefix: #{$prefix}"; 35 | } 36 | } 37 | } 38 | 39 | @mixin disable-prefix-for-all() { 40 | $prefix-for-webkit: false; 41 | $prefix-for-mozilla: false; 42 | $prefix-for-microsoft: false; 43 | $prefix-for-opera: false; 44 | $prefix-for-spec: false; 45 | } 46 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_retina-image.scss: -------------------------------------------------------------------------------- 1 | @mixin retina-image($filename, $background-size, $extension: png, $retina-filename: null, $retina-suffix: _2x, $asset-pipeline: $asset-pipeline) { 2 | @if $asset-pipeline { 3 | background-image: image-url("#{$filename}.#{$extension}"); 4 | } 5 | @else { 6 | background-image: url("#{$filename}.#{$extension}"); 7 | } 8 | 9 | @include hidpi { 10 | @if $asset-pipeline { 11 | @if $retina-filename { 12 | background-image: image-url("#{$retina-filename}.#{$extension}"); 13 | } 14 | @else { 15 | background-image: image-url("#{$filename}#{$retina-suffix}.#{$extension}"); 16 | } 17 | } 18 | 19 | @else { 20 | @if $retina-filename { 21 | background-image: url("#{$retina-filename}.#{$extension}"); 22 | } 23 | @else { 24 | background-image: url("#{$filename}#{$retina-suffix}.#{$extension}"); 25 | } 26 | } 27 | 28 | background-size: $background-size; 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_size.scss: -------------------------------------------------------------------------------- 1 | @mixin size($size) { 2 | @if length($size) == 1 { 3 | @if $size == auto { 4 | width: $size; 5 | height: $size; 6 | } 7 | 8 | @else if unitless($size) { 9 | width: $size + px; 10 | height: $size + px; 11 | } 12 | 13 | @else if not(unitless($size)) { 14 | width: $size; 15 | height: $size; 16 | } 17 | } 18 | 19 | // Width x Height 20 | @if length($size) == 2 { 21 | $width: nth($size, 1); 22 | $height: nth($size, 2); 23 | 24 | @if $width == auto { 25 | width: $width; 26 | } 27 | @else if not(unitless($width)) { 28 | width: $width; 29 | } 30 | @else if unitless($width) { 31 | width: $width + px; 32 | } 33 | 34 | @if $height == auto { 35 | height: $height; 36 | } 37 | @else if not(unitless($height)) { 38 | height: $height; 39 | } 40 | @else if unitless($height) { 41 | height: $height + px; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_timing-functions.scss: -------------------------------------------------------------------------------- 1 | // CSS cubic-bezier timing functions. Timing functions courtesy of jquery.easie (github.com/jaukia/easie) 2 | // Timing functions are the same as demo'ed here: http://jqueryui.com/resources/demos/effect/easing.html 3 | 4 | // EASE IN 5 | $ease-in-quad: cubic-bezier(0.550, 0.085, 0.680, 0.530); 6 | $ease-in-cubic: cubic-bezier(0.550, 0.055, 0.675, 0.190); 7 | $ease-in-quart: cubic-bezier(0.895, 0.030, 0.685, 0.220); 8 | $ease-in-quint: cubic-bezier(0.755, 0.050, 0.855, 0.060); 9 | $ease-in-sine: cubic-bezier(0.470, 0.000, 0.745, 0.715); 10 | $ease-in-expo: cubic-bezier(0.950, 0.050, 0.795, 0.035); 11 | $ease-in-circ: cubic-bezier(0.600, 0.040, 0.980, 0.335); 12 | $ease-in-back: cubic-bezier(0.600, -0.280, 0.735, 0.045); 13 | 14 | // EASE OUT 15 | $ease-out-quad: cubic-bezier(0.250, 0.460, 0.450, 0.940); 16 | $ease-out-cubic: cubic-bezier(0.215, 0.610, 0.355, 1.000); 17 | $ease-out-quart: cubic-bezier(0.165, 0.840, 0.440, 1.000); 18 | $ease-out-quint: cubic-bezier(0.230, 1.000, 0.320, 1.000); 19 | $ease-out-sine: cubic-bezier(0.390, 0.575, 0.565, 1.000); 20 | $ease-out-expo: cubic-bezier(0.190, 1.000, 0.220, 1.000); 21 | $ease-out-circ: cubic-bezier(0.075, 0.820, 0.165, 1.000); 22 | $ease-out-back: cubic-bezier(0.175, 0.885, 0.320, 1.275); 23 | 24 | // EASE IN OUT 25 | $ease-in-out-quad: cubic-bezier(0.455, 0.030, 0.515, 0.955); 26 | $ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1.000); 27 | $ease-in-out-quart: cubic-bezier(0.770, 0.000, 0.175, 1.000); 28 | $ease-in-out-quint: cubic-bezier(0.860, 0.000, 0.070, 1.000); 29 | $ease-in-out-sine: cubic-bezier(0.445, 0.050, 0.550, 0.950); 30 | $ease-in-out-expo: cubic-bezier(1.000, 0.000, 0.000, 1.000); 31 | $ease-in-out-circ: cubic-bezier(0.785, 0.135, 0.150, 0.860); 32 | $ease-in-out-back: cubic-bezier(0.680, -0.550, 0.265, 1.550); 33 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_triangle.scss: -------------------------------------------------------------------------------- 1 | @mixin triangle ($size, $color, $direction) { 2 | height: 0; 3 | width: 0; 4 | 5 | $width: nth($size, 1); 6 | $height: nth($size, length($size)); 7 | 8 | $foreground-color: nth($color, 1); 9 | $background-color: transparent !default; 10 | @if (length($color) == 2) { 11 | $background-color: nth($color, 2); 12 | } 13 | 14 | @if ($direction == up) or ($direction == down) or ($direction == right) or ($direction == left) { 15 | 16 | $width: $width / 2; 17 | $height: if(length($size) > 1, $height, $height/2); 18 | 19 | @if $direction == up { 20 | border-left: $width solid $background-color; 21 | border-right: $width solid $background-color; 22 | border-bottom: $height solid $foreground-color; 23 | 24 | } @else if $direction == right { 25 | border-top: $width solid $background-color; 26 | border-bottom: $width solid $background-color; 27 | border-left: $height solid $foreground-color; 28 | 29 | } @else if $direction == down { 30 | border-left: $width solid $background-color; 31 | border-right: $width solid $background-color; 32 | border-top: $height solid $foreground-color; 33 | 34 | } @else if $direction == left { 35 | border-top: $width solid $background-color; 36 | border-bottom: $width solid $background-color; 37 | border-right: $height solid $foreground-color; 38 | } 39 | } 40 | 41 | @else if ($direction == up-right) or ($direction == up-left) { 42 | border-top: $height solid $foreground-color; 43 | 44 | @if $direction == up-right { 45 | border-left: $width solid $background-color; 46 | 47 | } @else if $direction == up-left { 48 | border-right: $width solid $background-color; 49 | } 50 | } 51 | 52 | @else if ($direction == down-right) or ($direction == down-left) { 53 | border-bottom: $height solid $foreground-color; 54 | 55 | @if $direction == down-right { 56 | border-left: $width solid $background-color; 57 | 58 | } @else if $direction == down-left { 59 | border-right: $width solid $background-color; 60 | } 61 | } 62 | 63 | @else if ($direction == inset-up) { 64 | border-width: $height $width; 65 | border-style: solid; 66 | border-color: $background-color $background-color $foreground-color; 67 | } 68 | 69 | @else if ($direction == inset-down) { 70 | border-width: $height $width; 71 | border-style: solid; 72 | border-color: $foreground-color $background-color $background-color; 73 | } 74 | 75 | @else if ($direction == inset-right) { 76 | border-width: $width $height; 77 | border-style: solid; 78 | border-color: $background-color $background-color $background-color $foreground-color; 79 | } 80 | 81 | @else if ($direction == inset-left) { 82 | border-width: $width $height; 83 | border-style: solid; 84 | border-color: $background-color $foreground-color $background-color $background-color; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/addons/_word-wrap.scss: -------------------------------------------------------------------------------- 1 | @mixin word-wrap($wrap: break-word) { 2 | word-wrap: $wrap; 3 | 4 | @if $wrap == break-word { 5 | overflow-wrap: break-word; 6 | word-break: break-all; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_animation.scss: -------------------------------------------------------------------------------- 1 | // http://www.w3.org/TR/css3-animations/#the-animation-name-property- 2 | // Each of these mixins support comma separated lists of values, which allows different transitions for individual properties to be described in a single style rule. Each value in the list corresponds to the value at that same position in the other properties. 3 | 4 | // Official animation shorthand property. 5 | @mixin animation ($animations...) { 6 | @include prefixer(animation, $animations, webkit moz spec); 7 | } 8 | 9 | // Individual Animation Properties 10 | @mixin animation-name ($names...) { 11 | @include prefixer(animation-name, $names, webkit moz spec); 12 | } 13 | 14 | 15 | @mixin animation-duration ($times...) { 16 | @include prefixer(animation-duration, $times, webkit moz spec); 17 | } 18 | 19 | 20 | @mixin animation-timing-function ($motions...) { 21 | // ease | linear | ease-in | ease-out | ease-in-out 22 | @include prefixer(animation-timing-function, $motions, webkit moz spec); 23 | } 24 | 25 | 26 | @mixin animation-iteration-count ($values...) { 27 | // infinite | 28 | @include prefixer(animation-iteration-count, $values, webkit moz spec); 29 | } 30 | 31 | 32 | @mixin animation-direction ($directions...) { 33 | // normal | alternate 34 | @include prefixer(animation-direction, $directions, webkit moz spec); 35 | } 36 | 37 | 38 | @mixin animation-play-state ($states...) { 39 | // running | paused 40 | @include prefixer(animation-play-state, $states, webkit moz spec); 41 | } 42 | 43 | 44 | @mixin animation-delay ($times...) { 45 | @include prefixer(animation-delay, $times, webkit moz spec); 46 | } 47 | 48 | 49 | @mixin animation-fill-mode ($modes...) { 50 | // none | forwards | backwards | both 51 | @include prefixer(animation-fill-mode, $modes, webkit moz spec); 52 | } 53 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_appearance.scss: -------------------------------------------------------------------------------- 1 | @mixin appearance ($value) { 2 | @include prefixer(appearance, $value, webkit moz ms o spec); 3 | } 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_backface-visibility.scss: -------------------------------------------------------------------------------- 1 | //************************************************************************// 2 | // Backface-visibility mixin 3 | //************************************************************************// 4 | @mixin backface-visibility($visibility) { 5 | @include prefixer(backface-visibility, $visibility, webkit spec); 6 | } 7 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_background-image.scss: -------------------------------------------------------------------------------- 1 | //************************************************************************// 2 | // Background-image property for adding multiple background images with 3 | // gradients, or for stringing multiple gradients together. 4 | //************************************************************************// 5 | 6 | @mixin background-image($images...) { 7 | background-image: _add-prefix($images, webkit); 8 | background-image: _add-prefix($images); 9 | } 10 | 11 | @function _add-prefix($images, $vendor: false) { 12 | $images-prefixed: (); 13 | $gradient-positions: false; 14 | @for $i from 1 through length($images) { 15 | $type: type-of(nth($images, $i)); // Get type of variable - List or String 16 | 17 | // If variable is a list - Gradient 18 | @if $type == list { 19 | $gradient-type: nth(nth($images, $i), 1); // linear or radial 20 | $gradient-pos: null; 21 | $gradient-args: null; 22 | 23 | @if ($gradient-type == linear) or ($gradient-type == radial) { 24 | $gradient-pos: nth(nth($images, $i), 2); // Get gradient position 25 | $gradient-args: nth(nth($images, $i), 3); // Get actual gradient (red, blue) 26 | } 27 | @else { 28 | $gradient-args: nth(nth($images, $i), 2); // Get actual gradient (red, blue) 29 | } 30 | 31 | $gradient-positions: _gradient-positions-parser($gradient-type, $gradient-pos); 32 | $gradient: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor); 33 | $images-prefixed: append($images-prefixed, $gradient, comma); 34 | } 35 | // If variable is a string - Image 36 | @else if $type == string { 37 | $images-prefixed: join($images-prefixed, nth($images, $i), comma); 38 | } 39 | } 40 | @return $images-prefixed; 41 | } 42 | 43 | //Examples: 44 | //@include background-image(linear-gradient(top, orange, red)); 45 | //@include background-image(radial-gradient(50% 50%, cover circle, orange, red)); 46 | //@include background-image(url("/images/a.png"), linear-gradient(orange, red)); 47 | //@include background-image(url("image.png"), linear-gradient(orange, red), url("image.png")); 48 | //@include background-image(linear-gradient(hsla(0, 100%, 100%, 0.25) 0%, hsla(0, 100%, 100%, 0.08) 50%, transparent 50%), linear-gradient(orange, red)); 49 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_background.scss: -------------------------------------------------------------------------------- 1 | //************************************************************************// 2 | // Background property for adding multiple backgrounds using shorthand 3 | // notation. 4 | //************************************************************************// 5 | 6 | @mixin background( 7 | $background-1 , $background-2: null, 8 | $background-3: null, $background-4: null, 9 | $background-5: null, $background-6: null, 10 | $background-7: null, $background-8: null, 11 | $background-9: null, $background-10: null, 12 | $fallback: null 13 | ) { 14 | $backgrounds: $background-1, $background-2, 15 | $background-3, $background-4, 16 | $background-5, $background-6, 17 | $background-7, $background-8, 18 | $background-9, $background-10; 19 | 20 | $fallback-color: false; 21 | @if (type-of($fallback) == color) or ($fallback == "transparent") { 22 | $fallback-color: $fallback; 23 | } 24 | @else { 25 | $fallback-color: _extract-background-color($backgrounds); 26 | } 27 | 28 | @if $fallback-color { 29 | background-color: $fallback-color; 30 | } 31 | background: _background-add-prefix($backgrounds, webkit); 32 | background: _background-add-prefix($backgrounds); 33 | } 34 | 35 | @function _extract-background-color($backgrounds) { 36 | $final-bg-layer: nth($backgrounds, length($backgrounds)); 37 | @if type-of($final-bg-layer) == list { 38 | @for $i from 1 through length($final-bg-layer) { 39 | $value: nth($final-bg-layer, $i); 40 | @if type-of($value) == color { 41 | @return $value; 42 | } 43 | } 44 | } 45 | @return false; 46 | } 47 | 48 | @function _background-add-prefix($backgrounds, $vendor: false) { 49 | $backgrounds-prefixed: (); 50 | 51 | @for $i from 1 through length($backgrounds) { 52 | $shorthand: nth($backgrounds, $i); // Get member for current index 53 | $type: type-of($shorthand); // Get type of variable - List (gradient) or String (image) 54 | 55 | // If shorthand is a list (gradient) 56 | @if $type == list { 57 | $first-member: nth($shorthand, 1); // Get first member of shorthand 58 | 59 | // Linear Gradient 60 | @if index(linear radial, nth($first-member, 1)) { 61 | $gradient-type: nth($first-member, 1); // linear || radial 62 | $gradient-args: false; 63 | $gradient-positions: false; 64 | $shorthand-start: false; 65 | @if type-of($first-member) == list { // Linear gradient plus additional shorthand values - lg(red,orange)repeat,... 66 | $gradient-positions: nth($first-member, 2); 67 | $gradient-args: nth($first-member, 3); 68 | $shorthand-start: 2; 69 | } 70 | @else { // Linear gradient only - lg(red,orange),... 71 | $gradient-positions: nth($shorthand, 2); 72 | $gradient-args: nth($shorthand, 3); // Get gradient (red, blue) 73 | } 74 | 75 | $gradient-positions: _gradient-positions-parser($gradient-type, $gradient-positions); 76 | $gradient: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor); 77 | 78 | // Append any additional shorthand args to gradient 79 | @if $shorthand-start { 80 | @for $j from $shorthand-start through length($shorthand) { 81 | $gradient: join($gradient, nth($shorthand, $j), space); 82 | } 83 | } 84 | $backgrounds-prefixed: append($backgrounds-prefixed, $gradient, comma); 85 | } 86 | // Image with additional properties 87 | @else { 88 | $backgrounds-prefixed: append($backgrounds-prefixed, $shorthand, comma); 89 | } 90 | } 91 | // If shorthand is a simple string (color or image) 92 | @else if $type == string { 93 | $backgrounds-prefixed: join($backgrounds-prefixed, $shorthand, comma); 94 | } 95 | } 96 | @return $backgrounds-prefixed; 97 | } 98 | 99 | //Examples: 100 | //@include background(linear-gradient(top, orange, red)); 101 | //@include background(radial-gradient(circle at 40% 40%, orange, red)); 102 | //@include background(url("/images/a.png") no-repeat, linear-gradient(orange, red)); 103 | //@include background(url("image.png") center center, linear-gradient(orange, red), url("image.png")); 104 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_border-image.scss: -------------------------------------------------------------------------------- 1 | @mixin border-image($images) { 2 | -webkit-border-image: _border-add-prefix($images, webkit); 3 | -moz-border-image: _border-add-prefix($images, moz); 4 | -o-border-image: _border-add-prefix($images, o); 5 | border-image: _border-add-prefix($images); 6 | border-style: solid; 7 | } 8 | 9 | @function _border-add-prefix($images, $vendor: false) { 10 | $border-image: null; 11 | $images-type: type-of(nth($images, 1)); 12 | $first-var: nth(nth($images, 1), 1); // Get type of Gradient (Linear || radial) 13 | 14 | // If input is a gradient 15 | @if $images-type == string { 16 | @if ($first-var == "linear") or ($first-var == "radial") { 17 | $gradient-type: nth($images, 1); // Get type of gradient (linear || radial) 18 | $gradient-pos: nth($images, 2); // Get gradient position 19 | $gradient-args: nth($images, 3); // Get actual gradient (red, blue) 20 | $gradient-positions: _gradient-positions-parser($gradient-type, $gradient-pos); 21 | $border-image: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor); 22 | } 23 | // If input is a URL 24 | @else { 25 | $border-image: $images; 26 | } 27 | } 28 | // If input is gradient or url + additional args 29 | @else if $images-type == list { 30 | $type: type-of(nth($images, 1)); // Get type of variable - List or String 31 | 32 | // If variable is a list - Gradient 33 | @if $type == list { 34 | $gradient: nth($images, 1); 35 | $gradient-type: nth($gradient, 1); // Get type of gradient (linear || radial) 36 | $gradient-pos: nth($gradient, 2); // Get gradient position 37 | $gradient-args: nth($gradient, 3); // Get actual gradient (red, blue) 38 | $gradient-positions: _gradient-positions-parser($gradient-type, $gradient-pos); 39 | $border-image: _render-gradients($gradient-positions, $gradient-args, $gradient-type, $vendor); 40 | 41 | @for $i from 2 through length($images) { 42 | $border-image: append($border-image, nth($images, $i)); 43 | } 44 | } 45 | } 46 | @return $border-image; 47 | } 48 | 49 | //Examples: 50 | // @include border-image(url("image.png")); 51 | // @include border-image(url("image.png") 20 stretch); 52 | // @include border-image(linear-gradient(45deg, orange, yellow)); 53 | // @include border-image(linear-gradient(45deg, orange, yellow) stretch); 54 | // @include border-image(linear-gradient(45deg, orange, yellow) 20 30 40 50 stretch round); 55 | // @include border-image(radial-gradient(top, cover, orange, yellow, orange)); 56 | 57 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_border-radius.scss: -------------------------------------------------------------------------------- 1 | //************************************************************************// 2 | // Shorthand Border-radius mixins 3 | //************************************************************************// 4 | @mixin border-top-radius($radii) { 5 | @include prefixer(border-top-left-radius, $radii, spec); 6 | @include prefixer(border-top-right-radius, $radii, spec); 7 | } 8 | 9 | @mixin border-bottom-radius($radii) { 10 | @include prefixer(border-bottom-left-radius, $radii, spec); 11 | @include prefixer(border-bottom-right-radius, $radii, spec); 12 | } 13 | 14 | @mixin border-left-radius($radii) { 15 | @include prefixer(border-top-left-radius, $radii, spec); 16 | @include prefixer(border-bottom-left-radius, $radii, spec); 17 | } 18 | 19 | @mixin border-right-radius($radii) { 20 | @include prefixer(border-top-right-radius, $radii, spec); 21 | @include prefixer(border-bottom-right-radius, $radii, spec); 22 | } 23 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_box-sizing.scss: -------------------------------------------------------------------------------- 1 | @mixin box-sizing ($box) { 2 | // content-box | border-box | inherit 3 | @include prefixer(box-sizing, $box, webkit moz spec); 4 | } 5 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_calc.scss: -------------------------------------------------------------------------------- 1 | @mixin calc($property, $value) { 2 | #{$property}: -webkit-calc(#{$value}); 3 | #{$property}: calc(#{$value}); 4 | } 5 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_columns.scss: -------------------------------------------------------------------------------- 1 | @mixin columns($arg: auto) { 2 | // || 3 | @include prefixer(columns, $arg, webkit moz spec); 4 | } 5 | 6 | @mixin column-count($int: auto) { 7 | // auto || integer 8 | @include prefixer(column-count, $int, webkit moz spec); 9 | } 10 | 11 | @mixin column-gap($length: normal) { 12 | // normal || length 13 | @include prefixer(column-gap, $length, webkit moz spec); 14 | } 15 | 16 | @mixin column-fill($arg: auto) { 17 | // auto || length 18 | @include prefixer(column-fill, $arg, webkit moz spec); 19 | } 20 | 21 | @mixin column-rule($arg) { 22 | // || || 23 | @include prefixer(column-rule, $arg, webkit moz spec); 24 | } 25 | 26 | @mixin column-rule-color($color) { 27 | @include prefixer(column-rule-color, $color, webkit moz spec); 28 | } 29 | 30 | @mixin column-rule-style($style: none) { 31 | // none | hidden | dashed | dotted | double | groove | inset | inset | outset | ridge | solid 32 | @include prefixer(column-rule-style, $style, webkit moz spec); 33 | } 34 | 35 | @mixin column-rule-width ($width: none) { 36 | @include prefixer(column-rule-width, $width, webkit moz spec); 37 | } 38 | 39 | @mixin column-span($arg: none) { 40 | // none || all 41 | @include prefixer(column-span, $arg, webkit moz spec); 42 | } 43 | 44 | @mixin column-width($length: auto) { 45 | // auto || length 46 | @include prefixer(column-width, $length, webkit moz spec); 47 | } 48 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_filter.scss: -------------------------------------------------------------------------------- 1 | @mixin filter($function: none) { 2 | // [ 3 | @include prefixer(perspective, $depth, webkit moz spec); 4 | } 5 | 6 | @mixin perspective-origin($value: 50% 50%) { 7 | @include prefixer(perspective-origin, $value, webkit moz spec); 8 | } 9 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_placeholder.scss: -------------------------------------------------------------------------------- 1 | @mixin placeholder { 2 | $placeholders: ":-webkit-input" ":-moz" "-moz" "-ms-input"; 3 | @each $placeholder in $placeholders { 4 | &:#{$placeholder}-placeholder { 5 | @content; 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_radial-gradient.scss: -------------------------------------------------------------------------------- 1 | // Requires Sass 3.1+ 2 | @mixin radial-gradient($G1, $G2, 3 | $G3: null, $G4: null, 4 | $G5: null, $G6: null, 5 | $G7: null, $G8: null, 6 | $G9: null, $G10: null, 7 | $pos: null, 8 | $shape-size: null, 9 | $fallback: null) { 10 | 11 | $data: _radial-arg-parser($G1, $G2, $pos, $shape-size); 12 | $G1: nth($data, 1); 13 | $G2: nth($data, 2); 14 | $pos: nth($data, 3); 15 | $shape-size: nth($data, 4); 16 | 17 | $full: $G1, $G2, $G3, $G4, $G5, $G6, $G7, $G8, $G9, $G10; 18 | 19 | // Strip deprecated cover/contain for spec 20 | $shape-size-spec: _shape-size-stripper($shape-size); 21 | 22 | // Set $G1 as the default fallback color 23 | $first-color: nth($full, 1); 24 | $fallback-color: nth($first-color, 1); 25 | 26 | @if (type-of($fallback) == color) or ($fallback == "transparent") { 27 | $fallback-color: $fallback; 28 | } 29 | 30 | // Add Commas and spaces 31 | $shape-size: if($shape-size, '#{$shape-size}, ', null); 32 | $pos: if($pos, '#{$pos}, ', null); 33 | $pos-spec: if($pos, 'at #{$pos}', null); 34 | $shape-size-spec: if(($shape-size-spec != ' ') and ($pos == null), '#{$shape-size-spec}, ', '#{$shape-size-spec} '); 35 | 36 | background-color: $fallback-color; 37 | background-image: -webkit-radial-gradient(unquote(#{$pos}#{$shape-size}#{$full})); 38 | background-image: unquote("radial-gradient(#{$shape-size-spec}#{$pos-spec}#{$full})"); 39 | } 40 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_transform.scss: -------------------------------------------------------------------------------- 1 | @mixin transform($property: none) { 2 | // none | 3 | @include prefixer(transform, $property, webkit moz ms o spec); 4 | } 5 | 6 | @mixin transform-origin($axes: 50%) { 7 | // x-axis - left | center | right | length | % 8 | // y-axis - top | center | bottom | length | % 9 | // z-axis - length 10 | @include prefixer(transform-origin, $axes, webkit moz ms o spec); 11 | } 12 | 13 | @mixin transform-style ($style: flat) { 14 | @include prefixer(transform-style, $style, webkit moz ms o spec); 15 | } 16 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_transition.scss: -------------------------------------------------------------------------------- 1 | // Shorthand mixin. Supports multiple parentheses-deliminated values for each variable. 2 | // Example: @include transition (all 2s ease-in-out); 3 | // @include transition (opacity 1s ease-in 2s, width 2s ease-out); 4 | // @include transition-property (transform, opacity); 5 | 6 | @mixin transition ($properties...) { 7 | // Fix for vendor-prefix transform property 8 | $needs-prefixes: false; 9 | $webkit: (); 10 | $moz: (); 11 | $spec: (); 12 | 13 | // Create lists for vendor-prefixed transform 14 | @each $list in $properties { 15 | @if nth($list, 1) == "transform" { 16 | $needs-prefixes: true; 17 | $list1: -webkit-transform; 18 | $list2: -moz-transform; 19 | $list3: (); 20 | 21 | @each $var in $list { 22 | $list3: join($list3, $var); 23 | 24 | @if $var != "transform" { 25 | $list1: join($list1, $var); 26 | $list2: join($list2, $var); 27 | } 28 | } 29 | 30 | $webkit: append($webkit, $list1); 31 | $moz: append($moz, $list2); 32 | $spec: append($spec, $list3); 33 | } 34 | 35 | // Create lists for non-prefixed transition properties 36 | @else { 37 | $webkit: append($webkit, $list, comma); 38 | $moz: append($moz, $list, comma); 39 | $spec: append($spec, $list, comma); 40 | } 41 | } 42 | 43 | @if $needs-prefixes { 44 | -webkit-transition: $webkit; 45 | -moz-transition: $moz; 46 | transition: $spec; 47 | } 48 | @else { 49 | @if length($properties) >= 1 { 50 | @include prefixer(transition, $properties, webkit moz spec); 51 | } 52 | 53 | @else { 54 | $properties: all 0.15s ease-out 0s; 55 | @include prefixer(transition, $properties, webkit moz spec); 56 | } 57 | } 58 | } 59 | 60 | @mixin transition-property ($properties...) { 61 | -webkit-transition-property: transition-property-names($properties, 'webkit'); 62 | -moz-transition-property: transition-property-names($properties, 'moz'); 63 | transition-property: transition-property-names($properties, false); 64 | } 65 | 66 | @mixin transition-duration ($times...) { 67 | @include prefixer(transition-duration, $times, webkit moz spec); 68 | } 69 | 70 | @mixin transition-timing-function ($motions...) { 71 | // ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier() 72 | @include prefixer(transition-timing-function, $motions, webkit moz spec); 73 | } 74 | 75 | @mixin transition-delay ($times...) { 76 | @include prefixer(transition-delay, $times, webkit moz spec); 77 | } 78 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/css3/_user-select.scss: -------------------------------------------------------------------------------- 1 | @mixin user-select($arg: none) { 2 | @include prefixer(user-select, $arg, webkit moz ms spec); 3 | } 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_color-lightness.scss: -------------------------------------------------------------------------------- 1 | // Programatically determines whether a color is light or dark 2 | // Returns a boolean 3 | // More details here http://robots.thoughtbot.com/closer-look-color-lightness 4 | 5 | @function is-light($hex-color) { 6 | $-local-red: red(rgba($hex-color, 1.0)); 7 | $-local-green: green(rgba($hex-color, 1.0)); 8 | $-local-blue: blue(rgba($hex-color, 1.0)); 9 | 10 | $-local-lightness: ($-local-red * 0.2126 + $-local-green * 0.7152 + $-local-blue * 0.0722) / 255; 11 | 12 | @return $-local-lightness > .6; 13 | } 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_flex-grid.scss: -------------------------------------------------------------------------------- 1 | // Flexible grid 2 | @function flex-grid($columns, $container-columns: $fg-max-columns) { 3 | $width: $columns * $fg-column + ($columns - 1) * $fg-gutter; 4 | $container-width: $container-columns * $fg-column + ($container-columns - 1) * $fg-gutter; 5 | @return percentage($width / $container-width); 6 | } 7 | 8 | // Flexible gutter 9 | @function flex-gutter($container-columns: $fg-max-columns, $gutter: $fg-gutter) { 10 | $container-width: $container-columns * $fg-column + ($container-columns - 1) * $fg-gutter; 11 | @return percentage($gutter / $container-width); 12 | } 13 | 14 | // The $fg-column, $fg-gutter and $fg-max-columns variables must be defined in your base stylesheet to properly use the flex-grid function. 15 | // This function takes the fluid grid equation (target / context = result) and uses columns to help define each. 16 | // 17 | // The calculation presumes that your column structure will be missing the last gutter: 18 | // 19 | // -- column -- gutter -- column -- gutter -- column 20 | // 21 | // $fg-column: 60px; // Column Width 22 | // $fg-gutter: 25px; // Gutter Width 23 | // $fg-max-columns: 12; // Total Columns For Main Container 24 | // 25 | // div { 26 | // width: flex-grid(4); // returns (315px / 995px) = 31.65829%; 27 | // margin-left: flex-gutter(); // returns (25px / 995px) = 2.51256%; 28 | // 29 | // p { 30 | // width: flex-grid(2, 4); // returns (145px / 315px) = 46.031746%; 31 | // float: left; 32 | // margin: flex-gutter(4); // returns (25px / 315px) = 7.936508%; 33 | // } 34 | // 35 | // blockquote { 36 | // float: left; 37 | // width: flex-grid(2, 4); // returns (145px / 315px) = 46.031746%; 38 | // } 39 | // } -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_golden-ratio.scss: -------------------------------------------------------------------------------- 1 | @function golden-ratio($value, $increment) { 2 | @return modular-scale($value, $increment, $golden) 3 | } 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_grid-width.scss: -------------------------------------------------------------------------------- 1 | @function grid-width($n) { 2 | @return $n * $gw-column + ($n - 1) * $gw-gutter; 3 | } 4 | 5 | // The $gw-column and $gw-gutter variables must be defined in your base stylesheet to properly use the grid-width function. 6 | // 7 | // $gw-column: 100px; // Column Width 8 | // $gw-gutter: 40px; // Gutter Width 9 | // 10 | // div { 11 | // width: grid-width(4); // returns 520px; 12 | // margin-left: $gw-gutter; // returns 40px; 13 | // } 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_linear-gradient.scss: -------------------------------------------------------------------------------- 1 | @function linear-gradient($pos, $gradients...) { 2 | $type: linear; 3 | $pos-type: type-of(nth($pos, 1)); 4 | 5 | // if $pos doesn't exist, fix $gradient 6 | @if ($pos-type == color) or (nth($pos, 1) == "transparent") { 7 | $gradients: zip($pos $gradients); 8 | $pos: false; 9 | } 10 | 11 | $type-gradient: $type, $pos, $gradients; 12 | @return $type-gradient; 13 | } 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_modular-scale.scss: -------------------------------------------------------------------------------- 1 | // Scaling Variables 2 | $golden: 1.618; 3 | $minor-second: 1.067; 4 | $major-second: 1.125; 5 | $minor-third: 1.2; 6 | $major-third: 1.25; 7 | $perfect-fourth: 1.333; 8 | $augmented-fourth: 1.414; 9 | $perfect-fifth: 1.5; 10 | $minor-sixth: 1.6; 11 | $major-sixth: 1.667; 12 | $minor-seventh: 1.778; 13 | $major-seventh: 1.875; 14 | $octave: 2; 15 | $major-tenth: 2.5; 16 | $major-eleventh: 2.667; 17 | $major-twelfth: 3; 18 | $double-octave: 4; 19 | 20 | @function modular-scale($value, $increment, $ratio) { 21 | $v1: nth($value, 1); 22 | $v2: nth($value, length($value)); 23 | $value: $v1; 24 | 25 | // scale $v2 to just above $v1 26 | @while $v2 > $v1 { 27 | $v2: ($v2 / $ratio); // will be off-by-1 28 | } 29 | @while $v2 < $v1 { 30 | $v2: ($v2 * $ratio); // will fix off-by-1 31 | } 32 | 33 | // check AFTER scaling $v2 to prevent double-counting corner-case 34 | $double-stranded: $v2 > $v1; 35 | 36 | @if $increment > 0 { 37 | @for $i from 1 through $increment { 38 | @if $double-stranded and ($v1 * $ratio) > $v2 { 39 | $value: $v2; 40 | $v2: ($v2 * $ratio); 41 | } @else { 42 | $v1: ($v1 * $ratio); 43 | $value: $v1; 44 | } 45 | } 46 | } 47 | 48 | @if $increment < 0 { 49 | // adjust $v2 to just below $v1 50 | @if $double-stranded { 51 | $v2: ($v2 / $ratio); 52 | } 53 | 54 | @for $i from $increment through -1 { 55 | @if $double-stranded and ($v1 / $ratio) < $v2 { 56 | $value: $v2; 57 | $v2: ($v2 / $ratio); 58 | } @else { 59 | $v1: ($v1 / $ratio); 60 | $value: $v1; 61 | } 62 | } 63 | } 64 | 65 | @return $value; 66 | } 67 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_px-to-em.scss: -------------------------------------------------------------------------------- 1 | // Convert pixels to ems 2 | // eg. for a relational value of 12px write em(12) when the parent is 16px 3 | // if the parent is another value say 24px write em(12, 24) 4 | 5 | @function em($pxval, $base: $em-base) { 6 | @if not unitless($pxval) { 7 | $pxval: strip-units($pxval); 8 | } 9 | @if not unitless($base) { 10 | $base: strip-units($base); 11 | } 12 | @return ($pxval / $base) * 1em; 13 | } 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_px-to-rem.scss: -------------------------------------------------------------------------------- 1 | // Convert pixels to rems 2 | // eg. for a relational value of 12px write rem(12) 3 | // Assumes $em-base is the font-size of 4 | 5 | @function rem($pxval) { 6 | @if not unitless($pxval) { 7 | $pxval: strip-units($pxval); 8 | } 9 | 10 | $base: $em-base; 11 | @if not unitless($base) { 12 | $base: strip-units($base); 13 | } 14 | @return ($pxval / $base) * 1rem; 15 | } 16 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_radial-gradient.scss: -------------------------------------------------------------------------------- 1 | // This function is required and used by the background-image mixin. 2 | @function radial-gradient($G1, $G2, 3 | $G3: null, $G4: null, 4 | $G5: null, $G6: null, 5 | $G7: null, $G8: null, 6 | $G9: null, $G10: null, 7 | $pos: null, 8 | $shape-size: null) { 9 | 10 | $data: _radial-arg-parser($G1, $G2, $pos, $shape-size); 11 | $G1: nth($data, 1); 12 | $G2: nth($data, 2); 13 | $pos: nth($data, 3); 14 | $shape-size: nth($data, 4); 15 | 16 | $type: radial; 17 | $gradient: $G1, $G2, $G3, $G4, $G5, $G6, $G7, $G8, $G9, $G10; 18 | 19 | $type-gradient: $type, $shape-size $pos, $gradient; 20 | @return $type-gradient; 21 | } 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_strip-units.scss: -------------------------------------------------------------------------------- 1 | // Srtips the units from a value. e.g. 12px -> 12 2 | 3 | @function strip-units($val) { 4 | @return ($val / ($val * 0 + 1)); 5 | } 6 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_tint-shade.scss: -------------------------------------------------------------------------------- 1 | // Add percentage of white to a color 2 | @function tint($color, $percent){ 3 | @return mix(white, $color, $percent); 4 | } 5 | 6 | // Add percentage of black to a color 7 | @function shade($color, $percent){ 8 | @return mix(black, $color, $percent); 9 | } 10 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_transition-property-name.scss: -------------------------------------------------------------------------------- 1 | // Return vendor-prefixed property names if appropriate 2 | // Example: transition-property-names((transform, color, background), moz) -> -moz-transform, color, background 3 | //************************************************************************// 4 | @function transition-property-names($props, $vendor: false) { 5 | $new-props: (); 6 | 7 | @each $prop in $props { 8 | $new-props: append($new-props, transition-property-name($prop, $vendor), comma); 9 | } 10 | 11 | @return $new-props; 12 | } 13 | 14 | @function transition-property-name($prop, $vendor: false) { 15 | // put other properties that need to be prefixed here aswell 16 | @if $vendor and $prop == transform { 17 | @return unquote('-'+$vendor+'-'+$prop); 18 | } 19 | @else { 20 | @return $prop; 21 | } 22 | } -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/functions/_unpack.scss: -------------------------------------------------------------------------------- 1 | // Convert shorthand to the 4-value syntax 2 | 3 | @function unpack($shorthand) { 4 | @if length($shorthand) == 1 { 5 | @return nth($shorthand, 1) nth($shorthand, 1) nth($shorthand, 1) nth($shorthand, 1); 6 | } 7 | @else if length($shorthand) == 2 { 8 | @return nth($shorthand, 1) nth($shorthand, 2) nth($shorthand, 1) nth($shorthand, 2); 9 | } 10 | @else if length($shorthand) == 3 { 11 | @return nth($shorthand, 1) nth($shorthand, 2) nth($shorthand, 3) nth($shorthand, 2); 12 | } 13 | @else { 14 | @return $shorthand; 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/helpers/_gradient-positions-parser.scss: -------------------------------------------------------------------------------- 1 | @function _gradient-positions-parser($gradient-type, $gradient-positions) { 2 | @if $gradient-positions 3 | and ($gradient-type == linear) 4 | and (type-of($gradient-positions) != color) { 5 | $gradient-positions: _linear-positions-parser($gradient-positions); 6 | } 7 | @else if $gradient-positions 8 | and ($gradient-type == radial) 9 | and (type-of($gradient-positions) != color) { 10 | $gradient-positions: _radial-positions-parser($gradient-positions); 11 | } 12 | @return $gradient-positions; 13 | } 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/helpers/_linear-positions-parser.scss: -------------------------------------------------------------------------------- 1 | @function _linear-positions-parser($pos) { 2 | $type: type-of(nth($pos, 1)); 3 | $spec: null; 4 | $degree: null; 5 | $side: null; 6 | $corner: null; 7 | $length: length($pos); 8 | // Parse Side and corner positions 9 | @if ($length > 1) { 10 | @if nth($pos, 1) == "to" { // Newer syntax 11 | $side: nth($pos, 2); 12 | 13 | @if $length == 2 { // eg. to top 14 | // Swap for backwards compatability 15 | $degree: _position-flipper(nth($pos, 2)); 16 | } 17 | @else if $length == 3 { // eg. to top left 18 | $corner: nth($pos, 3); 19 | } 20 | } 21 | @else if $length == 2 { // Older syntax ("top left") 22 | $side: _position-flipper(nth($pos, 1)); 23 | $corner: _position-flipper(nth($pos, 2)); 24 | } 25 | 26 | @if ("#{$side} #{$corner}" == "left top") or ("#{$side} #{$corner}" == "top left") { 27 | $degree: _position-flipper(#{$side}) _position-flipper(#{$corner}); 28 | } 29 | @else if ("#{$side} #{$corner}" == "right top") or ("#{$side} #{$corner}" == "top right") { 30 | $degree: _position-flipper(#{$side}) _position-flipper(#{$corner}); 31 | } 32 | @else if ("#{$side} #{$corner}" == "right bottom") or ("#{$side} #{$corner}" == "bottom right") { 33 | $degree: _position-flipper(#{$side}) _position-flipper(#{$corner}); 34 | } 35 | @else if ("#{$side} #{$corner}" == "left bottom") or ("#{$side} #{$corner}" == "bottom left") { 36 | $degree: _position-flipper(#{$side}) _position-flipper(#{$corner}); 37 | } 38 | $spec: to $side $corner; 39 | } 40 | @else if $length == 1 { 41 | // Swap for backwards compatability 42 | @if $type == string { 43 | $degree: $pos; 44 | $spec: to _position-flipper($pos); 45 | } 46 | @else { 47 | $degree: -270 - $pos; //rotate the gradient opposite from spec 48 | $spec: $pos; 49 | } 50 | } 51 | $degree: unquote($degree + ","); 52 | $spec: unquote($spec + ","); 53 | @return $degree $spec; 54 | } 55 | 56 | @function _position-flipper($pos) { 57 | @return if($pos == left, right, null) 58 | if($pos == right, left, null) 59 | if($pos == top, bottom, null) 60 | if($pos == bottom, top, null); 61 | } 62 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/helpers/_radial-arg-parser.scss: -------------------------------------------------------------------------------- 1 | @function _radial-arg-parser($G1, $G2, $pos, $shape-size) { 2 | @each $value in $G1, $G2 { 3 | $first-val: nth($value, 1); 4 | $pos-type: type-of($first-val); 5 | $spec-at-index: null; 6 | 7 | // Determine if spec was passed to mixin 8 | @if type-of($value) == list { 9 | $spec-at-index: if(index($value, at), index($value, at), false); 10 | } 11 | @if $spec-at-index { 12 | @if $spec-at-index > 1 { 13 | @for $i from 1 through ($spec-at-index - 1) { 14 | $shape-size: $shape-size nth($value, $i); 15 | } 16 | @for $i from ($spec-at-index + 1) through length($value) { 17 | $pos: $pos nth($value, $i); 18 | } 19 | } 20 | @else if $spec-at-index == 1 { 21 | @for $i from ($spec-at-index + 1) through length($value) { 22 | $pos: $pos nth($value, $i); 23 | } 24 | } 25 | $G1: null; 26 | } 27 | 28 | // If not spec calculate correct values 29 | @else { 30 | @if ($pos-type != color) or ($first-val != "transparent") { 31 | @if ($pos-type == number) 32 | or ($first-val == "center") 33 | or ($first-val == "top") 34 | or ($first-val == "right") 35 | or ($first-val == "bottom") 36 | or ($first-val == "left") { 37 | 38 | $pos: $value; 39 | 40 | @if $pos == $G1 { 41 | $G1: null; 42 | } 43 | } 44 | 45 | @else if 46 | ($first-val == "ellipse") 47 | or ($first-val == "circle") 48 | or ($first-val == "closest-side") 49 | or ($first-val == "closest-corner") 50 | or ($first-val == "farthest-side") 51 | or ($first-val == "farthest-corner") 52 | or ($first-val == "contain") 53 | or ($first-val == "cover") { 54 | 55 | $shape-size: $value; 56 | 57 | @if $value == $G1 { 58 | $G1: null; 59 | } 60 | 61 | @else if $value == $G2 { 62 | $G2: null; 63 | } 64 | } 65 | } 66 | } 67 | } 68 | @return $G1, $G2, $pos, $shape-size; 69 | } 70 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/helpers/_radial-positions-parser.scss: -------------------------------------------------------------------------------- 1 | @function _radial-positions-parser($gradient-pos) { 2 | $shape-size: nth($gradient-pos, 1); 3 | $pos: nth($gradient-pos, 2); 4 | $shape-size-spec: _shape-size-stripper($shape-size); 5 | 6 | $pre-spec: unquote(if($pos, "#{$pos}, ", null)) 7 | unquote(if($shape-size, "#{$shape-size},", null)); 8 | $pos-spec: if($pos, "at #{$pos}", null); 9 | 10 | $spec: "#{$shape-size-spec} #{$pos-spec}"; 11 | 12 | // Add comma 13 | @if ($spec != ' ') { 14 | $spec: "#{$spec}," 15 | } 16 | 17 | @return $pre-spec $spec; 18 | } 19 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/helpers/_render-gradients.scss: -------------------------------------------------------------------------------- 1 | // User for linear and radial gradients within background-image or border-image properties 2 | 3 | @function _render-gradients($gradient-positions, $gradients, $gradient-type, $vendor: false) { 4 | $pre-spec: null; 5 | $spec: null; 6 | $vendor-gradients: null; 7 | @if $gradient-type == linear { 8 | @if $gradient-positions { 9 | $pre-spec: nth($gradient-positions, 1); 10 | $spec: nth($gradient-positions, 2); 11 | } 12 | } 13 | @else if $gradient-type == radial { 14 | $pre-spec: nth($gradient-positions, 1); 15 | $spec: nth($gradient-positions, 2); 16 | } 17 | 18 | @if $vendor { 19 | $vendor-gradients: "-#{$vendor}-#{$gradient-type}-gradient(#{$pre-spec} #{$gradients})"; 20 | } 21 | @else if $vendor == false { 22 | $vendor-gradients: "#{$gradient-type}-gradient(#{$spec} #{$gradients})"; 23 | } 24 | $vendor-gradients: unquote($vendor-gradients); 25 | @return $vendor-gradients; 26 | } 27 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/helpers/_shape-size-stripper.scss: -------------------------------------------------------------------------------- 1 | @function _shape-size-stripper($shape-size) { 2 | $shape-size-spec: null; 3 | @each $value in $shape-size { 4 | @if ($value == "cover") or ($value == "contain") { 5 | $value: null; 6 | } 7 | $shape-size-spec: "#{$shape-size-spec} #{$value}"; 8 | } 9 | @return $shape-size-spec; 10 | } 11 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/settings/_asset-pipeline.scss: -------------------------------------------------------------------------------- 1 | $asset-pipeline: false !default; 2 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/settings/_prefixer.scss: -------------------------------------------------------------------------------- 1 | // Variable settings for /addons/prefixer.scss 2 | $prefix-for-webkit: true !default; 3 | $prefix-for-mozilla: true !default; 4 | $prefix-for-microsoft: true !default; 5 | $prefix-for-opera: true !default; 6 | $prefix-for-spec: true !default; // required for keyframe mixin 7 | -------------------------------------------------------------------------------- /app/assets/stylesheets/bourbon/settings/_px-to-em.scss: -------------------------------------------------------------------------------- 1 | $em-base: 16px !default; 2 | -------------------------------------------------------------------------------- /app/assets/stylesheets/devise.css.sass: -------------------------------------------------------------------------------- 1 | @import 'bourbon/bourbon' 2 | @import 'normalize' 3 | 4 | html 5 | background: #F2F2F2 6 | 7 | html, body 8 | height: 100% 9 | margin: 0 10 | padding: 0 11 | font-size: 16px 12 | text-align: center 13 | padding-top: 3em 14 | 15 | form 16 | width: 320px 17 | margin: 1em auto 18 | padding: 1.5em 19 | background: #FFF 20 | box-shadow: 0 1px 6px rgba(0,0,0,0.12), 0 1px 4px rgba(0,0,0,0.12) 21 | 22 | .field, .actions 23 | text-align: left 24 | padding: 0 1em 25 | margin: 1em 0em 26 | 27 | input[type=text], 28 | input[type=password], 29 | input[type=email], 30 | input[type=submit] 31 | width: 100% 32 | height: 2em 33 | border-radius: 3px 34 | background: white 35 | border: 1px solid rgba(0,0,0,0.12) 36 | 37 | input[type=text]:focus, 38 | input[type=password]:focus, 39 | input[type=email]:focus 40 | border-color: #66afe9 41 | outline: 0 42 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6) 43 | box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6) 44 | 45 | input[type=submit] 46 | background: rgb(102,175,233) 47 | color: #FFF 48 | 49 | label 50 | text-transform: uppercase 51 | font-size: 0.8em 52 | color: #666 -------------------------------------------------------------------------------- /app/assets/stylesheets/normalize.scss: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */ 2 | 3 | /** 4 | * 1. Set default font family to sans-serif. 5 | * 2. Prevent iOS text size adjust after orientation change, without disabling 6 | * user zoom. 7 | */ 8 | 9 | html { 10 | font-family: sans-serif; /* 1 */ 11 | -ms-text-size-adjust: 100%; /* 2 */ 12 | -webkit-text-size-adjust: 100%; /* 2 */ 13 | } 14 | 15 | /** 16 | * Remove default margin. 17 | */ 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | /* HTML5 display definitions 24 | ========================================================================== */ 25 | 26 | /** 27 | * Correct `block` display not defined for any HTML5 element in IE 8/9. 28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11 29 | * and Firefox. 30 | * Correct `block` display not defined for `main` in IE 11. 31 | */ 32 | 33 | article, 34 | aside, 35 | details, 36 | figcaption, 37 | figure, 38 | footer, 39 | header, 40 | hgroup, 41 | main, 42 | menu, 43 | nav, 44 | section, 45 | summary { 46 | display: block; 47 | } 48 | 49 | /** 50 | * 1. Correct `inline-block` display not defined in IE 8/9. 51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. 52 | */ 53 | 54 | audio, 55 | canvas, 56 | progress, 57 | video { 58 | display: inline-block; /* 1 */ 59 | vertical-align: baseline; /* 2 */ 60 | } 61 | 62 | /** 63 | * Prevent modern browsers from displaying `audio` without controls. 64 | * Remove excess height in iOS 5 devices. 65 | */ 66 | 67 | audio:not([controls]) { 68 | display: none; 69 | height: 0; 70 | } 71 | 72 | /** 73 | * Address `[hidden]` styling not present in IE 8/9/10. 74 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. 75 | */ 76 | 77 | [hidden], 78 | template { 79 | display: none; 80 | } 81 | 82 | /* Links 83 | ========================================================================== */ 84 | 85 | /** 86 | * Remove the gray background color from active links in IE 10. 87 | */ 88 | 89 | a { 90 | background-color: transparent; 91 | } 92 | 93 | /** 94 | * Improve readability when focused and also mouse hovered in all browsers. 95 | */ 96 | 97 | a:active, 98 | a:hover { 99 | outline: 0; 100 | } 101 | 102 | /* Text-level semantics 103 | ========================================================================== */ 104 | 105 | /** 106 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome. 107 | */ 108 | 109 | abbr[title] { 110 | border-bottom: 1px dotted; 111 | } 112 | 113 | /** 114 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. 115 | */ 116 | 117 | b, 118 | strong { 119 | font-weight: bold; 120 | } 121 | 122 | /** 123 | * Address styling not present in Safari and Chrome. 124 | */ 125 | 126 | dfn { 127 | font-style: italic; 128 | } 129 | 130 | /** 131 | * Address variable `h1` font-size and margin within `section` and `article` 132 | * contexts in Firefox 4+, Safari, and Chrome. 133 | */ 134 | 135 | h1 { 136 | font-size: 2em; 137 | margin: 0.67em 0; 138 | } 139 | 140 | /** 141 | * Address styling not present in IE 8/9. 142 | */ 143 | 144 | mark { 145 | background: #ff0; 146 | color: #000; 147 | } 148 | 149 | /** 150 | * Address inconsistent and variable font size in all browsers. 151 | */ 152 | 153 | small { 154 | font-size: 80%; 155 | } 156 | 157 | /** 158 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 159 | */ 160 | 161 | sub, 162 | sup { 163 | font-size: 75%; 164 | line-height: 0; 165 | position: relative; 166 | vertical-align: baseline; 167 | } 168 | 169 | sup { 170 | top: -0.5em; 171 | } 172 | 173 | sub { 174 | bottom: -0.25em; 175 | } 176 | 177 | /* Embedded content 178 | ========================================================================== */ 179 | 180 | /** 181 | * Remove border when inside `a` element in IE 8/9/10. 182 | */ 183 | 184 | img { 185 | border: 0; 186 | } 187 | 188 | /** 189 | * Correct overflow not hidden in IE 9/10/11. 190 | */ 191 | 192 | svg:not(:root) { 193 | overflow: hidden; 194 | } 195 | 196 | /* Grouping content 197 | ========================================================================== */ 198 | 199 | /** 200 | * Address margin not present in IE 8/9 and Safari. 201 | */ 202 | 203 | figure { 204 | margin: 1em 40px; 205 | } 206 | 207 | /** 208 | * Address differences between Firefox and other browsers. 209 | */ 210 | 211 | hr { 212 | -moz-box-sizing: content-box; 213 | box-sizing: content-box; 214 | height: 0; 215 | } 216 | 217 | /** 218 | * Contain overflow in all browsers. 219 | */ 220 | 221 | pre { 222 | overflow: auto; 223 | } 224 | 225 | /** 226 | * Address odd `em`-unit font size rendering in all browsers. 227 | */ 228 | 229 | code, 230 | kbd, 231 | pre, 232 | samp { 233 | font-family: monospace, monospace; 234 | font-size: 1em; 235 | } 236 | 237 | /* Forms 238 | ========================================================================== */ 239 | 240 | /** 241 | * Known limitation: by default, Chrome and Safari on OS X allow very limited 242 | * styling of `select`, unless a `border` property is set. 243 | */ 244 | 245 | /** 246 | * 1. Correct color not being inherited. 247 | * Known issue: affects color of disabled elements. 248 | * 2. Correct font properties not being inherited. 249 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. 250 | */ 251 | 252 | button, 253 | input, 254 | optgroup, 255 | select, 256 | textarea { 257 | color: inherit; /* 1 */ 258 | font: inherit; /* 2 */ 259 | margin: 0; /* 3 */ 260 | } 261 | 262 | /** 263 | * Address `overflow` set to `hidden` in IE 8/9/10/11. 264 | */ 265 | 266 | button { 267 | overflow: visible; 268 | } 269 | 270 | /** 271 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 272 | * All other form control elements do not inherit `text-transform` values. 273 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. 274 | * Correct `select` style inheritance in Firefox. 275 | */ 276 | 277 | button, 278 | select { 279 | text-transform: none; 280 | } 281 | 282 | /** 283 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 284 | * and `video` controls. 285 | * 2. Correct inability to style clickable `input` types in iOS. 286 | * 3. Improve usability and consistency of cursor style between image-type 287 | * `input` and others. 288 | */ 289 | 290 | button, 291 | html input[type="button"], /* 1 */ 292 | input[type="reset"], 293 | input[type="submit"] { 294 | -webkit-appearance: button; /* 2 */ 295 | cursor: pointer; /* 3 */ 296 | } 297 | 298 | /** 299 | * Re-set default cursor for disabled elements. 300 | */ 301 | 302 | button[disabled], 303 | html input[disabled] { 304 | cursor: default; 305 | } 306 | 307 | /** 308 | * Remove inner padding and border in Firefox 4+. 309 | */ 310 | 311 | button::-moz-focus-inner, 312 | input::-moz-focus-inner { 313 | border: 0; 314 | padding: 0; 315 | } 316 | 317 | /** 318 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in 319 | * the UA stylesheet. 320 | */ 321 | 322 | input { 323 | line-height: normal; 324 | } 325 | 326 | /** 327 | * It's recommended that you don't attempt to style these elements. 328 | * Firefox's implementation doesn't respect box-sizing, padding, or width. 329 | * 330 | * 1. Address box sizing set to `content-box` in IE 8/9/10. 331 | * 2. Remove excess padding in IE 8/9/10. 332 | */ 333 | 334 | input[type="checkbox"], 335 | input[type="radio"] { 336 | box-sizing: border-box; /* 1 */ 337 | padding: 0; /* 2 */ 338 | } 339 | 340 | /** 341 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain 342 | * `font-size` values of the `input`, it causes the cursor style of the 343 | * decrement button to change from `default` to `text`. 344 | */ 345 | 346 | input[type="number"]::-webkit-inner-spin-button, 347 | input[type="number"]::-webkit-outer-spin-button { 348 | height: auto; 349 | } 350 | 351 | /** 352 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome. 353 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome 354 | * (include `-moz` to future-proof). 355 | */ 356 | 357 | input[type="search"] { 358 | -webkit-appearance: textfield; /* 1 */ 359 | -moz-box-sizing: content-box; 360 | -webkit-box-sizing: content-box; /* 2 */ 361 | box-sizing: content-box; 362 | } 363 | 364 | /** 365 | * Remove inner padding and search cancel button in Safari and Chrome on OS X. 366 | * Safari (but not Chrome) clips the cancel button when the search input has 367 | * padding (and `textfield` appearance). 368 | */ 369 | 370 | input[type="search"]::-webkit-search-cancel-button, 371 | input[type="search"]::-webkit-search-decoration { 372 | -webkit-appearance: none; 373 | } 374 | 375 | /** 376 | * Define consistent border, margin, and padding. 377 | */ 378 | 379 | fieldset { 380 | border: 1px solid #c0c0c0; 381 | margin: 0 2px; 382 | padding: 0.35em 0.625em 0.75em; 383 | } 384 | 385 | /** 386 | * 1. Correct `color` not being inherited in IE 8/9/10/11. 387 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 388 | */ 389 | 390 | legend { 391 | border: 0; /* 1 */ 392 | padding: 0; /* 2 */ 393 | } 394 | 395 | /** 396 | * Remove default vertical scrollbar in IE 8/9/10/11. 397 | */ 398 | 399 | textarea { 400 | overflow: auto; 401 | } 402 | 403 | /** 404 | * Don't inherit the `font-weight` (applied by a rule above). 405 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. 406 | */ 407 | 408 | optgroup { 409 | font-weight: bold; 410 | } 411 | 412 | /* Tables 413 | ========================================================================== */ 414 | 415 | /** 416 | * Remove most spacing between table cells. 417 | */ 418 | 419 | table { 420 | border-collapse: collapse; 421 | border-spacing: 0; 422 | } 423 | 424 | td, 425 | th { 426 | padding: 0; 427 | } 428 | -------------------------------------------------------------------------------- /app/controllers/admin/confirmations_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::ConfirmationsController < Devise::ConfirmationsController 2 | layout 'admin' 3 | end 4 | -------------------------------------------------------------------------------- /app/controllers/admin/omniauth_callbacks_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::OmniauthCallbacksController < Devise::OmniauthCallbacksController 2 | layout 'admin' 3 | end 4 | -------------------------------------------------------------------------------- /app/controllers/admin/passwords_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::PasswordsController < Devise::PasswordsController 2 | layout 'admin' 3 | end 4 | -------------------------------------------------------------------------------- /app/controllers/admin/registrations_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::RegistrationsController < Devise::RegistrationsController 2 | layout 'admin' 3 | end 4 | -------------------------------------------------------------------------------- /app/controllers/admin/sessions_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::SessionsController < Devise::SessionsController 2 | layout 'admin' 3 | 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/admin/unlocks_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::UnlocksController < Devise::UnlocksController 2 | layout 'admin' 3 | end 4 | -------------------------------------------------------------------------------- /app/controllers/api/hotels_controller.rb: -------------------------------------------------------------------------------- 1 | class Api::HotelsController < InheritedResources::Base 2 | respond_to :json 3 | 4 | # GET /api/hotels 5 | def index 6 | @hotels = Hotel.all.order(:name) 7 | respond_with(@hotels) 8 | end 9 | 10 | # GET /api/hotels/:id 11 | def find 12 | @hotel = Hotel.find(params[:id]) 13 | respond_with(@hotel) 14 | end 15 | 16 | # PUT /api/hotels/:id 17 | def update 18 | @hotel = Hotel.find(params[:hotel][:id]) 19 | if @hotel.update_attributes(params[:hotel]) 20 | head :no_content and return 21 | else 22 | head :no_content, status: :unprocessable_entity 23 | end 24 | end 25 | 26 | # GET /api/search 27 | def search 28 | render nothing: true, status: :unprocessable_entity and return unless params[:q].present? 29 | @hotels = Hotel.search(params[:q]) 30 | respond_with(@hotels) 31 | end 32 | 33 | # DELETE /api/search 34 | def destroy 35 | @hotel = Hotel.find(params[:id]) 36 | 37 | if @hotel.destroy 38 | head :no_content and return 39 | else 40 | render nothing: true, status: :bad_request 41 | end 42 | end 43 | end -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found 3 | protect_from_forgery with: :null_session 4 | 5 | def record_not_found 6 | render nothing: true, status: 404 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zekitow/rails-api-and-angularjs/46f50e9d6c80071dd89f2c7557c80e3ced8e9003/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /app/controllers/home_controller.rb: -------------------------------------------------------------------------------- 1 | class HomeController < ApplicationController 2 | 3 | # GET '/' 4 | def index 5 | render nothing: true, status: :not_implemented 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/mailers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zekitow/rails-api-and-angularjs/46f50e9d6c80071dd89f2c7557c80e3ced8e9003/app/mailers/.gitkeep -------------------------------------------------------------------------------- /app/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zekitow/rails-api-and-angularjs/46f50e9d6c80071dd89f2c7557c80e3ced8e9003/app/mailers/.keep -------------------------------------------------------------------------------- /app/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zekitow/rails-api-and-angularjs/46f50e9d6c80071dd89f2c7557c80e3ced8e9003/app/models/.keep -------------------------------------------------------------------------------- /app/models/admin.rb: -------------------------------------------------------------------------------- 1 | class Admin < ActiveRecord::Base 2 | devise :database_authenticatable, :recoverable, 3 | :rememberable, :trackable, :validatable 4 | end 5 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zekitow/rails-api-and-angularjs/46f50e9d6c80071dd89f2c7557c80e3ced8e9003/app/models/concerns/.keep -------------------------------------------------------------------------------- /app/models/hotel.rb: -------------------------------------------------------------------------------- 1 | class Hotel < ActiveRecord::Base 2 | include SearchCop 3 | search_scope :search do 4 | attributes :name, :address 5 | end 6 | 7 | validates :name, :address, :star_rating, :accomodation_type, presence: true 8 | validates_numericality_of :star_rating 9 | end 10 | -------------------------------------------------------------------------------- /app/views/home/index.html.erb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zekitow/rails-api-and-angularjs/46f50e9d6c80071dd89f2c7557c80e3ced8e9003/app/views/home/index.html.erb -------------------------------------------------------------------------------- /app/views/layouts/admin.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Admin 7 | 8 | <%= stylesheet_link_tag 'devise', media: 'all' %> 9 | <%= csrf_meta_tags %> 10 | 11 | 12 | <%= yield %> 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <%= yield %> 6 | <%= javascript_include_tag 'application' %> 7 | 8 | 9 | -------------------------------------------------------------------------------- /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 5 | end 6 | APP_PATH = File.expand_path('../../config/application', __FILE__) 7 | require_relative '../config/boot' 8 | require 'rails/commands' 9 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path("../spring", __FILE__) 4 | rescue LoadError 5 | end 6 | require_relative '../config/boot' 7 | require 'rake' 8 | Rake.application.run 9 | -------------------------------------------------------------------------------- /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 | ENV["GEM_PATH"] = ([Bundler.bundle_path.to_s] + Gem.path).join(File::PATH_SEPARATOR) 12 | ENV["GEM_HOME"] = "" 13 | Gem.paths = ENV 14 | 15 | gem "spring", match[1] 16 | require "spring/binstub" 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require ::File.expand_path('../config/environment', __FILE__) 4 | run Rails.application 5 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../boot', __FILE__) 2 | 3 | # require 'rails/all' 4 | require 'active_record/railtie' 5 | require 'action_controller/railtie' 6 | require 'action_mailer/railtie' 7 | require 'active_model/railtie' 8 | 9 | # Require the gems listed in Gemfile, including any gems 10 | # you've limited to :test, :development, or :production. 11 | Bundler.require(*Rails.groups) 12 | 13 | module ApplicationName 14 | class Application < Rails::Application 15 | config.action_controller.permit_all_parameters = true 16 | # Settings in config/environments/* take precedence over those specified here. 17 | # Application configuration should go into files in config/initializers 18 | # -- all .rb files in that directory are automatically loaded. 19 | 20 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. 21 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. 22 | # config.time_zone = 'Central Time (US & Canada)' 23 | 24 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. 25 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] 26 | # config.i18n.default_locale = :de 27 | 28 | config.middleware.insert_before "ActionDispatch::Static", "Rack::Cors", :debug => true, :logger => Rails.logger do 29 | allow do 30 | origins '*' 31 | 32 | resource '*', 33 | :headers => :any, 34 | :methods => [:get, :post, :delete, :put, :options], 35 | :max_age => 0 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | # Set up gems listed in the Gemfile. 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | 4 | require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) 5 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: postgresql 3 | encoding: unicode 4 | database: hotels_development 5 | username: hotels 6 | password: 7 | pool: 5 8 | 9 | test: &test 10 | adapter: postgresql 11 | encoding: unicode 12 | database: hotels_test 13 | username: hotels 14 | password: 15 | pool: 5 16 | 17 | production: 18 | adapter: postgresql 19 | encoding: unicode 20 | database: rails 21 | username: rails 22 | password: 23 | pool: 5 24 | 25 | cucumber: 26 | <<: *test -------------------------------------------------------------------------------- /config/deploy.rb: -------------------------------------------------------------------------------- 1 | # -*- encoding : utf-8 -*- 2 | require 'mina/bundler' 3 | require 'mina/rails' 4 | require 'mina/git' 5 | require 'mina/rvm' 6 | 7 | set :domain, '127.0.0.1' 8 | set :user, 'root' 9 | set :deploy_to, '/home/rails' 10 | set :repository, 'git@repot-name/APPNAME.git' 11 | set :branch, 'master' 12 | set :rvm_path, '/usr/local/rvm/bin/rvm' 13 | set :ssh_flags, "-l root" 14 | set :shared_paths, ['config/database.yml', 'log'] 15 | 16 | task :environment do 17 | invoke :'rvm:use[2.1.3@APPNAME]' 18 | end 19 | 20 | task :setup => :environment do 21 | queue! %[mkdir -p "#{deploy_to}/shared/log"] 22 | queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/log"] 23 | queue! %[mkdir -p "#{deploy_to}/shared/config"] 24 | queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/config"] 25 | queue! %[touch "#{deploy_to}/shared/config/database.yml"] 26 | queue! %[mkdir -p "#{deploy_to}/shared/public/system"] 27 | 28 | end 29 | 30 | desc "Deploys the current version to the server." 31 | task :deploy => :environment do 32 | deploy do 33 | invoke :'git:clone' 34 | invoke :'deploy:link_shared_paths' 35 | invoke :'bundle:install' 36 | invoke :'rails:db_migrate' 37 | invoke :'rails:assets_precompile' 38 | 39 | to :launch do 40 | queue! '/etc/init.d/unicorn restart' 41 | queue! '/etc/init.d/nginx restart' 42 | queue! 'rm -f /home/rails/current/public/system/' 43 | queue! "ln -s /home/rails/shared/public/system/ /home/rails/current/public/" 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require File.expand_path('../application', __FILE__) 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 and disable caching. 13 | config.consider_all_requests_local = true 14 | config.action_controller.perform_caching = false 15 | 16 | # Don't care if the mailer can't send. 17 | config.action_mailer.raise_delivery_errors = false 18 | 19 | # Print deprecation notices to the Rails logger. 20 | config.active_support.deprecation = :log 21 | 22 | # Raise an error on page load if there are pending migrations. 23 | config.active_record.migration_error = :page_load 24 | 25 | # Debug mode disables concatenation and preprocessing of assets. 26 | # This option may cause significant delays in view rendering with a large 27 | # number of complex assets. 28 | config.assets.debug = false 29 | 30 | # Adds additional error checking when serving assets at runtime. 31 | # Checks for improperly declared sprockets dependencies. 32 | # Raises helpful error messages. 33 | config.assets.raise_runtime_errors = true 34 | 35 | # Raises error for missing translations 36 | # config.action_view.raise_on_missing_translations = true 37 | end 38 | -------------------------------------------------------------------------------- /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 | # Enable Rack::Cache to put a simple HTTP cache in front of your application 18 | # Add `rack-cache` to your Gemfile before enabling this. 19 | # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid. 20 | # config.action_dispatch.rack_cache = true 21 | 22 | # Disable Rails's static asset server (Apache or nginx will already do this). 23 | 24 | # Compress JavaScripts and CSS. 25 | config.assets.js_compressor = :uglifier 26 | # config.assets.css_compressor = :sass 27 | 28 | # Do not fallback to assets pipeline if a precompiled asset is missed. 29 | config.assets.compile = false 30 | 31 | # Generate digests for assets URLs. 32 | config.assets.digest = true 33 | 34 | # `config.assets.precompile` has moved to config/initializers/assets.rb 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 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 41 | # config.force_ssl = true 42 | 43 | # Set to :debug to see everything in the log. 44 | config.log_level = :info 45 | 46 | # Prepend all log lines with the following tags. 47 | # config.log_tags = [ :subdomain, :uuid ] 48 | 49 | # Use a different logger for distributed setups. 50 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) 51 | 52 | # Use a different cache store in production. 53 | # config.cache_store = :mem_cache_store 54 | 55 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 56 | # config.action_controller.asset_host = "http://assets.example.com" 57 | 58 | # Precompile additional assets. 59 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. 60 | # config.assets.precompile += %w( search.js ) 61 | 62 | # Ignore bad email addresses and do not raise email delivery errors. 63 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 64 | # config.action_mailer.raise_delivery_errors = false 65 | 66 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 67 | # the I18n.default_locale when a translation cannot be found). 68 | config.i18n.fallbacks = true 69 | 70 | # Send deprecation notices to registered listeners. 71 | config.active_support.deprecation = :notify 72 | 73 | # Disable automatic flushing of the log to improve performance. 74 | # config.autoflush_log = false 75 | 76 | # Use default logging formatter so that PID and timestamp are not suppressed. 77 | config.log_formatter = ::Logger::Formatter.new 78 | 79 | # Do not dump schema after migrations. 80 | end -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # The test environment is used exclusively to run your application's 5 | # test suite. You never need to work with it otherwise. Remember that 6 | # your test database is "scratch space" for the test suite and is wiped 7 | # and recreated between test runs. Don't rely on the data there! 8 | config.cache_classes = true 9 | 10 | # Do not eager load code on boot. This avoids loading your whole application 11 | # just for the purpose of running a single test. If you are using a tool that 12 | # preloads Rails for running tests, you may have to set it to true. 13 | config.eager_load = false 14 | 15 | # Configure static asset server for tests with Cache-Control for performance. 16 | config.static_cache_control = 'public, max-age=3600' 17 | 18 | # Show full error reports and disable caching. 19 | config.consider_all_requests_local = true 20 | config.action_controller.perform_caching = false 21 | 22 | # Raise exceptions instead of rendering exception templates. 23 | config.action_dispatch.show_exceptions = false 24 | 25 | # Disable request forgery protection in test environment. 26 | config.action_controller.allow_forgery_protection = false 27 | 28 | # Tell Action Mailer not to deliver emails to the real world. 29 | # The :test delivery method accumulates sent emails in the 30 | # ActionMailer::Base.deliveries array. 31 | config.action_mailer.delivery_method = :test 32 | 33 | # Print deprecation notices to the stderr. 34 | config.active_support.deprecation = :stderr 35 | 36 | # Raises error for missing translations 37 | # config.action_view.raise_on_missing_translations = true 38 | end 39 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = '1.0' 5 | 6 | # Precompile additional assets. 7 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. 8 | Rails.application.config.assets.precompile += %w( devise.css ) 9 | -------------------------------------------------------------------------------- /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/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.action_dispatch.cookies_serializer = :json -------------------------------------------------------------------------------- /config/initializers/devise.rb: -------------------------------------------------------------------------------- 1 | # Use this hook to configure devise mailer, warden hooks and so forth. 2 | # Many of these configuration options can be set straight in your model. 3 | Devise.setup do |config| 4 | # The secret key used by Devise. Devise uses this key to generate 5 | # random tokens. Changing this key will render invalid all existing 6 | # confirmation, reset password and unlock tokens in the database. 7 | # config.secret_key = '4e950584cdc3b5380c7f43c8a13459096d45c1be85803b6f4d7a07177180f049bf96589483e509fc270159ea3ec5bbda476fdb8d39b0d90c0e9e14c2bd8b7eb6' 8 | 9 | # ==> Mailer Configuration 10 | # Configure the e-mail address which will be shown in Devise::Mailer, 11 | # note that it will be overwritten if you use your own mailer class 12 | # with default "from" parameter. 13 | config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com' 14 | 15 | # Configure the class responsible to send e-mails. 16 | # config.mailer = 'Devise::Mailer' 17 | 18 | # ==> ORM configuration 19 | # Load and configure the ORM. Supports :active_record (default) and 20 | # :mongoid (bson_ext recommended) by default. Other ORMs may be 21 | # available as additional gems. 22 | require 'devise/orm/active_record' 23 | 24 | # ==> Configuration for any authentication mechanism 25 | # Configure which keys are used when authenticating a user. The default is 26 | # just :email. You can configure it to use [:username, :subdomain], so for 27 | # authenticating a user, both parameters are required. Remember that those 28 | # parameters are used only when authenticating and not when retrieving from 29 | # session. If you need permissions, you should implement that in a before filter. 30 | # You can also supply a hash where the value is a boolean determining whether 31 | # or not authentication should be aborted when the value is not present. 32 | # config.authentication_keys = [ :email ] 33 | 34 | # Configure parameters from the request object used for authentication. Each entry 35 | # given should be a request method and it will automatically be passed to the 36 | # find_for_authentication method and considered in your model lookup. For instance, 37 | # if you set :request_keys to [:subdomain], :subdomain will be used on authentication. 38 | # The same considerations mentioned for authentication_keys also apply to request_keys. 39 | # config.request_keys = [] 40 | 41 | # Configure which authentication keys should be case-insensitive. 42 | # These keys will be downcased upon creating or modifying a user and when used 43 | # to authenticate or find a user. Default is :email. 44 | config.case_insensitive_keys = [ :email ] 45 | 46 | # Configure which authentication keys should have whitespace stripped. 47 | # These keys will have whitespace before and after removed upon creating or 48 | # modifying a user and when used to authenticate or find a user. Default is :email. 49 | config.strip_whitespace_keys = [ :email ] 50 | 51 | # Tell if authentication through request.params is enabled. True by default. 52 | # It can be set to an array that will enable params authentication only for the 53 | # given strategies, for example, `config.params_authenticatable = [:database]` will 54 | # enable it only for database (email + password) authentication. 55 | # config.params_authenticatable = true 56 | 57 | # Tell if authentication through HTTP Auth is enabled. False by default. 58 | # It can be set to an array that will enable http authentication only for the 59 | # given strategies, for example, `config.http_authenticatable = [:database]` will 60 | # enable it only for database authentication. The supported strategies are: 61 | # :database = Support basic authentication with authentication key + password 62 | # config.http_authenticatable = false 63 | 64 | # If 401 status code should be returned for AJAX requests. True by default. 65 | # config.http_authenticatable_on_xhr = true 66 | 67 | # The realm used in Http Basic Authentication. 'Application' by default. 68 | # config.http_authentication_realm = 'Application' 69 | 70 | # It will change confirmation, password recovery and other workflows 71 | # to behave the same regardless if the e-mail provided was right or wrong. 72 | # Does not affect registerable. 73 | # config.paranoid = true 74 | 75 | # By default Devise will store the user in session. You can skip storage for 76 | # particular strategies by setting this option. 77 | # Notice that if you are skipping storage for all authentication paths, you 78 | # may want to disable generating routes to Devise's sessions controller by 79 | # passing skip: :sessions to `devise_for` in your config/routes.rb 80 | config.skip_session_storage = [:http_auth] 81 | 82 | # By default, Devise cleans up the CSRF token on authentication to 83 | # avoid CSRF token fixation attacks. This means that, when using AJAX 84 | # requests for sign in and sign up, you need to get a new CSRF token 85 | # from the server. You can disable this option at your own risk. 86 | # config.clean_up_csrf_token_on_authentication = true 87 | 88 | # ==> Configuration for :database_authenticatable 89 | # For bcrypt, this is the cost for hashing the password and defaults to 10. If 90 | # using other encryptors, it sets how many times you want the password re-encrypted. 91 | # 92 | # Limiting the stretches to just one in testing will increase the performance of 93 | # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use 94 | # a value less than 10 in other environments. Note that, for bcrypt (the default 95 | # encryptor), the cost increases exponentially with the number of stretches (e.g. 96 | # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation). 97 | config.stretches = Rails.env.test? ? 1 : 10 98 | 99 | # Setup a pepper to generate the encrypted password. 100 | # config.pepper = '37494624c452e7064e2b2beac91e713418801e09adf1d4abd01a21a74d45017a3136955e2f5bf3a025e7c0db88c99e6fa98af06c97ab11cc7982f3b7c1a5797e' 101 | 102 | # ==> Configuration for :confirmable 103 | # A period that the user is allowed to access the website even without 104 | # confirming their account. For instance, if set to 2.days, the user will be 105 | # able to access the website for two days without confirming their account, 106 | # access will be blocked just in the third day. Default is 0.days, meaning 107 | # the user cannot access the website without confirming their account. 108 | # config.allow_unconfirmed_access_for = 2.days 109 | 110 | # A period that the user is allowed to confirm their account before their 111 | # token becomes invalid. For example, if set to 3.days, the user can confirm 112 | # their account within 3 days after the mail was sent, but on the fourth day 113 | # their account can't be confirmed with the token any more. 114 | # Default is nil, meaning there is no restriction on how long a user can take 115 | # before confirming their account. 116 | # config.confirm_within = 3.days 117 | 118 | # If true, requires any email changes to be confirmed (exactly the same way as 119 | # initial account confirmation) to be applied. Requires additional unconfirmed_email 120 | # db field (see migrations). Until confirmed, new email is stored in 121 | # unconfirmed_email column, and copied to email column on successful confirmation. 122 | config.reconfirmable = true 123 | 124 | # Defines which key will be used when confirming an account 125 | # config.confirmation_keys = [ :email ] 126 | 127 | # ==> Configuration for :rememberable 128 | # The time the user will be remembered without asking for credentials again. 129 | # config.remember_for = 2.weeks 130 | 131 | # Invalidates all the remember me tokens when the user signs out. 132 | config.expire_all_remember_me_on_sign_out = true 133 | 134 | # If true, extends the user's remember period when remembered via cookie. 135 | # config.extend_remember_period = false 136 | 137 | # Options to be passed to the created cookie. For instance, you can set 138 | # secure: true in order to force SSL only cookies. 139 | # config.rememberable_options = {} 140 | 141 | # ==> Configuration for :validatable 142 | # Range for password length. 143 | config.password_length = 8..128 144 | 145 | # Email regex used to validate email formats. It simply asserts that 146 | # one (and only one) @ exists in the given string. This is mainly 147 | # to give user feedback and not to assert the e-mail validity. 148 | # config.email_regexp = /\A[^@]+@[^@]+\z/ 149 | 150 | # ==> Configuration for :timeoutable 151 | # The time you want to timeout the user session without activity. After this 152 | # time the user will be asked for credentials again. Default is 30 minutes. 153 | # config.timeout_in = 30.minutes 154 | 155 | # If true, expires auth token on session timeout. 156 | # config.expire_auth_token_on_timeout = false 157 | 158 | # ==> Configuration for :lockable 159 | # Defines which strategy will be used to lock an account. 160 | # :failed_attempts = Locks an account after a number of failed attempts to sign in. 161 | # :none = No lock strategy. You should handle locking by yourself. 162 | # config.lock_strategy = :failed_attempts 163 | 164 | # Defines which key will be used when locking and unlocking an account 165 | # config.unlock_keys = [ :email ] 166 | 167 | # Defines which strategy will be used to unlock an account. 168 | # :email = Sends an unlock link to the user email 169 | # :time = Re-enables login after a certain amount of time (see :unlock_in below) 170 | # :both = Enables both strategies 171 | # :none = No unlock strategy. You should handle unlocking by yourself. 172 | # config.unlock_strategy = :both 173 | 174 | # Number of authentication tries before locking an account if lock_strategy 175 | # is failed attempts. 176 | # config.maximum_attempts = 20 177 | 178 | # Time interval to unlock the account if :time is enabled as unlock_strategy. 179 | # config.unlock_in = 1.hour 180 | 181 | # Warn on the last attempt before the account is locked. 182 | # config.last_attempt_warning = true 183 | 184 | # ==> Configuration for :recoverable 185 | # 186 | # Defines which key will be used when recovering the password for an account 187 | # config.reset_password_keys = [ :email ] 188 | 189 | # Time interval you can reset your password with a reset password key. 190 | # Don't put a too small interval or your users won't have the time to 191 | # change their passwords. 192 | config.reset_password_within = 6.hours 193 | 194 | # ==> Configuration for :encryptable 195 | # Allow you to use another encryption algorithm besides bcrypt (default). You can use 196 | # :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1, 197 | # :authlogic_sha512 (then you should set stretches above to 20 for default behavior) 198 | # and :restful_authentication_sha1 (then you should set stretches to 10, and copy 199 | # REST_AUTH_SITE_KEY to pepper). 200 | # 201 | # Require the `devise-encryptable` gem when using anything other than bcrypt 202 | # config.encryptor = :sha512 203 | 204 | # ==> Scopes configuration 205 | # Turn scoped views on. Before rendering "sessions/new", it will first check for 206 | # "users/sessions/new". It's turned off by default because it's slower if you 207 | # are using only default views. 208 | # config.scoped_views = false 209 | 210 | # Configure the default scope given to Warden. By default it's the first 211 | # devise role declared in your routes (usually :user). 212 | # config.default_scope = :user 213 | 214 | # Set this configuration to false if you want /users/sign_out to sign out 215 | # only the current scope. By default, Devise signs out all scopes. 216 | # config.sign_out_all_scopes = true 217 | 218 | # ==> Navigation configuration 219 | # Lists the formats that should be treated as navigational. Formats like 220 | # :html, should redirect to the sign in page when the user does not have 221 | # access, but formats like :xml or :json, should return 401. 222 | # 223 | # If you have any extra navigational formats, like :iphone or :mobile, you 224 | # should add them to the navigational formats lists. 225 | # 226 | # The "*/*" below is required to match Internet Explorer requests. 227 | # config.navigational_formats = ['*/*', :html] 228 | 229 | # The default HTTP method used to sign out a resource. Default is :delete. 230 | config.sign_out_via = :delete 231 | 232 | # ==> OmniAuth 233 | # Add a new OmniAuth provider. Check the wiki for more information on setting 234 | # up on your models and hooks. 235 | # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo' 236 | 237 | # ==> Warden configuration 238 | # If you want to use other strategies, that are not supported by Devise, or 239 | # change the failure app, you can configure them inside the config.warden block. 240 | # 241 | # config.warden do |manager| 242 | # manager.intercept_401 = false 243 | # manager.default_strategies(scope: :user).unshift :some_external_strategy 244 | # end 245 | 246 | # ==> Mountable engine configurations 247 | # When using Devise inside an engine, let's call it `MyEngine`, and this engine 248 | # is mountable, there are some extra configurations to be taken into account. 249 | # The following options are available, assuming the engine is mounted as: 250 | # 251 | # mount MyEngine, at: '/my_engine' 252 | # 253 | # The router that invoked `devise_for`, in the example above, would be: 254 | # config.router_name = :my_engine 255 | # 256 | # When using omniauth, Devise cannot automatically set Omniauth path, 257 | # so you need to do it manually. For the users scope, it would be: 258 | # config.omniauth_path_prefix = '/my_engine/users/auth' 259 | end 260 | -------------------------------------------------------------------------------- /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/locale.rb: -------------------------------------------------------------------------------- 1 | # -*- encoding : utf-8 -*- 2 | I18n.load_path += Dir[Rails.root.join('locales', '*.{yml}')] 3 | -------------------------------------------------------------------------------- /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/rails_admin.rb: -------------------------------------------------------------------------------- 1 | RailsAdmin.config do |config| 2 | 3 | ### Popular gems integration 4 | 5 | ## == Devise == 6 | config.authenticate_with do 7 | warden.authenticate! scope: :admin 8 | end 9 | config.current_user_method(&:current_admin) 10 | 11 | ## == Cancan == 12 | # config.authorize_with :cancan 13 | 14 | ## == Pundit == 15 | # config.authorize_with :pundit 16 | 17 | ## == PaperTrail == 18 | # config.audit_with :paper_trail, 'User', 'PaperTrail::Version' # PaperTrail >= 3.0.0 19 | 20 | ### More at https://github.com/sferik/rails_admin/wiki/Base-configuration 21 | 22 | config.actions do 23 | dashboard # mandatory 24 | index # mandatory 25 | new 26 | export 27 | bulk_delete 28 | show 29 | edit 30 | delete 31 | show_in_app 32 | 33 | ## With an audit adapter, you can add: 34 | # history_index 35 | # history_show 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | Rails.application.config.session_store :cookie_store, key: '_session' 4 | -------------------------------------------------------------------------------- /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] if respond_to?(:wrap_parameters) 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 = false 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 | omniauth_callbacks: 27 | failure: "Could not authenticate you from %{kind} because \"%{reason}\"." 28 | success: "Successfully authenticated from %{kind} account." 29 | passwords: 30 | no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided." 31 | send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes." 32 | send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes." 33 | updated: "Your password has been changed successfully. You are now signed in." 34 | updated_not_active: "Your password has been changed successfully." 35 | registrations: 36 | destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon." 37 | signed_up: "Welcome! You have signed up successfully." 38 | signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated." 39 | signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked." 40 | signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account." 41 | update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirm link to confirm your new email address." 42 | updated: "Your account has been updated successfully." 43 | sessions: 44 | signed_in: "Signed in successfully." 45 | signed_out: "Signed out successfully." 46 | already_signed_out: "Signed out successfully." 47 | unlocks: 48 | send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes." 49 | send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes." 50 | unlocked: "Your account has been unlocked successfully. Please sign in to continue." 51 | errors: 52 | messages: 53 | already_confirmed: "was already confirmed, please try signing in" 54 | confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one" 55 | expired: "has expired, please request a new one" 56 | not_found: "not found" 57 | not_locked: "was not locked" 58 | not_saved: 59 | one: "1 error prohibited this %{resource} from being saved:" 60 | other: "%{count} errors prohibited this %{resource} from being saved:" 61 | -------------------------------------------------------------------------------- /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/routes.rb: -------------------------------------------------------------------------------- 1 | 2 | Rails.application.routes.draw do 3 | 4 | devise_for :admins, :controllers => { :sessions => 'admin/sessions', :passwords => 'admin/passwords' } 5 | mount RailsAdmin::Engine => '/admin', as: 'rails_admin' 6 | 7 | root 'home#index' 8 | 9 | namespace :api, defaults: { format: :json } do 10 | get 'hotels', to: 'hotels#index' 11 | get 'hotels/:id', to: 'hotels#find' 12 | put 'hotels/:id', to: 'hotels#update' 13 | delete 'hotels/:id', to: 'hotels#destroy' 14 | post 'hotels', to: 'hotels#create' 15 | get 'search', to: 'hotels#search' 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /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 `rake 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: 71dd0d5afe01b0656692ef516d83f01beae115c997b8ad9eb388b163b6f09698968443a18f16b70cc6b906709fd6160c968477a51a9836bf42678251cf2ab688 15 | 16 | test: 17 | secret_key_base: ef9d797e72b9d19df1c86ff6fab51e218c8a9caf9bd67575c2b8dcfee606f067528528339e6a830f7c4e4ea13e1ac85964c493af439c1890c0df10476655606b 18 | 19 | # Do not keep production secrets in the repository, 20 | # instead read values from the environment. 21 | production: 22 | secret_key_base: tadebrinks 23 | -------------------------------------------------------------------------------- /contributors.txt: -------------------------------------------------------------------------------- 1 | zekitow 2 | -------------------------------------------------------------------------------- /db/migrate/20160218131223_devise_create_admins.rb: -------------------------------------------------------------------------------- 1 | class DeviseCreateAdmins < ActiveRecord::Migration 2 | def change 3 | create_table(:admins) do |t| 4 | ## Database authenticatable 5 | t.string :email, null: false, default: "" 6 | t.string :encrypted_password, null: false, default: "" 7 | 8 | ## Recoverable 9 | t.string :reset_password_token 10 | t.datetime :reset_password_sent_at 11 | 12 | ## Rememberable 13 | t.datetime :remember_created_at 14 | 15 | ## Trackable 16 | t.integer :sign_in_count, default: 0, null: false 17 | t.datetime :current_sign_in_at 18 | t.datetime :last_sign_in_at 19 | t.string :current_sign_in_ip 20 | t.string :last_sign_in_ip 21 | 22 | ## Confirmable 23 | # t.string :confirmation_token 24 | # t.datetime :confirmed_at 25 | # t.datetime :confirmation_sent_at 26 | # t.string :unconfirmed_email # Only if using reconfirmable 27 | 28 | ## Lockable 29 | # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts 30 | # t.string :unlock_token # Only if unlock strategy is :email or :both 31 | # t.datetime :locked_at 32 | 33 | 34 | t.timestamps 35 | end 36 | 37 | add_index :admins, :email, unique: true 38 | add_index :admins, :reset_password_token, unique: true 39 | # add_index :admins, :confirmation_token, unique: true 40 | # add_index :admins, :unlock_token, unique: true 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /db/migrate/20160308164308_create_hotels.rb: -------------------------------------------------------------------------------- 1 | class CreateHotels < ActiveRecord::Migration 2 | def change 3 | create_table :hotels do |t| 4 | t.string :name 5 | t.string :address 6 | t.integer :star_rating 7 | t.string :accomodation_type 8 | 9 | t.timestamps null: false 10 | end 11 | add_index :hotels, :name 12 | add_index :hotels, :address 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/schema.rb: -------------------------------------------------------------------------------- 1 | # encoding: UTF-8 2 | # This file is auto-generated from the current state of the database. Instead 3 | # of editing this file, please use the migrations feature of Active Record to 4 | # incrementally modify your database, and then regenerate this schema definition. 5 | # 6 | # Note that this schema.rb definition is the authoritative source for your 7 | # database schema. If you need to create the application database on another 8 | # system, you should be using db:schema:load, not running all the migrations 9 | # from scratch. The latter is a flawed and unsustainable approach (the more migrations 10 | # you'll amass, the slower it'll run and the greater likelihood for issues). 11 | # 12 | # It's strongly recommended that you check this file into your version control system. 13 | 14 | ActiveRecord::Schema.define(version: 20160308164308) do 15 | 16 | # These are extensions that must be enabled in order to support this database 17 | enable_extension "plpgsql" 18 | 19 | create_table "admins", force: :cascade do |t| 20 | t.string "email", default: "", null: false 21 | t.string "encrypted_password", default: "", null: false 22 | t.string "reset_password_token" 23 | t.datetime "reset_password_sent_at" 24 | t.datetime "remember_created_at" 25 | t.integer "sign_in_count", default: 0, null: false 26 | t.datetime "current_sign_in_at" 27 | t.datetime "last_sign_in_at" 28 | t.string "current_sign_in_ip" 29 | t.string "last_sign_in_ip" 30 | t.datetime "created_at" 31 | t.datetime "updated_at" 32 | end 33 | 34 | add_index "admins", ["email"], name: "index_admins_on_email", unique: true, using: :btree 35 | add_index "admins", ["reset_password_token"], name: "index_admins_on_reset_password_token", unique: true, using: :btree 36 | 37 | create_table "hotels", force: :cascade do |t| 38 | t.string "name" 39 | t.string "address" 40 | t.integer "star_rating" 41 | t.string "accomodation_type" 42 | t.datetime "created_at", null: false 43 | t.datetime "updated_at", null: false 44 | end 45 | 46 | add_index "hotels", ["address"], name: "index_hotels_on_address", using: :btree 47 | add_index "hotels", ["name"], name: "index_hotels_on_name", using: :btree 48 | 49 | end 50 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). 3 | # 4 | # Examples: 5 | # 6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }]) 7 | # Mayor.create(name: 'Emanuel', city: cities.first) 8 | 9 | Admin.first_or_create( 10 | email: 'admin@example.com', 11 | password: 'password', 12 | password_confirmation: 'password') 13 | 14 | Hotel.first_or_create(name: 'Hotel 1', address: 'Address 1', star_rating: 5.0, accomodation_type: 'Hotel') -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zekitow/rails-api-and-angularjs/46f50e9d6c80071dd89f2c7557c80e3ced8e9003/lib/assets/.keep -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zekitow/rails-api-and-angularjs/46f50e9d6c80071dd89f2c7557c80e3ced8e9003/lib/tasks/.keep -------------------------------------------------------------------------------- /log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zekitow/rails-api-and-angularjs/46f50e9d6c80071dd89f2c7557c80e3ced8e9003/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/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zekitow/rails-api-and-angularjs/46f50e9d6c80071dd89f2c7557c80e3ced8e9003/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Hotels Client 8 | 9 | 10 | 11 | 12 | 25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /public/js/app.js: -------------------------------------------------------------------------------- 1 | angular.module('hotelApp',['ui.router','ngResource','hotelApp.controllers','hotelApp.services']); 2 | 3 | angular.module('hotelApp').config(function($stateProvider, $httpProvider) { 4 | 5 | $stateProvider.state('hotels', { 6 | url: '/hotels', 7 | templateUrl: '/partials/index.html', 8 | controller: 'ListController' 9 | 10 | }).state('show', { 11 | url: '/hotels/:id/show', 12 | templateUrl: '/partials/show.html', 13 | controller: 'ShowController' 14 | 15 | }).state('newHotel', { 16 | url: '/hotels/new', 17 | templateUrl: '/partials/new.html', 18 | controller: 'CreateController' 19 | 20 | }).state('edit', { 21 | url: '/hotels/:id/edit', 22 | templateUrl: '/partials/edit.html', 23 | controller: 'EditController' 24 | 25 | 26 | }).state('search', { 27 | url: '/search', 28 | templateUrl: '/partials/search.html', 29 | controller: 'SearchController' 30 | 31 | }); 32 | 33 | }).run(function($state){ 34 | $state.go('hotels'); 35 | }); -------------------------------------------------------------------------------- /public/js/controllers.js: -------------------------------------------------------------------------------- 1 | angular.module('hotelApp.controllers',[]).controller('ListController', function($scope, $state, confirmDialog, $window, Hotel) { 2 | 3 | $scope.hotels = Hotel.query(); 4 | 5 | $scope.remove = function(hotel) { 6 | if(confirmDialog.show('Are you sure?')) { 7 | hotel.$remove(function() { 8 | $window.location.href='/'; 9 | }); 10 | } 11 | } 12 | 13 | }) 14 | 15 | .controller('ShowController',function($scope, $stateParams, Hotel) { 16 | $scope.hotel = Hotel.get({ id: $stateParams.id }); 17 | 18 | }) 19 | 20 | .controller('CreateController',function($scope, $state, $stateParams, Hotel) { 21 | $scope.hotel = new Hotel(); 22 | 23 | $scope.add = function() { 24 | $scope.hotel.$save(function() { 25 | $state.go('hotels'); 26 | }); 27 | } 28 | 29 | }).controller('EditController',function($scope, $state, $stateParams, Hotel) { 30 | 31 | $scope.update = function() { 32 | $scope.hotel.$update(function() { 33 | $state.go('hotels'); 34 | }); 35 | }; 36 | 37 | $scope.loadAll = function() { 38 | $scope.hotel = Hotel.get({ id: $stateParams.id }); 39 | }; 40 | $scope.loadAll(); 41 | }) 42 | 43 | .controller('SearchController',function($scope, $stateParams, Hotel) { 44 | // $scope.hotels = []; 45 | 46 | $scope.searchNow = function() { 47 | // if ($scope.q.length > 3) { 48 | $scope.hotels = Hotel.search({ q: $scope.q }); 49 | // } 50 | } 51 | 52 | }); -------------------------------------------------------------------------------- /public/js/services.js: -------------------------------------------------------------------------------- 1 | angular.module('hotelApp.services',[]).factory('Hotel',function($resource) { 2 | 3 | return $resource('http://localhost:3000/api/hotels/:id',{ id:'@id' }, { 4 | update: { method: 'PUT' }, 5 | remove: { params: { id: '@id' }, method: 'DELETE' }, 6 | search: { url: 'http://localhost:3000/api/search', method: 'GET', isArray: true } 7 | }); 8 | }) 9 | 10 | 11 | .service('confirmDialog',function($window) { 12 | this.show = function(message) { 13 | return $window.confirm(message); 14 | } 15 | }); -------------------------------------------------------------------------------- /public/lib/angular-resource.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | AngularJS v1.4.5 3 | (c) 2010-2015 Google, Inc. http://angularjs.org 4 | License: MIT 5 | */ 6 | (function(I,c,B){'use strict';function D(s,e){e=e||{};c.forEach(e,function(c,k){delete e[k]});for(var k in s)!s.hasOwnProperty(k)||"$"===k.charAt(0)&&"$"===k.charAt(1)||(e[k]=s[k]);return e}var x=c.$$minErr("$resource"),C=/^(\.[a-zA-Z_$@][0-9a-zA-Z_$@]*)+$/;c.module("ngResource",["ng"]).provider("$resource",function(){var s=/^https?:\/\/[^\/]*/,e=this;this.defaults={stripTrailingSlashes:!0,actions:{get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}}}; 7 | this.$get=["$http","$q",function(k,F){function v(c,h){this.template=c;this.defaults=r({},e.defaults,h);this.urlParams={}}function y(l,h,p,f){function d(b,q){var d={};q=r({},h,q);t(q,function(a,q){w(a)&&(a=a());var m;if(a&&a.charAt&&"@"==a.charAt(0)){m=b;var c=a.substr(1);if(null==c||""===c||"hasOwnProperty"===c||!C.test("."+c))throw x("badmember",c);for(var c=c.split("."),g=0,h=c.length;g>>0,d=Number(arguments[2])||0;for(d=0>d?Math.ceil(d):Math.floor(d),0>d&&(d+=c);c>d;d++)if(d in a&&a[d]===b)return d;return-1}function h(a,b,c,d){var e,h=f(c,d),i={},j=[];for(var k in h)if(h[k].params&&h[k].params.length){e=h[k].params;for(var l in e)g(j,e[l])>=0||(j.push(e[l]),i[e[l]]=a[e[l]])}return I({},i,b)}function i(a,b){var c={};return H(a,function(a){var d=b[a];c[a]=null!=d?String(d):null}),c}function j(a,b,c){if(!c){c=[];for(var d in a)c.push(d)}for(var e=0;e "));if(o[c]=d,E(a))m.push(c,[function(){return b.get(a)}],h);else{var e=b.annotate(a);H(e,function(a){a!==c&&g.hasOwnProperty(a)&&k(g[a],a)}),m.push(c,a,e)}n.pop(),o[c]=f}}function l(a){return F(a)&&a.then&&a.$$promises}if(!F(g))throw new Error("'invocables' must be an object");var m=[],n=[],o={};return H(g,k),g=n=o=null,function(d,f,g){function h(){--s||(t||e(r,f.$$values),p.$$values=r,p.$$promises=!0,o.resolve(r))}function k(a){p.$$failure=a,o.reject(a)}function n(c,e,f){function i(a){l.reject(a),k(a)}function j(){if(!C(p.$$failure))try{l.resolve(b.invoke(e,g,r)),l.promise.then(function(a){r[c]=a,h()},i)}catch(a){i(a)}}var l=a.defer(),m=0;H(f,function(a){q.hasOwnProperty(a)&&!d.hasOwnProperty(a)&&(m++,q[a].then(function(b){r[a]=b,--m||j()},i))}),m||j(),q[c]=l.promise}if(l(d)&&g===c&&(g=f,f=d,d=null),d){if(!F(d))throw new Error("'locals' must be an object")}else d=i;if(f){if(!l(f))throw new Error("'parent' must be a promise returned by $resolve.resolve()")}else f=j;var o=a.defer(),p=o.promise,q=p.$$promises={},r=I({},d),s=1+m.length/3,t=!1;if(C(f.$$failure))return k(f.$$failure),p;f.$$values?(t=e(r,f.$$values),h()):(I(q,f.$$promises),f.then(h,k));for(var u=0,v=m.length;v>u;u+=3)d.hasOwnProperty(m[u])?h():n(m[u],m[u+1],m[u+2]);return p}},this.resolve=function(a,b,c,d){return this.study(a)(b,c,d)}}function m(a,b,c){this.fromConfig=function(a,b,c){return C(a.template)?this.fromString(a.template,b):C(a.templateUrl)?this.fromUrl(a.templateUrl,b):C(a.templateProvider)?this.fromProvider(a.templateProvider,b,c):null},this.fromString=function(a,b){return D(a)?a(b):a},this.fromUrl=function(c,d){return D(c)&&(c=c(d)),null==c?null:a.get(c,{cache:b}).then(function(a){return a.data})},this.fromProvider=function(a,b,d){return c.invoke(a,null,d||{params:b})}}function n(a){function b(b){if(!/^\w+(-+\w+)*$/.test(b))throw new Error("Invalid parameter name '"+b+"' in pattern '"+a+"'");if(f[b])throw new Error("Duplicate parameter name '"+b+"' in pattern '"+a+"'");f[b]=!0,j.push(b)}function c(a){return a.replace(/[\\\[\]\^$*+?.()|{}]/g,"\\$&")}var d,e=/([:*])(\w+)|\{(\w+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,f={},g="^",h=0,i=this.segments=[],j=this.params=[];this.source=a;for(var k,l,m;(d=e.exec(a))&&(k=d[2]||d[3],l=d[4]||("*"==d[1]?".*":"[^/]*"),m=a.substring(h,d.index),!(m.indexOf("?")>=0));)g+=c(m)+"("+l+")",b(k),i.push(m),h=e.lastIndex;m=a.substring(h);var n=m.indexOf("?");if(n>=0){var o=this.sourceSearch=m.substring(n);m=m.substring(0,n),this.sourcePath=a.substring(0,h+n),H(o.substring(1).split(/[&?]/),b)}else this.sourcePath=a,this.sourceSearch="";g+=c(m)+"$",i.push(m),this.regexp=new RegExp(g),this.prefix=i[0]}function o(){this.compile=function(a){return new n(a)},this.isMatcher=function(a){return F(a)&&D(a.exec)&&D(a.format)&&D(a.concat)},this.$get=function(){return this}}function p(a){function b(a){var b=/^\^((?:\\[^a-zA-Z0-9]|[^\\\[\]\^$*+?.()|{}]+)*)/.exec(a.source);return null!=b?b[1].replace(/\\(.)/g,"$1"):""}function c(a,b){return a.replace(/\$(\$|\d{1,2})/,function(a,c){return b["$"===c?0:Number(c)]})}function d(a,b,c){if(!c)return!1;var d=a.invoke(b,b,{$match:c});return C(d)?d:!0}var e=[],f=null;this.rule=function(a){if(!D(a))throw new Error("'rule' must be a function");return e.push(a),this},this.otherwise=function(a){if(E(a)){var b=a;a=function(){return b}}else if(!D(a))throw new Error("'rule' must be a function");return f=a,this},this.when=function(e,f){var g,h=E(f);if(E(e)&&(e=a.compile(e)),!h&&!D(f)&&!G(f))throw new Error("invalid 'handler' in when()");var i={matcher:function(b,c){return h&&(g=a.compile(c),c=["$match",function(a){return g.format(a)}]),I(function(a,e){return d(a,c,b.exec(e.path(),e.search()))},{prefix:E(b.prefix)?b.prefix:""})},regex:function(a,e){if(a.global||a.sticky)throw new Error("when() RegExp must not be global or sticky");return h&&(g=e,e=["$match",function(a){return c(g,a)}]),I(function(b,c){return d(b,e,a.exec(c.path()))},{prefix:b(a)})}},j={matcher:a.isMatcher(e),regex:e instanceof RegExp};for(var k in j)if(j[k])return this.rule(i[k](e,f));throw new Error("invalid 'what' in when()")},this.$get=["$location","$rootScope","$injector",function(a,b,c){function d(b){function d(b){var d=b(c,a);return d?(E(d)&&a.replace().url(d),!0):!1}if(!b||!b.defaultPrevented){var g,h=e.length;for(g=0;h>g;g++)if(d(e[g]))return;f&&d(f)}}return b.$on("$locationChangeSuccess",d),{sync:function(){d()}}}]}function q(a,e,f){function g(a){return 0===a.indexOf(".")||0===a.indexOf("^")}function l(a,b){var d=E(a),e=d?a:a.name,f=g(e);if(f){if(!b)throw new Error("No reference point given for path '"+e+"'");for(var h=e.split("."),i=0,j=h.length,k=b;j>i;i++)if(""!==h[i]||0!==i){if("^"!==h[i])break;if(!k.parent)throw new Error("Path '"+e+"' not valid for state '"+b.name+"'");k=k.parent}else k=b;h=h.slice(i).join("."),e=k.name+(k.name&&h?".":"")+h}var l=w[e];return!l||!d&&(d||l!==a&&l.self!==a)?c:l}function m(a,b){x[a]||(x[a]=[]),x[a].push(b)}function n(b){b=d(b,{self:b,resolve:b.resolve||{},toString:function(){return this.name}});var c=b.name;if(!E(c)||c.indexOf("@")>=0)throw new Error("State must have a valid name");if(w.hasOwnProperty(c))throw new Error("State '"+c+"'' is already defined");var e=-1!==c.indexOf(".")?c.substring(0,c.lastIndexOf(".")):E(b.parent)?b.parent:"";if(e&&!w[e])return m(e,b.self);for(var f in z)D(z[f])&&(b[f]=z[f](b,z.$delegates[f]));if(w[c]=b,!b[y]&&b.url&&a.when(b.url,["$match","$stateParams",function(a,c){v.$current.navigable==b&&j(a,c)||v.transitionTo(b,a,{location:!1})}]),x[c])for(var g=0;g-1}function p(a){var b=a.split("."),c=v.$current.name.split(".");if("**"===b[0]&&(c=c.slice(c.indexOf(b[1])),c.unshift("**")),"**"===b[b.length-1]&&(c.splice(c.indexOf(b[b.length-2])+1,Number.MAX_VALUE),c.push("**")),b.length!=c.length)return!1;for(var d=0,e=b.length;e>d;d++)"*"===b[d]&&(c[d]="*");return c.join("")===b.join("")}function q(a,b){return E(a)&&!C(b)?z[a]:D(b)&&E(a)?(z[a]&&!z.$delegates[a]&&(z.$delegates[a]=z[a]),z[a]=b,this):this}function r(a,b){return F(a)?b=a:b.name=a,n(b),this}function s(a,e,g,m,n,q,r,s,x){function z(){r.url()!==M&&(r.url(M),r.replace())}function A(a,c,d,f,h){var i=d?c:k(a.params,c),j={$stateParams:i};h.resolve=n.resolve(a.resolve,j,h.resolve,a);var l=[h.resolve.then(function(a){h.globals=a})];return f&&l.push(f),H(a.views,function(c,d){var e=c.resolve&&c.resolve!==a.resolve?c.resolve:{};e.$template=[function(){return g.load(d,{view:c,locals:j,params:i,notify:!1})||""}],l.push(n.resolve(e,j,h.resolve,a).then(function(f){if(D(c.controllerProvider)||G(c.controllerProvider)){var g=b.extend({},e,j);f.$$controller=m.invoke(c.controllerProvider,null,g)}else f.$$controller=c.controller;f.$$state=a,f.$$controllerAs=c.controllerAs,h[d]=f}))}),e.all(l).then(function(){return h})}var B=e.reject(new Error("transition superseded")),F=e.reject(new Error("transition prevented")),K=e.reject(new Error("transition aborted")),L=e.reject(new Error("transition failed")),M=r.url(),N=x.baseHref();return u.locals={resolve:null,globals:{$stateParams:{}}},v={params:{},current:u.self,$current:u,transition:null},v.reload=function(){v.transitionTo(v.current,q,{reload:!0,inherit:!1,notify:!1})},v.go=function(a,b,c){return this.transitionTo(a,b,I({inherit:!0,relative:v.$current},c))},v.transitionTo=function(b,c,f){c=c||{},f=I({location:!0,inherit:!1,relative:null,notify:!0,reload:!1,$retry:!1},f||{});var g,k=v.$current,n=v.params,o=k.path,p=l(b,f.relative);if(!C(p)){var s={to:b,toParams:c,options:f};if(g=a.$broadcast("$stateNotFound",s,k.self,n),g.defaultPrevented)return z(),K;if(g.retry){if(f.$retry)return z(),L;var w=v.transition=e.when(g.retry);return w.then(function(){return w!==v.transition?B:(s.options.$retry=!0,v.transitionTo(s.to,s.toParams,s.options))},function(){return K}),z(),w}if(b=s.to,c=s.toParams,f=s.options,p=l(b,f.relative),!C(p)){if(f.relative)throw new Error("Could not resolve '"+b+"' from state '"+f.relative+"'");throw new Error("No such state '"+b+"'")}}if(p[y])throw new Error("Cannot transition to abstract state '"+b+"'");f.inherit&&(c=h(q,c||{},v.$current,p)),b=p;var x,D,E=b.path,G=u.locals,H=[];for(x=0,D=E[x];D&&D===o[x]&&j(c,n,D.ownParams)&&!f.reload;x++,D=E[x])G=H[x]=D.locals;if(t(b,k,G,f))return b.self.reloadOnSearch!==!1&&z(),v.transition=null,e.when(v.current);if(c=i(b.params,c||{}),f.notify&&(g=a.$broadcast("$stateChangeStart",b.self,c,k.self,n),g.defaultPrevented))return z(),F;for(var N=e.when(G),O=x;O=x;d--)g=o[d],g.self.onExit&&m.invoke(g.self.onExit,g.self,g.locals.globals),g.locals=null;for(d=x;d1||b.ctrlKey||b.metaKey||b.shiftKey||f.attr("target")||(c(function(){a.go(i.state,j,o)}),b.preventDefault())})}}}function y(a,b,c){return{restrict:"A",controller:["$scope","$element","$attrs",function(d,e,f){function g(){a.$current.self===i&&h()?e.addClass(l):e.removeClass(l)}function h(){return!k||j(k,b)}var i,k,l;l=c(f.uiSrefActive||"",!1)(d),this.$$setStateInfo=function(b,c){i=a.get(b,w(e)),k=c,g()},d.$on("$stateChangeSuccess",g)}]}}function z(a){return function(b){return a.is(b)}}function A(a){return function(b){return a.includes(b)}}function B(a,b){function e(a){this.locals=a.locals.globals,this.params=this.locals.$stateParams}function f(){this.locals=null,this.params=null}function g(c,g){if(null!=g.redirectTo){var h,j=g.redirectTo;if(E(j))h=j;else{if(!D(j))throw new Error("Invalid 'redirectTo' in when()");h=function(a,b){return j(a,b.path(),b.search())}}b.when(c,h)}else a.state(d(g,{parent:null,name:"route:"+encodeURIComponent(c),url:c,onEnter:e,onExit:f}));return i.push(g),this}function h(a,b,d){function e(a){return""!==a.name?a:c}var f={routes:i,params:d,current:c};return b.$on("$stateChangeStart",function(a,c,d,f){b.$broadcast("$routeChangeStart",e(c),e(f))}),b.$on("$stateChangeSuccess",function(a,c,d,g){f.current=e(c),b.$broadcast("$routeChangeSuccess",e(c),e(g)),J(d,f.params)}),b.$on("$stateChangeError",function(a,c,d,f,g,h){b.$broadcast("$routeChangeError",e(c),e(f),h)}),f}var i=[];e.$inject=["$$state"],this.when=g,this.$get=h,h.$inject=["$state","$rootScope","$routeParams"]}var C=b.isDefined,D=b.isFunction,E=b.isString,F=b.isObject,G=b.isArray,H=b.forEach,I=b.extend,J=b.copy;b.module("ui.router.util",["ng"]),b.module("ui.router.router",["ui.router.util"]),b.module("ui.router.state",["ui.router.router","ui.router.util"]),b.module("ui.router",["ui.router.state"]),b.module("ui.router.compat",["ui.router"]),l.$inject=["$q","$injector"],b.module("ui.router.util").service("$resolve",l),m.$inject=["$http","$templateCache","$injector"],b.module("ui.router.util").service("$templateFactory",m),n.prototype.concat=function(a){return new n(this.sourcePath+a+this.sourceSearch)},n.prototype.toString=function(){return this.source},n.prototype.exec=function(a,b){var c=this.regexp.exec(a);if(!c)return null;var d,e=this.params,f=e.length,g=this.segments.length-1,h={};if(g!==c.length-1)throw new Error("Unbalanced capture group in route '"+this.source+"'");for(d=0;g>d;d++)h[e[d]]=c[d+1];for(;f>d;d++)h[e[d]]=b[e[d]];return h},n.prototype.parameters=function(){return this.params},n.prototype.format=function(a){var b=this.segments,c=this.params;if(!a)return b.join("");var d,e,f,g=b.length-1,h=c.length,i=b[0];for(d=0;g>d;d++)f=a[c[d]],null!=f&&(i+=encodeURIComponent(f)),i+=b[d+1];for(;h>d;d++)f=a[c[d]],null!=f&&(i+=(e?"&":"?")+c[d]+"="+encodeURIComponent(f),e=!0);return i},b.module("ui.router.util").provider("$urlMatcherFactory",o),p.$inject=["$urlMatcherFactoryProvider"],b.module("ui.router.router").provider("$urlRouter",p),q.$inject=["$urlRouterProvider","$urlMatcherFactoryProvider","$locationProvider"],b.module("ui.router.state").value("$stateParams",{}).provider("$state",q),r.$inject=[],b.module("ui.router.state").provider("$view",r),b.module("ui.router.state").provider("$uiViewScroll",s),t.$inject=["$state","$injector","$uiViewScroll"],u.$inject=["$compile","$controller","$state"],b.module("ui.router.state").directive("uiView",t),b.module("ui.router.state").directive("uiView",u),x.$inject=["$state","$timeout"],y.$inject=["$state","$stateParams","$interpolate"],b.module("ui.router.state").directive("uiSref",x).directive("uiSrefActive",y),z.$inject=["$state"],A.$inject=["$state"],b.module("ui.router.state").filter("isState",z).filter("includedByState",A),B.$inject=["$stateProvider","$urlRouterProvider"],b.module("ui.router.compat").provider("$route",B).directive("ngView",t)}(window,window.angular); -------------------------------------------------------------------------------- /public/partials/_form.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 7 | 8 |
9 |
10 |
11 | 12 |
13 | 14 | 17 | 18 |
19 |
20 |
21 | 22 |
23 | 24 | 27 | 28 |
29 |
30 | 31 |
32 | 33 |
34 | 35 | 38 | 39 |
40 |
41 | 42 |
43 |
44 | Back 45 | 46 |
47 |
-------------------------------------------------------------------------------- /public/partials/edit.html: -------------------------------------------------------------------------------- 1 |

Edit: {{ hotel.name }}

2 |
3 |
4 |
-------------------------------------------------------------------------------- /public/partials/index.html: -------------------------------------------------------------------------------- 1 | 2 |

Hotels

3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 22 | 23 |
#NameAddressRatingAccomodation Type
{{hotel.id}}{{hotel.name}}{{hotel.address}}{{hotel.star_rating}}{{hotel.accomodation_type}} 19 | Edit 20 | Delete 21 |
24 | 25 | New Hotel -------------------------------------------------------------------------------- /public/partials/new.html: -------------------------------------------------------------------------------- 1 |

New Hotel

2 |
3 |
4 |
-------------------------------------------------------------------------------- /public/partials/search.html: -------------------------------------------------------------------------------- 1 |

Search

2 | 3 |
4 | 5 | 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
{{hotel.id}}{{hotel.name}}{{hotel.address}}{{hotel.star_rating}}{{hotel.accomodation_type}}
17 | -------------------------------------------------------------------------------- /public/partials/show.html: -------------------------------------------------------------------------------- 1 |

Details of {{ hotel.name }}

2 | 3 |

Name: {{ hotel.name }}

4 |

Address: {{ hotel.address }}

5 |

Rating: {{ hotel.star_rating }}

6 | 7 |

Accomodation Type: {{ hotel.accomodation_type }}

8 | 9 | 10 | Back 11 | -------------------------------------------------------------------------------- /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/controllers/api/hotels_controller_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | describe Api::HotelsController, type: :api do 4 | 5 | context 'GET /api/hotels' do 6 | subject { get '/api/hotels' } 7 | 8 | context 'when do not have hotels' do 9 | it { expect(subject.status).to eql(200) } 10 | it { expect(JSON.parse(subject.body)).to be_empty } 11 | end 12 | 13 | context 'when have two hotels' do 14 | before(:each) { FactoryGirl.create_list(:hotel, 2) } 15 | 16 | it { expect(subject.status).to eql(200) } 17 | it { expect(subject).to match_response_schema('hotels') } 18 | end 19 | 20 | end 21 | 22 | context 'POST /api/hotels' do 23 | subject { post '/api/hotels', request } 24 | 25 | context 'without required fields' do 26 | let(:request) { {} } 27 | 28 | it { expect(subject.status).to eql(422) } 29 | it { expect(subject).to match_response_schema('missing_required_fields') } 30 | end 31 | 32 | context 'with required fields' do 33 | let(:request) { { hotel: { name: 'name', address: 'address', star_rating: '3.5', accomodation_type: 'accomodation_type' } } } 34 | 35 | it { expect(subject.status).to eql(201) } 36 | it { expect(subject).to match_response_schema('hotel') } 37 | end 38 | 39 | end 40 | 41 | context 'GET /api/hotels/1' do 42 | 43 | subject { get '/api/hotels/1' } 44 | 45 | context 'when hotel does not exists' do 46 | 47 | it { expect(subject.status).to eql(404) } 48 | it { expect(subject.body).to be_blank } 49 | end 50 | 51 | context 'when hotel exists' do 52 | before(:each) { FactoryGirl.create(:hotel, id: 1) } 53 | 54 | it { expect(subject.status).to eql(200) } 55 | it { expect(subject).to match_response_schema('hotel') } 56 | end 57 | 58 | end 59 | 60 | context 'PUT /api/hotels/1' do 61 | let(:request) { { hotel: { id: 1, name: 'name', address: 'address', star_rating: '3.5', accomodation_type: 'accomodation_type' } } } 62 | 63 | subject { put '/api/hotels/1', request } 64 | 65 | context 'when hotel does not exists' do 66 | it { expect(subject.status).to eql(404) } 67 | it { expect(subject.body).to be_blank } 68 | end 69 | 70 | context 'when hotel exists' do 71 | before(:each) { FactoryGirl.create(:hotel, id: 1) } 72 | 73 | it { expect(subject.status).to eql(204) } 74 | it { expect(subject.body).to be_blank } 75 | end 76 | 77 | end 78 | 79 | 80 | context 'Remove and Hotel' do 81 | subject { delete '/api/hotels/1', request } 82 | 83 | let(:request) { { hotel: { id: 1 } } } 84 | 85 | context 'when hotel does not exists' do 86 | it { expect(subject.status).to eql(404) } 87 | it { expect(subject.body).to be_blank } 88 | end 89 | 90 | context 'when hotel exists' do 91 | before(:each) { FactoryGirl.create(:hotel, id: 1) } 92 | 93 | it { expect(subject.status).to eql(204) } 94 | it { expect(subject.body).to be_blank } 95 | end 96 | end 97 | 98 | 99 | context 'Find Hotels by string' do 100 | subject { get '/api/search', request } 101 | 102 | before(:each) do 103 | FactoryGirl.create(:hotel, id: 1, name: 'Pitangueiras') 104 | FactoryGirl.create(:hotel, id: 2, address: 'R. Rocha Pombo, 160') 105 | end 106 | 107 | context 'when param are not sent' do 108 | let(:request) { { } } 109 | 110 | it { expect(subject.status).to eql(422) } 111 | it { expect(subject.body).to be_blank } 112 | end 113 | 114 | context 'when nothing matches' do 115 | let(:request) { { q: 'Unmatched text' } } 116 | 117 | it { expect(subject.status).to eql(200) } 118 | it { expect(JSON.parse(subject.body)).to be_empty } 119 | end 120 | 121 | context 'when name matches' do 122 | let(:request) { { q: 'Pitangueiras' } } 123 | 124 | it { expect(subject.status).to eql(200) } 125 | it { expect(subject).to match_response_schema('hotels') } 126 | it { expect(JSON.parse(subject.body).size).to eql(1) } 127 | end 128 | 129 | context 'when address matches' do 130 | let(:request) { { q: 'Rocha' } } 131 | 132 | it { expect(subject.status).to eql(200) } 133 | it { expect(subject).to match_response_schema('hotels') } 134 | it { expect(JSON.parse(subject.body).size).to eql(1) } 135 | end 136 | 137 | context 'when name and address matches' do 138 | let(:request) { { q: 'Royal' } } 139 | 140 | before(:each) do 141 | FactoryGirl.create(:hotel, name: 'Royal Atlântica') 142 | FactoryGirl.create(:hotel, address: 'Port Royal') 143 | end 144 | 145 | it { expect(subject.status).to eql(200) } 146 | it { expect(subject).to match_response_schema('hotels') } 147 | it { expect(JSON.parse(subject.body).size).to eql(2) } 148 | end 149 | end 150 | end -------------------------------------------------------------------------------- /spec/factories.rb: -------------------------------------------------------------------------------- 1 | FactoryGirl.define do 2 | factory :hotel do 3 | name 'Hotel 1' 4 | address 'Address 1' 5 | star_rating 5.0 6 | accomodation_type 'Hotel' 7 | end 8 | end -------------------------------------------------------------------------------- /spec/models/hotel_spec.rb: -------------------------------------------------------------------------------- 1 | require 'rails_helper' 2 | 3 | RSpec.describe Hotel, type: :model do 4 | 5 | describe 'validations' do 6 | it { should validate_presence_of(:name) } 7 | it { should validate_presence_of(:address) } 8 | it { should validate_presence_of(:star_rating) } 9 | it { should validate_numericality_of(:star_rating) } 10 | it { should validate_presence_of(:accomodation_type) } 11 | end 12 | end -------------------------------------------------------------------------------- /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 File.expand_path('../../config/environment', __FILE__) 4 | # Prevent database truncation if the environment is production 5 | abort("The Rails environment is running in production mode!") if Rails.env.production? 6 | require 'spec_helper' 7 | require 'rspec/rails' 8 | # require 'shoulda/matchers' 9 | # Add additional requires below this line. Rails is not loaded until this point! 10 | 11 | # Requires supporting ruby files with custom matchers and macros, etc, in 12 | # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are 13 | # run as spec files by default. This means that files in spec/support that end 14 | # in _spec.rb will both be required and run as specs, causing the specs to be 15 | # run twice. It is recommended that you do not name files matching this glob to 16 | # end with _spec.rb. You can configure this pattern with the --pattern 17 | # option on the command line or in ~/.rspec, .rspec or `.rspec-local`. 18 | # 19 | # The following line is provided for convenience purposes. It has the downside 20 | # of increasing the boot-up time by auto-requiring all files in the support 21 | # directory. Alternatively, in the individual `*_spec.rb` files, manually 22 | # require only the support files necessary. 23 | # 24 | # Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f } 25 | 26 | # Checks for pending migration and applies them before tests are run. 27 | # If you are not using ActiveRecord, you can remove this line. 28 | ActiveRecord::Migration.maintain_test_schema! 29 | 30 | RSpec.configure do |config| 31 | # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures 32 | config.fixture_path = "#{::Rails.root}/spec/fixtures" 33 | config.include FactoryGirl::Syntax::Methods 34 | 35 | # If you're not using ActiveRecord, or you'd prefer not to run each of your 36 | # examples within a transaction, remove the following line or assign false 37 | # instead of true. 38 | config.use_transactional_fixtures = true 39 | 40 | # RSpec Rails can automatically mix in different behaviours to your tests 41 | # based on their file location, for example enabling you to call `get` and 42 | # `post` in specs under `spec/controllers`. 43 | # 44 | # You can disable this behaviour by removing the line below, and instead 45 | # explicitly tag your specs with their type, e.g.: 46 | # 47 | # RSpec.describe UsersController, :type => :controller do 48 | # # ... 49 | # end 50 | # 51 | # The different available types are documented in the features, such as in 52 | # https://relishapp.com/rspec/rspec-rails/docs 53 | config.infer_spec_type_from_file_location! 54 | 55 | # Filter lines from Rails gems in backtraces. 56 | config.filter_rails_from_backtrace! 57 | # arbitrary gems may also be filtered via: 58 | # config.filter_gems_from_backtrace("gem name") 59 | Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} 60 | 61 | Shoulda::Matchers.configure do |config| 62 | config.integrate do |with| 63 | with.test_framework :rspec 64 | with.library :active_record 65 | with.library :active_model 66 | end 67 | end 68 | 69 | config.infer_spec_type_from_file_location! 70 | end 71 | -------------------------------------------------------------------------------- /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 4 | # this file to always be loaded, without a need to explicitly require it in any 5 | # files. 6 | # 7 | # Given that it is always loaded, you are encouraged to keep this file as 8 | # light-weight as possible. Requiring heavyweight dependencies from this file 9 | # will add to the boot time of your test suite on EVERY test run, even for an 10 | # individual file that may not need all of that loaded. Instead, consider making 11 | # a separate helper file that requires the additional dependencies and performs 12 | # the additional setup, and require it from the spec files that actually need 13 | # it. 14 | # 15 | # The `.rspec` file also contains a few flags that are not defaults but that 16 | # users commonly want. 17 | # 18 | # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration 19 | RSpec.configure do |config| 20 | config.expect_with :rspec do |expectations| 21 | expectations.include_chain_clauses_in_custom_matcher_descriptions = true 22 | end 23 | 24 | 25 | config.mock_with :rspec do |mocks| 26 | mocks.verify_partial_doubles = true 27 | end 28 | end -------------------------------------------------------------------------------- /spec/support/api/schemas/hotel.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "object", 3 | "properties": { 4 | "id": { 5 | "type": "integer" 6 | }, 7 | "name": { 8 | "type": "string" 9 | }, 10 | "address": { 11 | "type": "string" 12 | }, 13 | "star_rating": { 14 | "type": "integer" 15 | }, 16 | "accomodation_type": { 17 | "type": "string" 18 | }, 19 | "created_at": { 20 | "type": "string" 21 | }, 22 | "updated_at": { 23 | "type": "string" 24 | } 25 | }, 26 | "required": [ 27 | "id", 28 | "name", 29 | "address", 30 | "star_rating", 31 | "accomodation_type", 32 | "created_at", 33 | "updated_at" 34 | ] 35 | } -------------------------------------------------------------------------------- /spec/support/api/schemas/hotels.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "array", 3 | "items": { 4 | "type": "object", 5 | "properties": { 6 | "id": { 7 | "type": "integer" 8 | }, 9 | "name": { 10 | "type": "string" 11 | }, 12 | "address": { 13 | "type": "string" 14 | }, 15 | "star_rating": { 16 | "type": "integer" 17 | }, 18 | "accomodation_type": { 19 | "type": "string" 20 | }, 21 | "created_at": { 22 | "type": "string" 23 | }, 24 | "updated_at": { 25 | "type": "string" 26 | } 27 | }, 28 | "required": [ 29 | "id", 30 | "name", 31 | "address", 32 | "star_rating", 33 | "accomodation_type", 34 | "created_at", 35 | "updated_at" 36 | ] 37 | }, 38 | "required": [ 39 | "0" 40 | ] 41 | } -------------------------------------------------------------------------------- /spec/support/api/schemas/missing_required_fields.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "object", 3 | "properties": { 4 | "errors": { 5 | "type": "object", 6 | "properties": { 7 | "name": { 8 | "type": "array", 9 | "items": { 10 | "type": "string" 11 | }, 12 | "required": [ 13 | "0" 14 | ] 15 | }, 16 | "address": { 17 | "type": "array", 18 | "items": { 19 | "type": "string" 20 | } 21 | }, 22 | "star_rating": { 23 | "type": "array", 24 | "items": [ 25 | { 26 | "type": "string" 27 | }, 28 | { 29 | "type": "string" 30 | } 31 | ] 32 | }, 33 | "accomodation_type": { 34 | "type": "array", 35 | "items": { 36 | "type": "string" 37 | } 38 | } 39 | }, 40 | "required": [ 41 | "name", 42 | "address", 43 | "star_rating", 44 | "accomodation_type" 45 | ] 46 | } 47 | }, 48 | "required": [ 49 | "errors" 50 | ] 51 | } -------------------------------------------------------------------------------- /spec/support/api_helper.rb: -------------------------------------------------------------------------------- 1 | module ApiHelper 2 | include Rack::Test::Methods 3 | 4 | def app 5 | Rails.application 6 | end 7 | end 8 | 9 | RSpec.configure do |config| 10 | config.include ApiHelper, type: :api 11 | end -------------------------------------------------------------------------------- /spec/support/api_schema_matcher.rb: -------------------------------------------------------------------------------- 1 | RSpec::Matchers.define :match_response_schema do |schema| 2 | match do |response| 3 | schema_directory = "#{Dir.pwd}/spec/support/api/schemas" 4 | schema_path = "#{schema_directory}/#{schema}.json" 5 | JSON::Validator.validate!(schema_path, response.body, strict: true) 6 | end 7 | end -------------------------------------------------------------------------------- /spec/support/database_cleaner.rb: -------------------------------------------------------------------------------- 1 | RSpec.configure do |config| 2 | 3 | config.before(:suite) do 4 | DatabaseCleaner.strategy = :transaction 5 | DatabaseCleaner.clean_with(:truncation) 6 | end 7 | 8 | # config.around(:each) do |example| 9 | # DatabaseCleaner.cleaning do 10 | # example.run 11 | # end 12 | # end 13 | 14 | end -------------------------------------------------------------------------------- /spec/support/factory_girl.rb: -------------------------------------------------------------------------------- 1 | RSpec.configure do |config| 2 | config.include FactoryGirl::Syntax::Methods 3 | end -------------------------------------------------------------------------------- /vendor/assets/javascripts/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zekitow/rails-api-and-angularjs/46f50e9d6c80071dd89f2c7557c80e3ced8e9003/vendor/assets/javascripts/.keep -------------------------------------------------------------------------------- /vendor/assets/stylesheets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zekitow/rails-api-and-angularjs/46f50e9d6c80071dd89f2c7557c80e3ced8e9003/vendor/assets/stylesheets/.keep --------------------------------------------------------------------------------