├── .gitignore ├── Gemfile ├── Gemfile.lock ├── README.md ├── Rakefile ├── app ├── controllers │ ├── application_controller.rb │ └── notes_controller.rb └── models │ ├── .keep │ └── note.rb ├── bin ├── bundle ├── rails └── rake ├── config.ru ├── config ├── application.rb ├── boot.rb ├── database.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── backtrace_silencers.rb │ ├── filter_parameter_logging.rb │ ├── inflections.rb │ ├── mime_types.rb │ ├── secret_token.rb │ ├── session_store.rb │ └── wrap_parameters.rb ├── locales │ └── en.yml └── routes.rb ├── db ├── migrate │ └── 20130723050253_create_notes.rb ├── schema.rb └── seeds.rb ├── doc └── layout.jpg ├── log └── .keep └── ngapp ├── .bowerrc ├── .editorconfig ├── .gitattributes ├── .gitignore ├── .jshintrc ├── Gruntfile.js ├── app ├── .buildignore ├── .htaccess ├── 404.html ├── favicon.ico ├── index.html ├── robots.txt ├── scripts │ ├── app.js │ └── controllers │ │ └── main.js ├── styles │ ├── bootstrap.css │ └── main.css └── views │ └── main.html ├── bower.json ├── karma-e2e.conf.js ├── karma.conf.js ├── libpeerconnection.log ├── package.json └── test ├── runner.html └── spec └── controllers └── main.js /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # 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 | public/ 19 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'rails', '4.0.0' 4 | 5 | # Heroku stuff 6 | gem 'rails_12factor', group: :production 7 | gem 'pg' 8 | gem 'sqlite3' 9 | 10 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder 11 | gem 'jbuilder', '~> 1.2' 12 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | actionmailer (4.0.0) 5 | actionpack (= 4.0.0) 6 | mail (~> 2.5.3) 7 | actionpack (4.0.0) 8 | activesupport (= 4.0.0) 9 | builder (~> 3.1.0) 10 | erubis (~> 2.7.0) 11 | rack (~> 1.5.2) 12 | rack-test (~> 0.6.2) 13 | activemodel (4.0.0) 14 | activesupport (= 4.0.0) 15 | builder (~> 3.1.0) 16 | activerecord (4.0.0) 17 | activemodel (= 4.0.0) 18 | activerecord-deprecated_finders (~> 1.0.2) 19 | activesupport (= 4.0.0) 20 | arel (~> 4.0.0) 21 | activerecord-deprecated_finders (1.0.3) 22 | activesupport (4.0.0) 23 | i18n (~> 0.6, >= 0.6.4) 24 | minitest (~> 4.2) 25 | multi_json (~> 1.3) 26 | thread_safe (~> 0.1) 27 | tzinfo (~> 0.3.37) 28 | arel (4.0.0) 29 | atomic (1.1.10) 30 | builder (3.1.4) 31 | erubis (2.7.0) 32 | hike (1.2.3) 33 | i18n (0.6.4) 34 | jbuilder (1.4.2) 35 | activesupport (>= 3.0.0) 36 | multi_json (>= 1.2.0) 37 | mail (2.5.4) 38 | mime-types (~> 1.16) 39 | treetop (~> 1.4.8) 40 | mime-types (1.23) 41 | minitest (4.7.5) 42 | multi_json (1.7.7) 43 | pg (0.16.0) 44 | polyglot (0.3.3) 45 | rack (1.5.2) 46 | rack-test (0.6.2) 47 | rack (>= 1.0) 48 | rails (4.0.0) 49 | actionmailer (= 4.0.0) 50 | actionpack (= 4.0.0) 51 | activerecord (= 4.0.0) 52 | activesupport (= 4.0.0) 53 | bundler (>= 1.3.0, < 2.0) 54 | railties (= 4.0.0) 55 | sprockets-rails (~> 2.0.0) 56 | rails_12factor (0.0.2) 57 | rails_serve_static_assets 58 | rails_stdout_logging 59 | rails_serve_static_assets (0.0.1) 60 | rails_stdout_logging (0.0.1) 61 | railties (4.0.0) 62 | actionpack (= 4.0.0) 63 | activesupport (= 4.0.0) 64 | rake (>= 0.8.7) 65 | thor (>= 0.18.1, < 2.0) 66 | rake (10.1.0) 67 | sprockets (2.10.0) 68 | hike (~> 1.2) 69 | multi_json (~> 1.0) 70 | rack (~> 1.0) 71 | tilt (~> 1.1, != 1.3.0) 72 | sprockets-rails (2.0.0) 73 | actionpack (>= 3.0) 74 | activesupport (>= 3.0) 75 | sprockets (~> 2.8) 76 | sqlite3 (1.3.7) 77 | thor (0.18.1) 78 | thread_safe (0.1.0) 79 | atomic 80 | tilt (1.4.1) 81 | treetop (1.4.14) 82 | polyglot 83 | polyglot (>= 0.3.1) 84 | tzinfo (0.3.37) 85 | 86 | PLATFORMS 87 | ruby 88 | 89 | DEPENDENCIES 90 | jbuilder (~> 1.2) 91 | pg 92 | rails (= 4.0.0) 93 | rails_12factor 94 | sqlite3 95 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A sample [AngularJS](http://angularjs.org) 2 | [app](https://github.com/EmmanuelOga/simple-angular-rails-app/) 3 | which uses [rails](http://rubyonrails.org/) as a backend. 4 | 5 | * [The running app](http://morning-chamber-9005.herokuapp.com/#/) on all its glory. 6 | * Github [repository](https://github.com/EmmanuelOga/simple-angular-rails-app/). 7 | 8 | While it is possible to include AngularJS as part of the rails assets, I 9 | think it is better to setup the angular code base on a 10 | standalone folder, leaving the rails app as a (more or less) 11 | isolated backend. 12 | 13 | There are several advantages to this setup: 14 | 15 | * Ability to manage the frontend app using 16 | [Yeoman](http://yeoman.io/) 17 | (including [generators](https://github.com/yeoman/generator-angular#readme)!). 18 | * No more questions about file layout: use rails layout for rails stuff, 19 | angular-generator layout for angular stuff. 20 | * Easily install external assets via [bower](http://bower.io/) (e.g. 21 | angularjs, jquery, twitter bootstrap, underscore, etc.). 22 | * Write client side unit tests and run them with 23 | [karma](http://karma-runner.github.com). 24 | * Promotes unit-testing the js codebase and removes the temptation of 25 | integration-testing everything: testing with karma is a lot faster 26 | than using capybara or a similar solution. 27 | * [LiveReload](http://livereload.com/) support for free with yeoman's 28 | angular generator! (uses websockets, no need to install a browser plugin). 29 | 30 | ## Yeoman, Bower, Livereload and Karma Runner. 31 | 32 | I want to stress out the convinience of working on your frontend using 33 | the stack yeoman sets up for you. By keeping the frontend isolated from 34 | the backend you get an amazingly fast development environment and draw a 35 | clear line between backend and frontend (great for making sure you are 36 | writing the right unit/integration tests). 37 | Yeoman sets up the test environment for you using jasmine as the testing 38 | library and karma as the runner. karma is possibly the [fastest and most 39 | complete js test runner](http://www.youtube.com/watch?feature=player_detailpage&v=Mb3_oT8ZreI&t=11) out 40 | there. And it is very well integrated with angular. 41 | 42 | 43 | 44 | The experience of coding with Livereload is simply amazing. Immediate 45 | feedback for every little addition you save in your code editor while 46 | you are working, without having to reload the page in the browser! 47 | 48 | True: you can [use livereload with rails](https://github.com/guard/guard-livereload) alone, and you 49 | can [use bower with rails too](http://dev.af83.com/2013/01/02/managing-rails-assets-with-bower.html). 50 | But Yeoman's angular generator sets everything right for you with a 51 | single command. 52 | 53 | Rails was born in the request-response era of web applications, and it 54 | shows. Yeoman sets up a web environment with defaults that are better 55 | suited for developing web applications. 56 | 57 | ## Setting the environment up 58 | 59 | You'll need: 60 | 61 | * ruby 1.9.3 ([rvm](https://rvm.io/) recommended for installation) 62 | * node 0.10.13 ([nvm](https://github.com/creationix/nvm) recommended for installation) 63 | * Two shell sessions! 64 | 65 | ### Session one: the rails backend: 66 | 67 | ``` 68 | rvm use 1.9.3 69 | git clone https://github.com/EmmanuelOga/simple-angular-rails-app.git 70 | cd simple-angular-rails-app 71 | bundle install 72 | bundle exec rails s -p 3000 73 | ``` 74 | 75 | **NOTE**: the angular application was generated using these commands. 76 | 77 | ``` 78 | npm install -g yo generator-angular 79 | mkdir ngapp; cd ngapp 80 | yo angular notes 81 | ``` 82 | 83 | ### Session two: a grunt server 84 | 85 | ``` 86 | nvm use 0.10.13 87 | cd simple-angular-rails-app/ngapp 88 | npm install -g grunt-cli 89 | npm install 90 | bower install 91 | grunt server # opens a browser window... you are done! 92 | ``` 93 | 94 | ## What's going on? 95 | 96 | During development, you need to run both the rails app and the grunt 97 | server. The reason is the html client was written as if the rails 98 | backend was an isolated, independent service, using 99 | [Yeoman](http://yeoman.io/) to scaffold the project. 100 | 101 | The intent is to **simulate** that the whole environment is a single web 102 | application. An, indeed, before deploying to prod we'll be consolidating 103 | the whole angular app as static assets in rails' public/ folder. 104 | 105 | Here's a diagram of the stack during development: 106 | 107 | ![Application Layout](https://raw.github.com/EmmanuelOga/simple-angular-rails-app/master/doc/layout.jpg "Application Layout") 108 | 109 | The grunt server task 110 | [proxies](http://github.com/EmmanuelOga/simple-angular-rails-app/blob/master/ngapp/Gruntfile.js#L65-L71) 111 | any url with path /api to the rails backend on localhost:3000. 112 | 113 | Rails is used in the backend, but really any web framework would be ok 114 | here ([sinatra](http://www.sinatrarb.com/) would make a lot more sense 115 | for my silly example app!). 116 | 117 | ## TESTING 118 | 119 | To run both the backend tests and front end tests, you can run: 120 | 121 | ``` 122 | rake test PHANTOMJS_BIN=`which phantomjs` 123 | ``` 124 | 125 | This is done by [reopening rails's test 126 | task](https://github.com/EmmanuelOga/simple-angular-rails-app/blob/master/Rakefile#L8-L10) 127 | and adding a step to run the karma runner. This design is a bit 128 | simplistic but it works. You may want to have something a bit more 129 | elaborate to make it so angular's tests are run even if rails tests fail 130 | to complete. 131 | 132 | The PHANTOMJS_BIN env var is needed because the project configures karma 133 | to use [phantom js](http://www.phantomjs.org), but it could be changed 134 | to run any other browser. 135 | 136 | karma can be 137 | [configured](https://github.com/EmmanuelOga/simple-angular-rails-app/blob/master/ngapp/karma.conf.js#L40) 138 | to watch the tests as opposed to do a single run. You should 139 | deffinitively look into that during development. 140 | 141 | ## Deploying 142 | 143 | If you run `grunt build`, grunt will package the whole angular app in a 144 | tidy package on the rails public/ folder. This packaging step could 145 | happen in the server to avoid having to commit the generated assets in 146 | your repository, analogous to how it is done for generating assets with 147 | rails' assets pipeline. 148 | 149 | ## XSRF support 150 | 151 | The rails app sets the XSRF token in the cookies. The cookies are 152 | accessible even when using the proxy because the port is [not taken into 153 | account](http://stackoverflow.com/questions/1612177/are-http-cookies-port-specific) 154 | when restricting access to the cookies. 155 | 156 | Check 157 | [ApplicationController](http://github.com/EmmanuelOga/simple-angular-rails-app/blob/master/app/controllers/application_controller.rb) 158 | for some notes on the XSRF protection. 159 | -------------------------------------------------------------------------------- /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 | Testapp::Application.load_tasks 7 | 8 | task :test do 9 | system("cd ngapp; grunt test") 10 | end 11 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | # Prevent CSRF attacks by raising an exception. 3 | # For APIs, you may want to use :null_session instead. 4 | protect_from_forgery with: :exception 5 | 6 | after_filter :set_csrf_cookie_for_ng 7 | 8 | def ping 9 | render text: "Rails Backend 1.0" 10 | end 11 | 12 | private 13 | 14 | #http://stackoverflow.com/questions/14734243/rails-csrf-protection-angular-js-protect-from-forgery-makes-me-to-log-out-on 15 | def set_csrf_cookie_for_ng 16 | cookies['XSRF-TOKEN'] = form_authenticity_token if protect_against_forgery? 17 | end 18 | 19 | def verified_request? 20 | super || form_authenticity_token == request.headers['HTTP_X_XSRF_TOKEN'] 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /app/controllers/notes_controller.rb: -------------------------------------------------------------------------------- 1 | class NotesController < ApplicationController 2 | before_action :set_note, only: [:show, :update, :destroy] 3 | 4 | # GET /notes.json 5 | def index 6 | render json: Note.all 7 | end 8 | 9 | # GET /notes/1.json 10 | def show 11 | end 12 | 13 | # POST /notes.json 14 | def create 15 | @note = Note.new(note_params) 16 | 17 | if @note.save 18 | render json: @note, status: :ok 19 | else 20 | render json: @note.errors, status: :unprocessable_entity 21 | end 22 | end 23 | 24 | # PATCH/PUT /notes/1.json 25 | def update 26 | if @note.update(note_params) 27 | head :no_content 28 | else 29 | render json: @note.errors, status: :unprocessable_entity 30 | end 31 | end 32 | 33 | # DELETE /notes/1.json 34 | def destroy 35 | @note.destroy 36 | head :no_content 37 | end 38 | 39 | private 40 | # Use callbacks to share common setup or constraints between actions. 41 | def set_note 42 | @note = Note.find(params[:id]) 43 | end 44 | 45 | # Never trust parameters from the scary internet, only allow the white list through. 46 | def note_params 47 | params.permit(:title, :body) 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /app/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EmmanuelOga/simple-angular-rails-app/3562ecb7d86ab2b3bfda2fb1ce69f085f0e88f97/app/models/.keep -------------------------------------------------------------------------------- /app/models/note.rb: -------------------------------------------------------------------------------- 1 | class Note < ActiveRecord::Base 2 | end 3 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../../config/application', __FILE__) 3 | require_relative '../config/boot' 4 | require 'rails/commands' 5 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /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 | 5 | # Require the gems listed in Gemfile, including any gems 6 | # you've limited to :test, :development, or :production. 7 | Bundler.require(:default, Rails.env) 8 | 9 | module Testapp 10 | class Application < Rails::Application 11 | # Settings in config/environments/* take precedence over those specified here. 12 | # Application configuration should go into files in config/initializers 13 | # -- all .rb files in that directory are automatically loaded. 14 | 15 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone. 16 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC. 17 | # config.time_zone = 'Central Time (US & Canada)' 18 | 19 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. 20 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] 21 | # config.i18n.default_locale = :de 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /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.exists?(ENV['BUNDLE_GEMFILE']) 5 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite version 3.x 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem 'sqlite3' 6 | development: 7 | adapter: sqlite3 8 | database: db/development.sqlite3 9 | pool: 5 10 | timeout: 5000 11 | 12 | # Warning: The database defined as "test" will be erased and 13 | # re-generated from your development database when you run "rake". 14 | # Do not set this db to the same as development or production. 15 | test: 16 | adapter: sqlite3 17 | database: db/test.sqlite3 18 | pool: 5 19 | timeout: 5000 20 | 21 | production: 22 | adapter: sqlite3 23 | database: db/production.sqlite3 24 | pool: 5 25 | timeout: 5000 26 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require File.expand_path('../application', __FILE__) 3 | 4 | # Initialize the Rails application. 5 | Testapp::Application.initialize! 6 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | Testapp::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 = true 29 | end 30 | -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | Testapp::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 thread 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 | config.serve_static_assets = false 24 | 25 | # Compress JavaScripts and CSS. 26 | config.assets.js_compressor = :uglifier 27 | # config.assets.css_compressor = :sass 28 | 29 | # Do not fallback to assets pipeline if a precompiled asset is missed. 30 | config.assets.compile = false 31 | 32 | # Generate digests for assets URLs. 33 | config.assets.digest = true 34 | 35 | # Version of your assets, change this if you want to expire all your assets. 36 | config.assets.version = '1.0' 37 | 38 | # Specifies the header that your server uses for sending files. 39 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache 40 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx 41 | 42 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 43 | # config.force_ssl = true 44 | 45 | # Set to :debug to see everything in the log. 46 | config.log_level = :info 47 | 48 | # Prepend all log lines with the following tags. 49 | # config.log_tags = [ :subdomain, :uuid ] 50 | 51 | # Use a different logger for distributed setups. 52 | # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) 53 | 54 | # Use a different cache store in production. 55 | # config.cache_store = :mem_cache_store 56 | 57 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 58 | # config.action_controller.asset_host = "http://assets.example.com" 59 | 60 | # Precompile additional assets. 61 | # application.js, application.css, and all non-JS/CSS in app/assets folder are already added. 62 | # config.assets.precompile += %w( search.js ) 63 | 64 | # Ignore bad email addresses and do not raise email delivery errors. 65 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 66 | # config.action_mailer.raise_delivery_errors = false 67 | 68 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 69 | # the I18n.default_locale when a translation can not be found). 70 | config.i18n.fallbacks = true 71 | 72 | # Send deprecation notices to registered listeners. 73 | config.active_support.deprecation = :notify 74 | 75 | # Disable automatic flushing of the log to improve performance. 76 | # config.autoflush_log = false 77 | 78 | # Use default logging formatter so that PID and timestamp are not suppressed. 79 | config.log_formatter = ::Logger::Formatter.new 80 | end 81 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | Testapp::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.serve_static_assets = true 17 | config.static_cache_control = "public, max-age=3600" 18 | 19 | # Show full error reports and disable caching. 20 | config.consider_all_requests_local = true 21 | config.action_controller.perform_caching = false 22 | 23 | # Raise exceptions instead of rendering exception templates. 24 | config.action_dispatch.show_exceptions = false 25 | 26 | # Disable request forgery protection in test environment. 27 | config.action_controller.allow_forgery_protection = false 28 | 29 | # Tell Action Mailer not to deliver emails to the real world. 30 | # The :test delivery method accumulates sent emails in the 31 | # ActionMailer::Base.deliveries array. 32 | config.action_mailer.delivery_method = :test 33 | 34 | # Print deprecation notices to the stderr. 35 | config.active_support.deprecation = :stderr 36 | end 37 | -------------------------------------------------------------------------------- /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/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | # Mime::Type.register_alias "text/html", :iphone 6 | -------------------------------------------------------------------------------- /config/initializers/secret_token.rb: -------------------------------------------------------------------------------- 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 your secret_key_base is kept private 11 | # if you're sharing your code publicly. 12 | Testapp::Application.config.secret_key_base = '4a8f13b352158d3d4ebccde17859378b55fb77d2dd288727c21d7a814b200ddcef64997a7c4aad99959293e6d376c761b0bb58274493e8a403f3f8873e28e59d' 13 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | Testapp::Application.config.session_store :cookie_store, key: '_testapp_session' 3 | -------------------------------------------------------------------------------- /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 = true 14 | # end 15 | -------------------------------------------------------------------------------- /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 | Testapp::Application.routes.draw do 2 | 3 | get "api/ping" => "application#ping" 4 | 5 | resources :notes, path: 'api/notes' 6 | 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20130723050253_create_notes.rb: -------------------------------------------------------------------------------- 1 | class CreateNotes < ActiveRecord::Migration 2 | def change 3 | create_table :notes do |t| 4 | t.string :title 5 | t.text :body 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /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: 20130723050253) do 15 | 16 | create_table "notes", force: true do |t| 17 | t.string "title" 18 | t.text "body" 19 | t.datetime "created_at" 20 | t.datetime "updated_at" 21 | end 22 | 23 | end 24 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /doc/layout.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EmmanuelOga/simple-angular-rails-app/3562ecb7d86ab2b3bfda2fb1ce69f085f0e88f97/doc/layout.jpg -------------------------------------------------------------------------------- /log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EmmanuelOga/simple-angular-rails-app/3562ecb7d86ab2b3bfda2fb1ce69f085f0e88f97/log/.keep -------------------------------------------------------------------------------- /ngapp/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "app/bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /ngapp/.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /ngapp/.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /ngapp/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .tmp 4 | .sass-cache 5 | app/bower_components 6 | -------------------------------------------------------------------------------- /ngapp/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 2, 11 | "latedef": true, 12 | "newcap": true, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "regexp": true, 16 | "undef": true, 17 | "unused": true, 18 | "strict": true, 19 | "trailing": true, 20 | "smarttabs": true, 21 | "globals": { 22 | "angular": false 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ngapp/Gruntfile.js: -------------------------------------------------------------------------------- 1 | // Generated on 2013-07-21 using generator-angular 0.3.0 2 | 'use strict'; 3 | var LIVERELOAD_PORT = 35729; 4 | var lrSnippet = require('connect-livereload')({ port: LIVERELOAD_PORT }); 5 | var mountFolder = function (connect, dir) { 6 | return connect.static(require('path').resolve(dir)); 7 | }; 8 | var proxySnippet = require('grunt-connect-proxy/lib/utils').proxyRequest; 9 | 10 | // # Globbing 11 | // for performance reasons we're only matching one level down: 12 | // 'test/spec/{,*/}*.js' 13 | // use this if you want to recursively match all subfolders: 14 | // 'test/spec/**/*.js' 15 | // 16 | /* jshint indent: false */ 17 | 18 | module.exports = function (grunt) { 19 | // load all grunt tasks 20 | require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks); 21 | 22 | // load the proxy. 23 | grunt.loadNpmTasks('grunt-connect-proxy'); 24 | 25 | // configurable paths 26 | var yeomanConfig = { 27 | app: 'app', 28 | dist: '../public' 29 | }; 30 | 31 | try { 32 | yeomanConfig.app = require('./bower.json').appPath || yeomanConfig.app; 33 | } catch (e) {} 34 | 35 | grunt.initConfig({ 36 | yeoman: yeomanConfig, 37 | watch: { 38 | coffee: { 39 | files: ['<%= yeoman.app %>/scripts/{,*/}*.coffee'], 40 | tasks: ['coffee:dist'] 41 | }, 42 | coffeeTest: { 43 | files: ['test/spec/{,*/}*.coffee'], 44 | tasks: ['coffee:test'] 45 | }, 46 | livereload: { 47 | options: { 48 | livereload: LIVERELOAD_PORT 49 | }, 50 | files: [ 51 | '<%= yeoman.app %>/{,*/}*.html', 52 | '{.tmp,<%= yeoman.app %>}/styles/{,*/}*.css', 53 | '{.tmp,<%= yeoman.app %>}/scripts/{,*/}*.js', 54 | '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}' 55 | ] 56 | } 57 | }, 58 | connect: { 59 | options: { 60 | port: 9000, 61 | // Change this to '0.0.0.0' to access the server from outside. 62 | hostname: 'localhost' 63 | }, 64 | proxies: [ 65 | { 66 | context: '/api', 67 | host: 'localhost', 68 | port: 3000 69 | } 70 | ], 71 | livereload: { 72 | options: { 73 | middleware: function (connect) { 74 | return [ 75 | proxySnippet, 76 | lrSnippet, 77 | mountFolder(connect, '.tmp'), 78 | mountFolder(connect, yeomanConfig.app) 79 | ]; 80 | } 81 | } 82 | }, 83 | test: { 84 | options: { 85 | middleware: function (connect) { 86 | return [ 87 | mountFolder(connect, '.tmp'), 88 | mountFolder(connect, 'test') 89 | ]; 90 | } 91 | } 92 | }, 93 | dist: { 94 | options: { 95 | middleware: function (connect) { 96 | return [ 97 | mountFolder(connect, yeomanConfig.dist) 98 | ]; 99 | } 100 | } 101 | } 102 | }, 103 | open: { 104 | server: { 105 | url: 'http://localhost:<%= connect.options.port %>' 106 | } 107 | }, 108 | clean: { 109 | dist: { 110 | files: [{ 111 | dot: true, 112 | src: [ 113 | '.tmp', 114 | '<%= yeoman.dist %>/*', 115 | '!<%= yeoman.dist %>/.git*' 116 | ] 117 | }] 118 | }, 119 | server: '.tmp' 120 | }, 121 | jshint: { 122 | options: { 123 | jshintrc: '.jshintrc' 124 | }, 125 | all: [ 126 | 'Gruntfile.js', 127 | '<%= yeoman.app %>/scripts/{,*/}*.js' 128 | ] 129 | }, 130 | coffee: { 131 | dist: { 132 | files: [{ 133 | expand: true, 134 | cwd: '<%= yeoman.app %>/scripts', 135 | src: '{,*/}*.coffee', 136 | dest: '.tmp/scripts', 137 | ext: '.js' 138 | }] 139 | }, 140 | test: { 141 | files: [{ 142 | expand: true, 143 | cwd: 'test/spec', 144 | src: '{,*/}*.coffee', 145 | dest: '.tmp/spec', 146 | ext: '.js' 147 | }] 148 | } 149 | }, 150 | // not used since Uglify task does concat, 151 | // but still available if needed 152 | /*concat: { 153 | dist: {} 154 | },*/ 155 | rev: { 156 | dist: { 157 | files: { 158 | src: [ 159 | '<%= yeoman.dist %>/scripts/{,*/}*.js', 160 | '<%= yeoman.dist %>/styles/{,*/}*.css', 161 | '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}', 162 | '<%= yeoman.dist %>/styles/fonts/*' 163 | ] 164 | } 165 | } 166 | }, 167 | useminPrepare: { 168 | html: '<%= yeoman.app %>/index.html', 169 | options: { 170 | dest: '<%= yeoman.dist %>' 171 | } 172 | }, 173 | usemin: { 174 | html: ['<%= yeoman.dist %>/{,*/}*.html'], 175 | css: ['<%= yeoman.dist %>/styles/{,*/}*.css'], 176 | options: { 177 | dirs: ['<%= yeoman.dist %>'] 178 | } 179 | }, 180 | imagemin: { 181 | dist: { 182 | files: [{ 183 | expand: true, 184 | cwd: '<%= yeoman.app %>/images', 185 | src: '{,*/}*.{png,jpg,jpeg}', 186 | dest: '<%= yeoman.dist %>/images' 187 | }] 188 | } 189 | }, 190 | cssmin: { 191 | // By default, your `index.html` will take care of 192 | // minification. This option is pre-configured if you do not wish to use 193 | // Usemin blocks. 194 | // dist: { 195 | // files: { 196 | // '<%= yeoman.dist %>/styles/main.css': [ 197 | // '.tmp/styles/{,*/}*.css', 198 | // '<%= yeoman.app %>/styles/{,*/}*.css' 199 | // ] 200 | // } 201 | // } 202 | }, 203 | htmlmin: { 204 | dist: { 205 | options: { 206 | /*removeCommentsFromCDATA: true, 207 | // https://github.com/yeoman/grunt-usemin/issues/44 208 | //collapseWhitespace: true, 209 | collapseBooleanAttributes: true, 210 | removeAttributeQuotes: true, 211 | removeRedundantAttributes: true, 212 | useShortDoctype: true, 213 | removeEmptyAttributes: true, 214 | removeOptionalTags: true*/ 215 | }, 216 | files: [{ 217 | expand: true, 218 | cwd: '<%= yeoman.app %>', 219 | src: ['*.html', 'views/*.html'], 220 | dest: '<%= yeoman.dist %>' 221 | }] 222 | } 223 | }, 224 | // Put files not handled in other tasks here 225 | copy: { 226 | dist: { 227 | files: [{ 228 | expand: true, 229 | dot: true, 230 | cwd: '<%= yeoman.app %>', 231 | dest: '<%= yeoman.dist %>', 232 | src: [ 233 | '*.{ico,png,txt}', 234 | '.htaccess', 235 | 'bower_components/**/*', 236 | 'images/{,*/}*.{gif,webp,svg}', 237 | 'styles/fonts/*' 238 | ] 239 | }, { 240 | expand: true, 241 | cwd: '.tmp/images', 242 | dest: '<%= yeoman.dist %>/images', 243 | src: [ 244 | 'generated/*' 245 | ] 246 | }] 247 | } 248 | }, 249 | concurrent: { 250 | server: [ 251 | 'coffee:dist' 252 | ], 253 | test: [ 254 | 'coffee' 255 | ], 256 | dist: [ 257 | 'coffee', 258 | 'imagemin', 259 | 'htmlmin' 260 | ] 261 | }, 262 | karma: { 263 | unit: { 264 | configFile: 'karma.conf.js', 265 | singleRun: true 266 | } 267 | }, 268 | cdnify: { 269 | dist: { 270 | html: ['<%= yeoman.dist %>/*.html'] 271 | } 272 | }, 273 | ngmin: { 274 | dist: { 275 | files: [{ 276 | expand: true, 277 | cwd: '<%= yeoman.dist %>/scripts', 278 | src: '*.js', 279 | dest: '<%= yeoman.dist %>/scripts' 280 | }] 281 | } 282 | }, 283 | uglify: { 284 | dist: { 285 | files: { 286 | '<%= yeoman.dist %>/scripts/scripts.js': [ 287 | '<%= yeoman.dist %>/scripts/scripts.js' 288 | ] 289 | } 290 | } 291 | } 292 | }); 293 | 294 | grunt.registerTask('server', function (target) { 295 | if (target === 'dist') { 296 | return grunt.task.run(['build', 'open', 'connect:dist:keepalive']); 297 | } 298 | 299 | grunt.task.run([ 300 | 'clean:server', 301 | 'concurrent:server', 302 | 'configureProxies', 303 | 'connect:livereload', 304 | 'open', 305 | 'watch' 306 | ]); 307 | }); 308 | 309 | grunt.registerTask('test', [ 310 | 'clean:server', 311 | 'concurrent:test', 312 | 'configureProxies', 313 | 'connect:test', 314 | 'karma' 315 | ]); 316 | 317 | grunt.registerTask('build', [ 318 | 'clean:dist', 319 | 'useminPrepare', 320 | 'concurrent:dist', 321 | 'concat', 322 | 'copy', 323 | 'cdnify', 324 | 'ngmin', 325 | 'cssmin', 326 | 'uglify', 327 | 'rev', 328 | 'usemin' 329 | ]); 330 | 331 | grunt.registerTask('default', [ 332 | 'jshint', 333 | 'test', 334 | 'build' 335 | ]); 336 | }; 337 | -------------------------------------------------------------------------------- /ngapp/app/.buildignore: -------------------------------------------------------------------------------- 1 | *.coffee -------------------------------------------------------------------------------- /ngapp/app/.htaccess: -------------------------------------------------------------------------------- 1 | # Apache Configuration File 2 | 3 | # (!) Using `.htaccess` files slows down Apache, therefore, if you have access 4 | # to the main server config file (usually called `httpd.conf`), you should add 5 | # this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html. 6 | 7 | # ############################################################################## 8 | # # CROSS-ORIGIN RESOURCE SHARING (CORS) # 9 | # ############################################################################## 10 | 11 | # ------------------------------------------------------------------------------ 12 | # | Cross-domain AJAX requests | 13 | # ------------------------------------------------------------------------------ 14 | 15 | # Enable cross-origin AJAX requests. 16 | # http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity 17 | # http://enable-cors.org/ 18 | 19 | # 20 | # Header set Access-Control-Allow-Origin "*" 21 | # 22 | 23 | # ------------------------------------------------------------------------------ 24 | # | CORS-enabled images | 25 | # ------------------------------------------------------------------------------ 26 | 27 | # Send the CORS header for images when browsers request it. 28 | # https://developer.mozilla.org/en/CORS_Enabled_Image 29 | # http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html 30 | # http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/ 31 | 32 | 33 | 34 | 35 | SetEnvIf Origin ":" IS_CORS 36 | Header set Access-Control-Allow-Origin "*" env=IS_CORS 37 | 38 | 39 | 40 | 41 | # ------------------------------------------------------------------------------ 42 | # | Web fonts access | 43 | # ------------------------------------------------------------------------------ 44 | 45 | # Allow access from all domains for web fonts 46 | 47 | 48 | 49 | Header set Access-Control-Allow-Origin "*" 50 | 51 | 52 | 53 | 54 | # ############################################################################## 55 | # # ERRORS # 56 | # ############################################################################## 57 | 58 | # ------------------------------------------------------------------------------ 59 | # | 404 error prevention for non-existing redirected folders | 60 | # ------------------------------------------------------------------------------ 61 | 62 | # Prevent Apache from returning a 404 error for a rewrite if a directory 63 | # with the same name does not exist. 64 | # http://httpd.apache.org/docs/current/content-negotiation.html#multiviews 65 | # http://www.webmasterworld.com/apache/3808792.htm 66 | 67 | Options -MultiViews 68 | 69 | # ------------------------------------------------------------------------------ 70 | # | Custom error messages / pages | 71 | # ------------------------------------------------------------------------------ 72 | 73 | # You can customize what Apache returns to the client in case of an error (see 74 | # http://httpd.apache.org/docs/current/mod/core.html#errordocument), e.g.: 75 | 76 | ErrorDocument 404 /404.html 77 | 78 | 79 | # ############################################################################## 80 | # # INTERNET EXPLORER # 81 | # ############################################################################## 82 | 83 | # ------------------------------------------------------------------------------ 84 | # | Better website experience | 85 | # ------------------------------------------------------------------------------ 86 | 87 | # Force IE to render pages in the highest available mode in the various 88 | # cases when it may not: http://hsivonen.iki.fi/doctype/ie-mode.pdf. 89 | # Use, if installed, Google Chrome Frame. 90 | 91 | 92 | Header set X-UA-Compatible "IE=edge,chrome=1" 93 | # `mod_headers` can't match based on the content-type, however, we only 94 | # want to send this header for HTML pages and not for the other resources 95 | 96 | Header unset X-UA-Compatible 97 | 98 | 99 | 100 | # ------------------------------------------------------------------------------ 101 | # | Cookie setting from iframes | 102 | # ------------------------------------------------------------------------------ 103 | 104 | # Allow cookies to be set from iframes in IE. 105 | 106 | # 107 | # Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"" 108 | # 109 | 110 | # ------------------------------------------------------------------------------ 111 | # | Screen flicker | 112 | # ------------------------------------------------------------------------------ 113 | 114 | # Stop screen flicker in IE on CSS rollovers (this only works in 115 | # combination with the `ExpiresByType` directives for images from below). 116 | 117 | # BrowserMatch "MSIE" brokenvary=1 118 | # BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1 119 | # BrowserMatch "Opera" !brokenvary 120 | # SetEnvIf brokenvary 1 force-no-vary 121 | 122 | 123 | # ############################################################################## 124 | # # MIME TYPES AND ENCODING # 125 | # ############################################################################## 126 | 127 | # ------------------------------------------------------------------------------ 128 | # | Proper MIME types for all files | 129 | # ------------------------------------------------------------------------------ 130 | 131 | 132 | 133 | # Audio 134 | AddType audio/mp4 m4a f4a f4b 135 | AddType audio/ogg oga ogg 136 | 137 | # JavaScript 138 | # Normalize to standard type (it's sniffed in IE anyways): 139 | # http://tools.ietf.org/html/rfc4329#section-7.2 140 | AddType application/javascript js jsonp 141 | AddType application/json json 142 | 143 | # Video 144 | AddType video/mp4 mp4 m4v f4v f4p 145 | AddType video/ogg ogv 146 | AddType video/webm webm 147 | AddType video/x-flv flv 148 | 149 | # Web fonts 150 | AddType application/font-woff woff 151 | AddType application/vnd.ms-fontobject eot 152 | 153 | # Browsers usually ignore the font MIME types and sniff the content, 154 | # however, Chrome shows a warning if other MIME types are used for the 155 | # following fonts. 156 | AddType application/x-font-ttf ttc ttf 157 | AddType font/opentype otf 158 | 159 | # Make SVGZ fonts work on iPad: 160 | # https://twitter.com/FontSquirrel/status/14855840545 161 | AddType image/svg+xml svg svgz 162 | AddEncoding gzip svgz 163 | 164 | # Other 165 | AddType application/octet-stream safariextz 166 | AddType application/x-chrome-extension crx 167 | AddType application/x-opera-extension oex 168 | AddType application/x-shockwave-flash swf 169 | AddType application/x-web-app-manifest+json webapp 170 | AddType application/x-xpinstall xpi 171 | AddType application/xml atom rdf rss xml 172 | AddType image/webp webp 173 | AddType image/x-icon ico 174 | AddType text/cache-manifest appcache manifest 175 | AddType text/vtt vtt 176 | AddType text/x-component htc 177 | AddType text/x-vcard vcf 178 | 179 | 180 | 181 | # ------------------------------------------------------------------------------ 182 | # | UTF-8 encoding | 183 | # ------------------------------------------------------------------------------ 184 | 185 | # Use UTF-8 encoding for anything served as `text/html` or `text/plain`. 186 | AddDefaultCharset utf-8 187 | 188 | # Force UTF-8 for certain file formats. 189 | 190 | AddCharset utf-8 .atom .css .js .json .rss .vtt .webapp .xml 191 | 192 | 193 | 194 | # ############################################################################## 195 | # # URL REWRITES # 196 | # ############################################################################## 197 | 198 | # ------------------------------------------------------------------------------ 199 | # | Rewrite engine | 200 | # ------------------------------------------------------------------------------ 201 | 202 | # Turning on the rewrite engine and enabling the `FollowSymLinks` option is 203 | # necessary for the following directives to work. 204 | 205 | # If your web host doesn't allow the `FollowSymlinks` option, you may need to 206 | # comment it out and use `Options +SymLinksIfOwnerMatch` but, be aware of the 207 | # performance impact: http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks 208 | 209 | # Also, some cloud hosting services require `RewriteBase` to be set: 210 | # http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site 211 | 212 | 213 | Options +FollowSymlinks 214 | # Options +SymLinksIfOwnerMatch 215 | RewriteEngine On 216 | # RewriteBase / 217 | 218 | 219 | # ------------------------------------------------------------------------------ 220 | # | Suppressing / Forcing the "www." at the beginning of URLs | 221 | # ------------------------------------------------------------------------------ 222 | 223 | # The same content should never be available under two different URLs especially 224 | # not with and without "www." at the beginning. This can cause SEO problems 225 | # (duplicate content), therefore, you should choose one of the alternatives and 226 | # redirect the other one. 227 | 228 | # By default option 1 (no "www.") is activated: 229 | # http://no-www.org/faq.php?q=class_b 230 | 231 | # If you'd prefer to use option 2, just comment out all the lines from option 1 232 | # and uncomment the ones from option 2. 233 | 234 | # IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME! 235 | 236 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 237 | 238 | # Option 1: rewrite www.example.com → example.com 239 | 240 | 241 | RewriteCond %{HTTPS} !=on 242 | RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] 243 | RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] 244 | 245 | 246 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 247 | 248 | # Option 2: rewrite example.com → www.example.com 249 | 250 | # Be aware that the following might not be a good idea if you use "real" 251 | # subdomains for certain parts of your website. 252 | 253 | # 254 | # RewriteCond %{HTTPS} !=on 255 | # RewriteCond %{HTTP_HOST} !^www\..+$ [NC] 256 | # RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] 257 | # 258 | 259 | 260 | # ############################################################################## 261 | # # SECURITY # 262 | # ############################################################################## 263 | 264 | # ------------------------------------------------------------------------------ 265 | # | Content Security Policy (CSP) | 266 | # ------------------------------------------------------------------------------ 267 | 268 | # You can mitigate the risk of cross-site scripting and other content-injection 269 | # attacks by setting a Content Security Policy which whitelists trusted sources 270 | # of content for your site. 271 | 272 | # The example header below allows ONLY scripts that are loaded from the current 273 | # site's origin (no inline scripts, no CDN, etc). This almost certainly won't 274 | # work as-is for your site! 275 | 276 | # To get all the details you'll need to craft a reasonable policy for your site, 277 | # read: http://html5rocks.com/en/tutorials/security/content-security-policy (or 278 | # see the specification: http://w3.org/TR/CSP). 279 | 280 | # 281 | # Header set Content-Security-Policy "script-src 'self'; object-src 'self'" 282 | # 283 | # Header unset Content-Security-Policy 284 | # 285 | # 286 | 287 | # ------------------------------------------------------------------------------ 288 | # | File access | 289 | # ------------------------------------------------------------------------------ 290 | 291 | # Block access to directories without a default document. 292 | # Usually you should leave this uncommented because you shouldn't allow anyone 293 | # to surf through every directory on your server (which may includes rather 294 | # private places like the CMS's directories). 295 | 296 | 297 | Options -Indexes 298 | 299 | 300 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 301 | 302 | # Block access to hidden files and directories. 303 | # This includes directories used by version control systems such as Git and SVN. 304 | 305 | 306 | RewriteCond %{SCRIPT_FILENAME} -d [OR] 307 | RewriteCond %{SCRIPT_FILENAME} -f 308 | RewriteRule "(^|/)\." - [F] 309 | 310 | 311 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 312 | 313 | # Block access to backup and source files. 314 | # These files may be left by some text editors and can pose a great security 315 | # danger when anyone has access to them. 316 | 317 | 318 | Order allow,deny 319 | Deny from all 320 | Satisfy All 321 | 322 | 323 | # ------------------------------------------------------------------------------ 324 | # | Secure Sockets Layer (SSL) | 325 | # ------------------------------------------------------------------------------ 326 | 327 | # Rewrite secure requests properly to prevent SSL certificate warnings, e.g.: 328 | # prevent `https://www.example.com` when your certificate only allows 329 | # `https://secure.example.com`. 330 | 331 | # 332 | # RewriteCond %{SERVER_PORT} !^443 333 | # RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L] 334 | # 335 | 336 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 337 | 338 | # Force client-side SSL redirection. 339 | 340 | # If a user types "example.com" in his browser, the above rule will redirect him 341 | # to the secure version of the site. That still leaves a window of opportunity 342 | # (the initial HTTP connection) for an attacker to downgrade or redirect the 343 | # request. The following header ensures that browser will ONLY connect to your 344 | # server via HTTPS, regardless of what the users type in the address bar. 345 | # http://www.html5rocks.com/en/tutorials/security/transport-layer-security/ 346 | 347 | # 348 | # Header set Strict-Transport-Security max-age=16070400; 349 | # 350 | 351 | # ------------------------------------------------------------------------------ 352 | # | Server software information | 353 | # ------------------------------------------------------------------------------ 354 | 355 | # Avoid displaying the exact Apache version number, the description of the 356 | # generic OS-type and the information about Apache's compiled-in modules. 357 | 358 | # ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`! 359 | 360 | # ServerTokens Prod 361 | 362 | 363 | # ############################################################################## 364 | # # WEB PERFORMANCE # 365 | # ############################################################################## 366 | 367 | # ------------------------------------------------------------------------------ 368 | # | Compression | 369 | # ------------------------------------------------------------------------------ 370 | 371 | 372 | 373 | # Force compression for mangled headers. 374 | # http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping 375 | 376 | 377 | SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding 378 | RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding 379 | 380 | 381 | 382 | # Compress all output labeled with one of the following MIME-types 383 | # (for Apache versions below 2.3.7, you don't need to enable `mod_filter` 384 | # and can remove the `` and `` lines 385 | # as `AddOutputFilterByType` is still in the core directives). 386 | 387 | AddOutputFilterByType DEFLATE application/atom+xml \ 388 | application/javascript \ 389 | application/json \ 390 | application/rss+xml \ 391 | application/vnd.ms-fontobject \ 392 | application/x-font-ttf \ 393 | application/x-web-app-manifest+json \ 394 | application/xhtml+xml \ 395 | application/xml \ 396 | font/opentype \ 397 | image/svg+xml \ 398 | image/x-icon \ 399 | text/css \ 400 | text/html \ 401 | text/plain \ 402 | text/x-component \ 403 | text/xml 404 | 405 | 406 | 407 | 408 | # ------------------------------------------------------------------------------ 409 | # | Content transformations | 410 | # ------------------------------------------------------------------------------ 411 | 412 | # Prevent some of the mobile network providers from modifying the content of 413 | # your site: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5. 414 | 415 | # 416 | # Header set Cache-Control "no-transform" 417 | # 418 | 419 | # ------------------------------------------------------------------------------ 420 | # | ETag removal | 421 | # ------------------------------------------------------------------------------ 422 | 423 | # Since we're sending far-future expires headers (see below), ETags can 424 | # be removed: http://developer.yahoo.com/performance/rules.html#etags. 425 | 426 | # `FileETag None` is not enough for every server. 427 | 428 | Header unset ETag 429 | 430 | 431 | FileETag None 432 | 433 | # ------------------------------------------------------------------------------ 434 | # | Expires headers (for better cache control) | 435 | # ------------------------------------------------------------------------------ 436 | 437 | # The following expires headers are set pretty far in the future. If you don't 438 | # control versioning with filename-based cache busting, consider lowering the 439 | # cache time for resources like CSS and JS to something like 1 week. 440 | 441 | 442 | 443 | ExpiresActive on 444 | ExpiresDefault "access plus 1 month" 445 | 446 | # CSS 447 | ExpiresByType text/css "access plus 1 year" 448 | 449 | # Data interchange 450 | ExpiresByType application/json "access plus 0 seconds" 451 | ExpiresByType application/xml "access plus 0 seconds" 452 | ExpiresByType text/xml "access plus 0 seconds" 453 | 454 | # Favicon (cannot be renamed!) 455 | ExpiresByType image/x-icon "access plus 1 week" 456 | 457 | # HTML components (HTCs) 458 | ExpiresByType text/x-component "access plus 1 month" 459 | 460 | # HTML 461 | ExpiresByType text/html "access plus 0 seconds" 462 | 463 | # JavaScript 464 | ExpiresByType application/javascript "access plus 1 year" 465 | 466 | # Manifest files 467 | ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds" 468 | ExpiresByType text/cache-manifest "access plus 0 seconds" 469 | 470 | # Media 471 | ExpiresByType audio/ogg "access plus 1 month" 472 | ExpiresByType image/gif "access plus 1 month" 473 | ExpiresByType image/jpeg "access plus 1 month" 474 | ExpiresByType image/png "access plus 1 month" 475 | ExpiresByType video/mp4 "access plus 1 month" 476 | ExpiresByType video/ogg "access plus 1 month" 477 | ExpiresByType video/webm "access plus 1 month" 478 | 479 | # Web feeds 480 | ExpiresByType application/atom+xml "access plus 1 hour" 481 | ExpiresByType application/rss+xml "access plus 1 hour" 482 | 483 | # Web fonts 484 | ExpiresByType application/font-woff "access plus 1 month" 485 | ExpiresByType application/vnd.ms-fontobject "access plus 1 month" 486 | ExpiresByType application/x-font-ttf "access plus 1 month" 487 | ExpiresByType font/opentype "access plus 1 month" 488 | ExpiresByType image/svg+xml "access plus 1 month" 489 | 490 | 491 | 492 | # ------------------------------------------------------------------------------ 493 | # | Filename-based cache busting | 494 | # ------------------------------------------------------------------------------ 495 | 496 | # If you're not using a build process to manage your filename version revving, 497 | # you might want to consider enabling the following directives to route all 498 | # requests such as `/css/style.12345.css` to `/css/style.css`. 499 | 500 | # To understand why this is important and a better idea than `*.css?v231`, read: 501 | # http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring 502 | 503 | # 504 | # RewriteCond %{REQUEST_FILENAME} !-f 505 | # RewriteCond %{REQUEST_FILENAME} !-d 506 | # RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L] 507 | # 508 | 509 | # ------------------------------------------------------------------------------ 510 | # | File concatenation | 511 | # ------------------------------------------------------------------------------ 512 | 513 | # Allow concatenation from within specific CSS and JS files, e.g.: 514 | # Inside of `script.combined.js` you could have 515 | # 516 | # 517 | # and they would be included into this single file. 518 | 519 | # 520 | # 521 | # Options +Includes 522 | # AddOutputFilterByType INCLUDES application/javascript application/json 523 | # SetOutputFilter INCLUDES 524 | # 525 | # 526 | # Options +Includes 527 | # AddOutputFilterByType INCLUDES text/css 528 | # SetOutputFilter INCLUDES 529 | # 530 | # 531 | 532 | # ------------------------------------------------------------------------------ 533 | # | Persistent connections | 534 | # ------------------------------------------------------------------------------ 535 | 536 | # Allow multiple requests to be sent over the same TCP connection: 537 | # http://httpd.apache.org/docs/current/en/mod/core.html#keepalive. 538 | 539 | # Enable if you serve a lot of static content but, be aware of the 540 | # possible disadvantages! 541 | 542 | # 543 | # Header set Connection Keep-Alive 544 | # 545 | -------------------------------------------------------------------------------- /ngapp/app/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Not Found :( 6 | 141 | 142 | 143 |
144 |

Not found :(

145 |

Sorry, but the page you were trying to view does not exist.

146 |

It looks like this was the result of either:

147 | 151 | 154 | 155 |
156 | 157 | 158 | -------------------------------------------------------------------------------- /ngapp/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EmmanuelOga/simple-angular-rails-app/3562ecb7d86ab2b3bfda2fb1ce69f085f0e88f97/ngapp/app/favicon.ico -------------------------------------------------------------------------------- /ngapp/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 28 | 29 | 30 |
31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /ngapp/app/robots.txt: -------------------------------------------------------------------------------- 1 | # robotstxt.org 2 | 3 | User-agent: * 4 | -------------------------------------------------------------------------------- /ngapp/app/scripts/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('notesApp', ['ngResource']) 4 | .config(function ($routeProvider) { 5 | $routeProvider 6 | .when('/', { 7 | templateUrl: 'views/main.html', 8 | controller: 'MainCtrl' 9 | }) 10 | .otherwise({ 11 | redirectTo: '/' 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /ngapp/app/scripts/controllers/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('notesApp') 4 | .factory('Note', function ($resource) { 5 | return $resource('/api/notes/:noteId'); 6 | }); 7 | 8 | angular.module('notesApp') 9 | .controller('MainCtrl', function ($scope, Note) { 10 | 11 | $scope.notes = Note.query(); 12 | 13 | $scope.create = function(title, body) { 14 | Note.save({title: title, body: body}, function(note) { 15 | $scope.notes.push(note); 16 | }); 17 | }; 18 | 19 | $scope.delete = function(index) { 20 | Note.delete({noteId: $scope.notes[index].id}, function() { 21 | $scope.notes.splice(index, 1); 22 | }); 23 | }; 24 | 25 | }); 26 | -------------------------------------------------------------------------------- /ngapp/app/styles/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | background: #fafafa; 3 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 4 | color: #333; 5 | padding-top: 40px; 6 | } 7 | -------------------------------------------------------------------------------- /ngapp/app/views/main.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Notes

5 |
6 | 7 | 8 |
9 | 10 |
11 |
12 |
13 | 14 |
15 |
16 | Delete 17 |

{{note.title}}

18 |

{{note.body}}

19 |
20 |
21 |
22 | -------------------------------------------------------------------------------- /ngapp/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "notes", 3 | "version": "0.0.0", 4 | "dependencies": { 5 | "angular": "~1.0.7", 6 | "json3": "~3.2.4", 7 | "jquery": "~1.9.1", 8 | "bootstrap-sass": "~2.3.1", 9 | "es5-shim": "~2.0.8", 10 | "angular-resource": "~1.0.7", 11 | "angular-cookies": "~1.0.7", 12 | "angular-sanitize": "~1.0.7" 13 | }, 14 | "devDependencies": { 15 | "angular-mocks": "~1.0.7", 16 | "angular-scenario": "~1.0.7" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ngapp/karma-e2e.conf.js: -------------------------------------------------------------------------------- 1 | // Karma E2E configuration 2 | 3 | // base path, that will be used to resolve files and exclude 4 | basePath = ''; 5 | 6 | // list of files / patterns to load in the browser 7 | files = [ 8 | ANGULAR_SCENARIO, 9 | ANGULAR_SCENARIO_ADAPTER, 10 | 'test/e2e/**/*.js' 11 | ]; 12 | 13 | // list of files to exclude 14 | exclude = []; 15 | 16 | // test results reporter to use 17 | // possible values: dots || progress || growl 18 | reporters = ['progress']; 19 | 20 | // web server port 21 | port = 8080; 22 | 23 | // cli runner port 24 | runnerPort = 9100; 25 | 26 | // enable / disable colors in the output (reporters and logs) 27 | colors = true; 28 | 29 | // level of logging 30 | // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG 31 | logLevel = LOG_INFO; 32 | 33 | // enable / disable watching file and executing tests whenever any file changes 34 | autoWatch = false; 35 | 36 | // Start these browsers, currently available: 37 | // - Chrome 38 | // - ChromeCanary 39 | // - Firefox 40 | // - Opera 41 | // - Safari (only Mac) 42 | // - PhantomJS 43 | // - IE (only Windows) 44 | browsers = ['Chrome']; 45 | 46 | // If browser does not capture in given timeout [ms], kill it 47 | captureTimeout = 5000; 48 | 49 | // Continuous Integration mode 50 | // if true, it capture browsers, run tests and exit 51 | singleRun = false; 52 | -------------------------------------------------------------------------------- /ngapp/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | 3 | // base path, that will be used to resolve files and exclude 4 | basePath = ''; 5 | 6 | // list of files / patterns to load in the browser 7 | files = [ 8 | JASMINE, 9 | JASMINE_ADAPTER, 10 | 'app/bower_components/angular/angular.js', 11 | 'app/bower_components/angular-mocks/angular-mocks.js', 12 | 'app/bower_components/angular-resource/angular-resource.js', 13 | 'app/scripts/*.js', 14 | 'app/scripts/**/*.js', 15 | 'test/mock/**/*.js', 16 | 'test/spec/**/*.js' 17 | ]; 18 | 19 | // list of files to exclude 20 | exclude = []; 21 | 22 | // test results reporter to use 23 | // possible values: dots || progress || growl 24 | reporters = ['progress']; 25 | 26 | // web server port 27 | port = 8080; 28 | 29 | // cli runner port 30 | runnerPort = 9100; 31 | 32 | // enable / disable colors in the output (reporters and logs) 33 | colors = true; 34 | 35 | // level of logging 36 | // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG 37 | logLevel = LOG_INFO; 38 | 39 | // enable / disable watching file and executing tests whenever any file changes 40 | autoWatch = false; 41 | 42 | // Start these browsers, currently available: 43 | // - Chrome 44 | // - ChromeCanary 45 | // - Firefox 46 | // - Opera 47 | // - Safari (only Mac) 48 | // - PhantomJS 49 | // - IE (only Windows) 50 | browsers = ['PhantomJS']; 51 | 52 | // If browser does not capture in given timeout [ms], kill it 53 | captureTimeout = 5000; 54 | 55 | // Continuous Integration mode 56 | // if true, it capture browsers, run tests and exit 57 | singleRun = true; 58 | -------------------------------------------------------------------------------- /ngapp/libpeerconnection.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EmmanuelOga/simple-angular-rails-app/3562ecb7d86ab2b3bfda2fb1ce69f085f0e88f97/ngapp/libpeerconnection.log -------------------------------------------------------------------------------- /ngapp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "notes", 3 | "version": "0.0.0", 4 | "dependencies": {}, 5 | "devDependencies": { 6 | "grunt": "~0.4.1", 7 | "grunt-contrib-copy": "~0.4.1", 8 | "grunt-contrib-concat": "~0.3.0", 9 | "grunt-contrib-coffee": "~0.7.0", 10 | "grunt-contrib-uglify": "~0.2.0", 11 | "grunt-contrib-compass": "~0.3.0", 12 | "grunt-contrib-jshint": "~0.6.0", 13 | "grunt-contrib-cssmin": "~0.6.0", 14 | "grunt-contrib-connect": "~0.3.0", 15 | "grunt-contrib-clean": "~0.4.1", 16 | "grunt-contrib-htmlmin": "~0.1.3", 17 | "grunt-contrib-imagemin": "~0.1.4", 18 | "grunt-contrib-watch": "~0.4.0", 19 | 20 | "grunt-connect-proxy": "~0.1.5", 21 | 22 | "grunt-usemin": "~0.1.11", 23 | "grunt-rev": "~0.1.0", 24 | "grunt-karma": "~0.4.3", 25 | "grunt-open": "~0.2.0", 26 | "grunt-concurrent": "~0.3.0", 27 | "matchdep": "~0.1.2", 28 | "connect-livereload": "~0.2.0", 29 | "grunt-google-cdn": "~0.2.0", 30 | "grunt-ngmin": "~0.0.2" 31 | }, 32 | "engines": { 33 | "node": ">=0.8.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ngapp/test/runner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | End2end Test Runner 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /ngapp/test/spec/controllers/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Controller: MainCtrl', function () { 4 | 5 | // load the controller's module 6 | beforeEach(module('notesApp')); 7 | 8 | var MainCtrl, scope; 9 | 10 | var mockNote = { 11 | 'query' : function() { return [{id: 1}, {id: 2}]; }, 12 | 'save' : function(params, callback) { return callback(params); }, 13 | 'delete' : function(params, callback) { return callback(params); } 14 | }; 15 | 16 | 17 | // Initialize the controller and a mock scope 18 | beforeEach(inject(function ($controller, $rootScope) { 19 | scope = $rootScope.$new(); 20 | MainCtrl = $controller('MainCtrl', { 21 | $scope: scope, 22 | Note : mockNote 23 | }); 24 | })); 25 | 26 | it('initializes the notes with a query to the server', function () { 27 | expect(scope.notes).toEqual([{id: 1}, {id: 2}]); 28 | }); 29 | 30 | it('is able to create notes', function () { 31 | scope.create('title', 'body'); 32 | expect(scope.notes[scope.notes.length - 1]).toEqual({'title' : 'title', 'body' : 'body' }); 33 | }); 34 | 35 | it('is able to delete notes', function () { 36 | scope.delete(0); 37 | expect(scope.notes[0]).toEqual({id: 2}); 38 | }); 39 | }); 40 | --------------------------------------------------------------------------------