├── practices ├── react.md ├── ios.md ├── javascript.md ├── design.md ├── README.md ├── git.md ├── issues.md ├── ember.md ├── react-redux.md ├── react-native.md ├── rails.md ├── qa.md ├── i18n.md └── testing.md ├── watch └── README.md ├── workflow ├── android-osx.md ├── rails-osx.md ├── heroku.md ├── elixir.md ├── rails-ubuntu1404.md └── ios.md ├── README.md ├── tools └── README.md └── read └── README.md /practices/react.md: -------------------------------------------------------------------------------- 1 | # React 2 | -------------------------------------------------------------------------------- /practices/ios.md: -------------------------------------------------------------------------------- 1 | # iOS 2 | 3 | - Follow the [Ray Wenderlich Styleguide](https://github.com/raywenderlich/swift-style-guide) except using 2 spaces as indentation. We'll use 4 spaces as recommended by Apple. 4 | - Prefer [realm.io](http://realm.io) over CoreData. 5 | - Use CocoaPods whenever available. When you need a library/plugin, check [Cocoa Controls](https://www.cocoacontrols.com/) first before trying to do it yourself. 6 | -------------------------------------------------------------------------------- /practices/javascript.md: -------------------------------------------------------------------------------- 1 | # JavaScript 2 | 3 | - Follow [airbnb/javascript](https://github.com/airbnb/javascript) the styleguide (feel free to discard ES6-isms for non-ES6 projects) 4 | - Follow [rsjs](https://github.com/rstacruz/rsjs)'s guideline on behaviors 5 | - Prefer [babel](http://babeljs.io/) as a preprocessor. For rails, use [sprockets-es6](https://rubygems.org/gems/sprockets-es6) 6 | 7 | Avoid: 8 | 9 | - Avoid [coffeescript](http://coffeescript.org/). See above 10 | -------------------------------------------------------------------------------- /watch/README.md: -------------------------------------------------------------------------------- 1 | ## Design 2 | 3 | - [Aaron Draplin on Logo Design](https://vimeo.com/113751583) - on logo design iterations 4 | - [The Design Sprint: from Google Ventures to Google](https://www.youtube.com/watch?v=aWQUSiOZ0x8) - on design sprint 5 | - [The History of Typography](https://www.youtube.com/watch?v=wOgIkxAfJsk) - on type 6 | - [How to Build Your Creative Confidence](https://www.youtube.com/watch?v=16p9YRF0l-g) - on motivation lol 7 | - [Bootstrap 4 Grid System](http://designmodo.com/bootstrap-4-grid-system/) - explaining Bootstrap's grids 8 | 9 | ## Development 10 | - [Nothing is Something by Sandi Metz](https://www.youtube.com/watch?v=OMPfEXIlTVE) - on nil objects 11 | - [Architecture the Lost Years by Robert Martin](https://www.youtube.com/watch?v=WpkDN78P884) - on architecture 12 | - [All the Little Things by Sandi Metz](https://www.youtube.com/watch?v=8bZh5LMaSmEA) - on small, interchangeable objects 13 | -------------------------------------------------------------------------------- /workflow/android-osx.md: -------------------------------------------------------------------------------- 1 | # Basic OS X Machine Setup for Android Development 2 | 3 | ## Easy mode 4 | 5 | If you have [Homebrew](http://brew.sh/) and [Homebrew Cask](https://caskroom.github.io/): 6 | 7 | ```sh 8 | brew cask install java 9 | brew cask install android-studio 10 | ``` 11 | 12 | Tested on El Capitan (OS X 10.11). You may also check out these brew packages: `android-sdk` (standalone SDK without studio), `android-platform-tools` (adb and friends). 13 | 14 | ## Manual setup 15 | 16 | > NB: These instructions are dated May 2015 and are for OS X 10.10. 17 | 18 | ####Pre-requisites 19 | 1. Update to Yosemite(OS X 10.10) from App Store 20 | 2. Install latest JRE at http://www.oracle.com/technetwork/java/javase/downloads/index.html 21 | 3. Android Studio still have dibs for Java 6 for its font rendering not to mention certain bugs with the latest OS X; Download this support patch https://support.apple.com/kb/DL1572 and install 22 | 23 | ####Setup Android Studio 24 | 1. Download and install it http://developer.android.com/sdk/index.html 25 | 2. Run Android Studio and follow throught the steps which includes downloading the rest of the dependencies such as Android SDK 26 | -------------------------------------------------------------------------------- /practices/design.md: -------------------------------------------------------------------------------- 1 | # Design practices 2 | 3 | ## Design 4 | 5 | - Prefer [Sketch](http://bohemiancoding.com/sketch/) for UI design 6 | - Prefer [ionicons](http://ionicons.com/) for UI icons (instead of FontAwesome) 7 | - Prefer [Styledown](https://github.com/styledown/styledown) for making a Living Styleguide 8 | 9 | ## Sass/CSS 10 | 11 | - Prefer `.scss` (nested) syntax over `.sass` (indented), since most projects use that 12 | - Enable [CSS antialiasing](http://ricostacruz.com/cheatsheets/css-antialias) globally 13 | - Prefer to make new components rather to extend/override Bootstrap components 14 | - Prefer to break CSS into multiple files and use `@import 'components/*'` ([info](https://github.com/rstacruz/rscss#one-component-per-file)) 15 | - Prefer to start a styleguide as early on in the project 16 | - Refer to [rscss](http://rscss.io) 17 | - The rscss [two-word rule](https://github.com/rstacruz/rscss#naming-components) isn't generally followed around here, feel free to break it 18 | - Style `&:focus, &:hover { ... }` together 19 | - If you've never broken the rule above, feel free to use `:focus { outline: none }` ([haha](http://www.outlinenone.com/)) 20 | 21 | ## Bootstrap 22 | 23 | - Refer to [bootstrap-practices](https://github.com/rstacruz/bootstrap-practices) 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # :cloud: Awesome 2 | 3 | ### Our practices 4 | This is a list of things to prefer and avoid in projects. These practices are a result of trials-and-errors across many [Proudcloud] projects. We've learned what works and what doesn't, and these are the lessons that stuck. 5 | 6 | - [General practices](practices/) - ethics, new projects 7 | - [Design](practices/design.md) - UI design and CSS 8 | - [Git](practices/git.md) - Git and GitHub 9 | - [JavaScript](practices/javascript.md) - Frontend and Node.js code 10 | - [Rails](practices/rails.md) - Makes the world go 'round 11 | - [Testing](practices/testing.md) - Detailed Rspec and TDD practices 12 | - [iOS](practices/ios.md) - Xcode Swift development 13 | - [i18n](practices/i18n.md) - Rails localization 14 | - [Ember](practices/ember.md) - SPA Development with Ember.js 15 | - [Issues](practices/issues.md) - Filing issues 16 | 17 | ---- 18 | 19 | ### Required reading 20 | Must-read books, articles and must-watch videos for every [Proudcloud] developer. 21 | 22 | - [Required reading](read/README.md) 23 | 24 | ---- 25 | 26 | ### Workflow 27 | Guides on setting up common development environments. 28 | 29 | - [Android on OSX](workflow/android-osx.md) 30 | - [Elixir](workflow/elixir.md) 31 | - [Heroku](workflow/heroku.md) 32 | - [Rails on OSX](workflow/rails-osx.md) 33 | - [iOS](workflow/ios.md) 34 | - [Rails on Ubuntu 14.04](workflow/rails-ubuntu1404.md) 35 | 36 | ---- 37 | 38 | ### Tools 39 | A list of our recommended tools for design and development. 40 | 41 | - [Tools](tools/README.md) 42 | 43 | [Proudcloud]: http://proudcloud.net 44 | 45 |
46 | 47 | ---- 48 | 49 | :copyright: 2015, [Proudcloud]. Released under MIT License.
50 | Feel free to reuse this list for your own team! 51 | -------------------------------------------------------------------------------- /practices/README.md: -------------------------------------------------------------------------------- 1 | # Development practices 2 | 3 | This is a list of things to prefer and avoid in projects. These practices are a result of trials-and-errors across many Proudcloud projects. We've learned what works and what doesn't, and these are the lessons that stuck. 4 | 5 | ## Ethics 6 | 7 | - Always be online on Slack 8 | - Better to ask forgiveness than permission 9 | - Respect your team and individual schedules 10 | - Always work on targeted release versions or milestones. We use `alpha`, `beta` for early stage projects. Moving forward, practice the use of [Semantic Versioning](http://semver.org). 11 | - Be aware of the product roadmap. 12 | - Work will never run out. Focus on approximately 2 weeks (1 sprint) worth of targets only. Close a version release. Repeat the cycle. 13 | - Conserve energy. Do not overwork yourselves. 14 | - Code clarity. Readable code. 15 | - Consistency with team practices but feel free to discuss improvements. 16 | - Consistency but correct and raise what you feel is wrong. 17 | - Do your best not to be a blocker to your teammates. 18 | - Got a problem? Ask on Slack. 19 | 20 | ## Starting a new project 21 | 22 | - Create a Github repo and make the default branch to `develop`. 23 | - Create and update the project's `README.md` 24 | - Add proper installation instructions. Notes and caveats. 25 | - Github Slack channel integration. The amount of notifications you want to receive depends on you. Usually, we like to get notified with new pull requests and comments only. 26 | - Continuous integration. Currently, we're using [Circleci](https://circleci.com). Ask an organization admin or a collaborator to add it for you if you don't have access. Circleci uses Github authentication so you don't need an invite. Don't forget the Slack integration. 27 | 28 | ## Watch out 29 | 30 | ![image](https://cloud.githubusercontent.com/assets/2481/8126567/1f6be7a0-1122-11e5-9292-a5eab7df6564.png) 31 | 32 | -------------------------------------------------------------------------------- /practices/git.md: -------------------------------------------------------------------------------- 1 | # Git 2 | 3 | Using GitHub: 4 | 5 | - Send pull requests for code review. Tag it with `review` when you're done 6 | - Be overly communicative about your pull requests. Best practice is to add screenshots to your pull requests ([example](https://github.com/proudcloud/crowd-funding/pull/371)) for your reviewer's convenience. 7 | - Long running PRs are welcome. Always get your branches checked against the main branch (usually `develop`) 8 | - Get your PRs updated. Rebase on top of the latest `develop` branch. 9 | - If your PR references a Github Issue, make sure to mention it in your PR's description using [this format ](https://help.github.com/articles/closing-issues-via-commit-messages/). 10 | 11 | Git: 12 | 13 | - Always commit. Small commits are acceptable. 14 | - Make your commits contextual. Avoid commits that does other things that the commit was intended to. 15 | - Commit messages that makes sense. Usually in this pattern: `"{action} {purpose|reason} {target}"`, order may vary. 16 | 17 | Avoid: 18 | ``` 19 | 1) "Adds price validation" 20 | 2) "Refactors the decorator" 21 | 3) "Fixes bug" 22 | 4) "Hotfix for the form bug" 23 | ``` 24 | 25 | Ideal: 26 | ``` 27 | 1) "Adds price validation to Product" 28 | 2) "Refactors product.total_price decorator" 29 | 3) "Fixes permitted params bug on orders#create" 30 | 4) "Hotfix for the product form's price input bug" 31 | ``` 32 | 33 | [Here's an example of a good PR and commit](https://github.com/proudcloud/crowd-funding/pull/371) 34 | 35 | - Target as the most important as without it `"Fixes bug"`, `"Adds price validation"` or `"Refactors"` doesn't actually make sense if people review the project commit history. 36 | - Always delete `merged`, `stale`, `outdated` branches. *Ang past ay para sa mga bitter lamang. Wag clingy.* [1](https://github.com/proudcloud/awesome/issues/23#issuecomment-108285010) 37 | 38 | Branching: 39 | 40 | - Use `feature/xyz` branches for features, `fix/xyz` for code fixes, `hotfix/xyz` for emergency hotfixes (see [git-flow]) 41 | - Use the `develop` branch for development 42 | - Use the `master` branch for deployable versions 43 | - Make sure `develop` is always passing CI tests 44 | - Make sure `master` is always at a deployable state 45 | 46 | Avoid: 47 | 48 | - Avoid `production` branches, they're usually the same as master 49 | 50 | [git-flow]: http://nvie.com/posts/a-successful-git-branching-model/ 51 | -------------------------------------------------------------------------------- /practices/issues.md: -------------------------------------------------------------------------------- 1 | # Writing issues 2 | 3 | When filing issues, keep the title short and the body descriptive. 4 | 5 |
6 | 7 | ## Titles 8 | 9 | * **Keep the title short.**
10 | Put any details in the body, not in the title. This makes it easier to digest a long list of issues. 11 | 12 | > `When I try to change passwords, an error is raised.` ✗ *...can be shorter*
13 | > `[User] can't change passwords` ✗ *...put that in the description*
14 | > `Can't change passwords` :+1: 15 | 16 | * **Don't be too general.**
17 | Try to be more specific when possible. 18 | 19 | > `Products error` ✗ *...too broad*
20 | > `Can't buy products` ✗ *...still too broad*
21 | > `Product page error` ✗ *...still too broad*
22 | > `Product page: the buy button isn't clickable` :+1: 23 | 24 |
25 | 26 | ## Details 27 | 28 | * **Write a short description.**
29 | Add a one-sentence (or one-paragraph) in the body of the issue. 30 | 31 | > 32 | > Title: `Can't change passwords`
33 | > Description: 34 | > `When I'm logged into as a User, the "change email" form returns an error.` 35 | 36 | * **Be visual.**
37 | Include screenshots when possible! 38 | 39 | * **Be detailed.**
40 | For bug reports, ensure that the following details are available or are obvious: 41 | 42 | * URL *(if applicable)* 43 | * Environment *(OS, browser, website environment)* 44 | * Steps to reproduce 45 | * Expected result 46 | * Actual result 47 | 48 | * **But not too detailed.**
49 | You don't need to actually list *all* of them (especially for simple issues), just make sure that anyone can figure those details out. 50 | 51 |
52 | 53 | ## Short example 54 | No need to include steps/expected/actual when it's obvious. 55 | 56 | > **Avatars are not shown**
57 | > The user directory is missing avatars. (OS X, Firefox, Production)
58 | > http://ticketadvisor.com/users 59 | > 60 | > `[screenshot goes here]` 61 | 62 | ## Full example 63 | 64 | > **Can't send email**
65 | > The "send email" button isn't clickable.
66 | > Environment: OS X, Firefox, Production.
67 | > http://ticketadvisor.com/user/23/edit 68 | 69 | > `[screenshot goes here]` 70 | 71 | > Steps:
72 | 1. Log in as a user
73 | 2. Go to the Inbox page
74 | 3. Click "write new email"
75 | 4. Click "send"
76 | 77 | > Expected: The email will be sent.
78 | > Actual: A JavaScript error appears when "send" is clicked. 79 | -------------------------------------------------------------------------------- /practices/ember.md: -------------------------------------------------------------------------------- 1 | # Ember 2 | 3 | ##Development 4 | 5 | ###Tools 6 | - [Ember-cli](http://www.ember-cli.com/) for project management 7 | - [ES2015/Babel](https://babeljs.io/) as our JS flavor 8 | - [Sass](http://sass-lang.com/) as our CSS flavor 9 | - [Emblem](http://emblemjs.com/) for templates 10 | - [Ember-data](https://github.com/emberjs/data) for data management 11 | 12 | ###Practices 13 | - Favor [Ember Object Model](http://guides.emberjs.com/v1.11.0/object-model/classes-and-instances/) over plain javascript 14 | 15 | ####Routes 16 | - Ember routes are tightly coupled with view rendering, but let's maintain restful routing as much as possible 17 | 18 | ####Models 19 | - Use [ActiveModel Adapter](http://emberjs.com/api/data/classes/DS.ActiveModelAdapter.html) for data serialization/deserialization 20 | - Load data in store as needed 21 | - Set relationships as async true as needed (be mindful that setting relationships as async true changes the behavior of certain functions) 22 | 23 | ```javascript 24 | //in models/sample.js 25 | export default DS.Model.extend({ 26 | sampleRelationship: DS.belongsTo('anotherModel', {async: true}), 27 | }); 28 | 29 | sampleInstance.get('sampleRelationship'); //Will return a promise object 30 | 31 | //set to async:false 32 | sampleInstance.get('sampleRelationship') //Will return the model 33 | 34 | ``` 35 | 36 | ####Controllers 37 | - Keep application level logic in controllers. 38 | 39 | ```javascript 40 | //route transitions 41 | this.transitionToRoute('sample.route'); 42 | 43 | //data manipulation 44 | sampleModel.save(); 45 | sampleModel.destroy(); 46 | 47 | //ajax requests 48 | Ember.$.ajax('/sample_url'); 49 | ``` 50 | 51 | - Keep api requests logic in one mixin/class and just require it in controllers as needed. 52 | 53 | ####Templates 54 | 55 | ####Components 56 | - favor components over views 57 | - always declare your component's name in its classNames property 58 | 59 | ```javascript 60 | //in sample-component.js 61 | export default Ember.Component.extend({ 62 | classNames: ['sample-component'] 63 | }); 64 | ``` 65 | 66 | - always declare layout related classes in component instantation 67 | 68 | ```javascript 69 | //in sample-component.js 70 | export default Ember.Component.extend({ 71 | //Don't do this 72 | classNames: ['sample-component', 'col-md-5'] 73 | }); 74 | 75 | //instead do it this way 76 | //in page.emblem 77 | sample-component class='col-md-5' 78 | ``` 79 | 80 | - Avoid application level logic here 81 | 82 | ##Helpful Resources 83 | - ember-cli 101 by Adolfo Builes 84 | - Ember [Blog](http://emberjs.com/blog/) - Ember is in active development, we need to sync our practices with new trends. 85 | -------------------------------------------------------------------------------- /workflow/rails-osx.md: -------------------------------------------------------------------------------- 1 | # Basic OS X Machine Setup for RoR Development 2 | ####Pre-requisites 3 | 1. Update to Yosemite(OSX 10.10) from App Store 4 | 5 | 2. Install xCode 6.x 6 | 3. Install xCode Command Line Tools 7 | ``` 8 | $ xcode-select --install 9 | ``` 10 | 4. Install Homebrew & update packages 11 | ``` 12 | $ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 13 | $ brew update 14 | ``` 15 | 5. Verify Homebrew installation 16 | ``` 17 | $ brew doctor 18 | ``` 19 | 20 | ####Setup Git, Homebrew, RVM, & Default Ruby & Gemset 21 | Run GCC then confirm appropriate root privileges 22 | ``` 23 | $ sudo gcc --version 24 | ``` 25 | Setup initial git config 26 | ``` 27 | $ git config --global user.name "Your Real Name" 28 | $ git config --global user.email me@example.com 29 | $ git config -l --global 30 | ``` 31 | Add SSH key 32 | ``` 33 | $ ssh-keygen -t rsa -C "YOUR@EMAIL.com" 34 | ``` 35 | Or copy from existing; create directory 36 | ``` 37 | $ mkdir ~/.ssh 38 | $ cp ~/Downloads/id_rsa ~/.ssh 39 | $ cp ~/Downloads/id_rsa.pub ~/.ssh 40 | ``` 41 | Install RVM and follow additional procedure such as sourcing RVM to profile 42 | ``` 43 | $ \curl -L https://get.rvm.io | bash -s stable --ruby 44 | ``` 45 | Install latest or appropriate ruby version 46 | ``` 47 | $ rvm install ruby 48 | $ rvm --default use ruby-2.2.0 49 | ``` 50 | For faster bundling 51 | ``` 52 | $ echo "gem: --no-ri --no-rdoc" >> ~/.gemrc 53 | ``` 54 | Double ruby version and gemset (default) is active then install 55 | ``` 56 | $ gem install rails 57 | ``` 58 | 59 | ####Install PostgreSQL 60 | ``` 61 | $ brew install postgresql 62 | ``` 63 | > Caveats: If builds of PostgreSQL 9 are failing and you have version 8.x installed, you may need to remove the previous version first. See: 64 | https://github.com/Homebrew/homebrew/issues/2510 65 | 66 | > To migrate existing data from a previous major version (pre-9.4) of PostgreSQL, see: 67 | http://www.postgresql.org/docs/9.4/static/upgrading.html 68 | 69 | To have launchd start postgresql at login 70 | ``` 71 | $ ln -sfv /usr/local/opt/postgresql/*.plist ~/Library/LaunchAgents 72 | ``` 73 | Then to load postgresql now 74 | ``` 75 | $ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.postgresql.plist 76 | ``` 77 | Or, if you don't want/need launchctl, you can just run 78 | ``` 79 | $ postgres -D /usr/local/var/postgres 80 | ``` 81 | You can check back this info by 82 | ``` 83 | $ brew info postgresql 84 | ``` 85 | 86 | #### Install MongoDB 87 | $ brew install mongodb 88 | To have launchd start mongodb at login: 89 | ``` 90 | $ ln -sfv /usr/local/opt/mongodb/*.plist ~/Library/LaunchAgents 91 | ``` 92 | Then to load mongodb now 93 | ``` 94 | $ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mongodb.plist 95 | ``` 96 | Or, if you don't want/need launchctl, you can just run 97 | ``` 98 | $ mongod --config /usr/local/etc/mongod.conf 99 | ``` -------------------------------------------------------------------------------- /workflow/heroku.md: -------------------------------------------------------------------------------- 1 | # Heroku Deployment for Rails 2 | ####Pre-requisites: 3 | - Existing Rails App 4 | - Git & associated SSH Keys 5 | ``` 6 | # If app isn't associated with git yet 7 | $ git init 8 | $ git add . 9 | $ git commit -m 'Sets initial commit' 10 | ``` 11 | ``` 12 | # If no SSH Keys generated yet, run command below; 13 | # Fill-in succeeding prompts as desired but leave out passphrase prompt as empty 14 | $ ssh-keygen -t rsa 15 | ``` 16 | - Heroku Account. Sign up [here]. 17 | - Heroku Toolbelt 18 | ``` 19 | # OSX (via Homebrew) 20 | $ brew install heroku-toolbelt 21 | # Debian/Ubuntu 22 | $ wget -qO- https://toolbelt.heroku.com/install-ubuntu.sh | sh 23 | # Login 24 | $ heroku login 25 | ``` 26 | 27 | 28 | ####Setup: 29 | Specify ruby version in your `Gemfile`. This is clearly ok unless you indicate a different version from that of your `.ruby-version` et al 30 | ``` 31 | source "https://rubygems.org" 32 | ruby "2.1.2" 33 | # ... 34 | ``` 35 | Set static asset serving at `config/application.rb` 36 | ``` 37 | config.serve_static_files = true 38 | ``` 39 | It is expected that credentials/keys are set in your `secrets.yml`(which is included in the repo), just make sure the these are appropriately set within `production: ` block as well 40 | ``` 41 | production: 42 | secret_key_base: 320f4772bb7e84f94f83b05a1e220d6b18c3053e4d601224efbda34434a79183e0f721a7b12c0ae89a91b9eaba092ceba8f145ddb4fd46dc9016fed6202e5a41 43 | ... 44 | development: 45 | secret_key_base: 769579477b78657f832f260b62151d8955b3f3bcdd054cc287d17fe0c75a7524f0d8a07c733c55acbe72e1ce8821e1ef11739a14e525a8443129d26742a10f1f 46 | ... 47 | ``` 48 | Set DB-related configurations differ depending on the DB you are using. If you're on `PostgreSQL`, a simple `heroku run rake db:migrate` will do. 49 | 50 | If you're using `mongoid`, I prefer [MongoLab] as a starting point 51 | 52 | Create Heroku app/instance 53 | ``` 54 | $ heroku apps:create my-very-own-project-such-wow 55 | ``` 56 | Push to Heroku 57 | ``` 58 | $ git push heroku master 59 | ``` 60 | 61 | Open your app deployed from Heroku 62 | ``` 63 | $ heroku open 64 | ``` 65 | **** 66 | 67 | 68 | ####After all this... 69 | ...why not add `rail_12factor` gem to Gemfile? *If you're not concerned with Rails logs being written to file, `config.serve_static_assets = true` is all you need.* 70 | 71 | ...I use `secrets.yml` instead of `application.yml`? *It's a known limitation for using Heroku. Best stick in using `ENV[___]` approach on this one.* 72 | 73 | ...why not set `RAILS_ENV=staging` instead of `production` at my Heroku instance? *1) Dev/Prod Parity; get your prod environment as close as that with your local one by minimizing enviroment-related differences on variables for example, also, 2) it is unlikely that you want a real production app deployed at Heroku.* 74 | 75 | ...why not use `Figaro` for environment variables? *Just use `heroku config:set`* 76 | 77 | ...why not use `Foreman`? *Use it, then!* 78 | 79 | [here]:https://www.heroku.com/ 80 | [MongoLab]:https://devcenter.heroku.com/articles/mongolab -------------------------------------------------------------------------------- /tools/README.md: -------------------------------------------------------------------------------- 1 | # Recommended tools 2 | 3 | ## Code Editors 4 | 5 | - [Vim](http://vim.org/) 6 | - [Atom](https://atom.io/) 7 | - [Emacs](https://www.gnu.org/software/emacs/) with [Spacemacs](https://github.com/syl20bnr/spacemacs) _(actually, only Vic uses this)_ 8 | 9 | ## Vim plugins 10 | 11 | - [neomake](https://github.com/neomake/neomake) - a plugin for asynchronous :make using Neovim's job-control functionality 12 | - [vim-commentary](https://github.com/tpope/vim-commentary) - comment stuff out 13 | - [vim-plug](https://github.com/junegunn/vim-plug) - a minimalist Vim plugin manager 14 | - [vim-surround](https://github.com/tpope/vim-surround) - quoting/parenthesizing made simple 15 | - [YouCompleteMe](https://github.com/Valloric/YouCompleteMe) - a code-completion engine for Vim 16 | 17 | ## Sketch plugins 18 | 19 | - [Sketch Toolbox](https://github.com/buzzfeed/Sketch-Toolbox) - installs sketch plugins for you 20 | - [Invision Craft](https://www.invisionapp.com/craft) - placeholder text and more 21 | - [Clipboard Fill](https://github.com/ScottSavarie/Clipboard-Fill) - paste images as a fill 22 | 23 | ## GIF recorders 24 | 25 | - [LICEcap](http://www.cockos.com/licecap/) (free, OSX, Win) - records to .gif locally 26 | - [Gyazo GIF](https://gyazo.com/) (freemium, OSX, Win, Linux) - records and uploads to the cloud. hosting limited to 10 images/month ($3.99/mo to unlock) 27 | - [Recordit](http://recordit.co/) (freemium, OSX, Win) - records and uploads to the cloud. unlock private recordings and higher FPS with the pro version for $29 28 | - [CloudApp](https://www.getcloudapp.com/) (freemium, OSX) - limited to 10 files ($10/mo to unlock) 29 | - [Claquette](https://www.peakstep.com/claquette/) $9.99 with addons for more export options 30 | 31 | ## OSX (Design) 32 | 33 | - [Sip](http://sipapp.io/) (freemium) - color picker 34 | - [Adobe Creative Cloud](https://creative.adobe.com/products/creative-cloud) (free) - for TypeKit fonts on your computer 35 | 36 | ## Chrome extensions 37 | 38 | - [Vimium](https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb?hl=en) - Vim on Chrome 39 | - [JSONView](https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc?hl=en) - Format JSON responses 40 | - [EyeDropper](https://chrome.google.com/webstore/detail/eye-dropper/hmdcmlfkchdmnmnmheododdhjedfccka) - Colorpicker 41 | - [Panda](https://usepanda.com/) - Newsfeed Dashboard for Design and Development 42 | - [WhatFont](https://chrome.google.com/webstore/detail/whatfont/jabopobgcpjmedljpbcaablpmlmfcogm?hl=en) - Easiest to identify fonts in web pages 43 | - [Window Resizer](https://chrome.google.com/webstore/detail/window-resizer/kkelicaakdanhinjdeammmilcgefonfh?hl=en) - Resize browser window to emulate various screen resolutions 44 | - [Raindrop](http://raindrop.io/extension/) - For bookmarks 45 | 46 | ## How to add to this list 47 | 48 | - Send a PR. 49 | - Have someone +1 it—we won't add something just because you use it! Unless you're Vic. 50 | - Bug for someone not to be too lazy to merge your PR 51 | -------------------------------------------------------------------------------- /practices/react-redux.md: -------------------------------------------------------------------------------- 1 | # React Redux 2 | 3 | ## Containers vs. Components 4 | 5 | Separate your containers from your components. 6 | 7 | - Containers are smart components. They do data-fetching and pass it to components. 8 | - Components are dumb and reliant to containers for their data. Since they are relaint to containers, they can be reused in other containers. 9 | 10 | See: [Making your app fast with high-performance components by Jason Bonta](https://youtu.be/KYzlpRvWZ6c?t=22m49s) 11 | 12 | ## Suggested File structure 13 | 14 | The suggested file structure is based on @adimasuhid's idea. If you have a directory and it was removed, the app should be still functional or needs minimal changes to make it work. 15 | 16 | This also allows reusable features through other applications such as `chat` and `filtering`. 17 | 18 | ``` 19 | react 20 | └───(Feature) 21 | │ └───components 22 | │ └───containers 23 | │ │ actions.jsx - action creator functions 24 | │ │ actionTypes.jsx 25 | │ │ apiWrappers.jsx 26 | │ │ reducer.jsx - reducer to be used in the store 27 | │ │ propTypes.jsx - reusable proptypes 28 | └───(Shared Components) 29 | └───App.jsx - main entrypoint 30 | └───configureStore.jsx - store builder 31 | └───DevTools.jsx 32 | └───rootReducer.jsx 33 | ``` 34 | 35 | ## `mapStateToProps`, `mapDispatchToProps` and `connect` 36 | 37 | There are some examples in the `redux` repository that show you can use a function for getting the object needed for `mapStateToProps`. We recommend that you use this example below for verbosity. 38 | 39 | ```js 40 | const mapStateToProps = (state) => { 41 | return { 42 | component: state.component.attribute 43 | } 44 | } 45 | ``` 46 | 47 | `mapDispatchToProps` can be omitted unless you want to. It can be written like this: 48 | 49 | ```js 50 | const mapDispatchToProps = (dispatch) => { 51 | return { 52 | function: () => { namedFunction() } 53 | } 54 | } 55 | 56 | export default connect( 57 | mapStateToProps, 58 | mapDispatchToProps 59 | )(Container) 60 | ``` 61 | 62 | or 63 | 64 | ```js 65 | export default connect( 66 | mapStateToProps, 67 | { namedFunction } 68 | )(Container) 69 | ``` 70 | 71 | ## Configuring the Store 72 | 73 | The `compose` function allows you to add different middlewares such as `redux-thunk` and `redux-devtools`. 74 | 75 | ```js 76 | export default configureStore(initialState = {}, environment) => { 77 | const store = createStore( 78 | rootReducer, 79 | initialState, 80 | compose( 81 | applyMiddleware(thunk) 82 | ) 83 | ) 84 | } 85 | ``` 86 | 87 | Here are some middlewares you might want to check out: 88 | - [redux-thunk](https://github.com/gaearon/redux-thunk) 89 | - [redux-saga](https://github.com/yelouafi/redux-saga) 90 | - [redux-promise-middleware](https://github.com/pburtchaell/redux-promise-middleware) 91 | 92 | See [this StackOverflow answer](http://stackoverflow.com/questions/36577510/what-is-the-difference-between-redux-thunk-and-redux-promise) on the difference between redux-thunk and redux-promise. 93 | -------------------------------------------------------------------------------- /practices/react-native.md: -------------------------------------------------------------------------------- 1 | # React Native 2 | 3 | This is a collection of (best?) practices when developing React Native apps--the Proudcloud way. 4 | 5 | Basic prerequisites of developing React Native apps include [React](https://facebook.github.io/react/) 6 | and [Redux](http://redux.js.org/). If you don't even have a slightest clue on what you're doing, STOP. 7 | Please do us a favor: read [Thinking In React](https://facebook.github.io/react/docs/thinking-in-react) 8 | and create sample apps before even jumping on-board a project. This will save us time spent on nonsense 9 | code reviews. 10 | 11 | ## Proposed File Structure 12 | 13 | Given that we have a Blog app with basic CRUD functionalities, below is its proposed file structure: 14 | 15 | ``` 16 | project 17 | `- android - Android Studio project 18 | `- ios - Xcode project 19 | `- js 20 | `- actions 21 | `- post.js 22 | `- user.js 23 | `- assets 24 | `- fonts 25 | `- images 26 | `- ... 27 | `- components 28 | `- common - Shared components like forms, buttons, etc. 29 | `- Button.js 30 | `- FacebookButton.js 31 | `- ... 32 | `- PostList.js 33 | `- PostDetails.js 34 | `- RegistrationForm.js 35 | `- LoginForm.js 36 | `- ... 37 | `- config 38 | `- index.js - You can probably load environment variables in this file 39 | `- facebook.js - Sample Facebook-related config. You can load this in config/index.js 40 | `- containers 41 | `- posts 42 | `- New.js 43 | `- Edit.js 44 | `- List.js 45 | `- sessions 46 | `- Registration.js 47 | `- Login.js 48 | `- reducers 49 | `- index.js - This is the root reducer 50 | `- posts.js 51 | `- users.js 52 | `- store 53 | `- configureStore.js 54 | `- utils - Any utility classes/helpers go here 55 | App(.ios/.android).js - Main React class. Omit .ios or .android as necessary 56 | `- node_modules 57 | index.android.js 58 | index.ios.js 59 | package.json 60 | ``` 61 | 62 | ## Containers vs. Components 63 | 64 | As mentioned in https://github.com/proudcloud/awesome/blob/master/practices/react-redux.md 65 | 66 | > Separate your containers from your components. 67 | 68 | > - Containers are smart components. They do data-fetching and pass it to components. 69 | > - Components are dumb and reliant to containers for their data. Since they are relaint to containers, they can be reused in other containers. 70 | 71 | > See: [Making your app fast with high-performance components by Jason Bonta](https://youtu.be/KYzlpRvWZ6c?t=22m49s) 72 | 73 | Or in iOS Development terms, think of Containers as View Controllers and Components as separate Views. 74 | 75 | 76 | ## Further Reading 77 | 78 | Here are great articles for further reading: 79 | - [React Native Getting Tutorial](https://facebook.github.io/react-native/docs/tutorial.html) 80 | - [React Native Awesome](https://github.com/enaqx/awesome-react#react-native) 81 | - [Building the F8 2016 App](http://makeitopen.com/) 82 | - [Preview your React Native apps in your Github Pull Request](http://tech.m6web.fr/preview-android-ios-react-native-on-github-pull-request/) 83 | 84 | 85 | ## Deep Dive 86 | 87 | If you need a good jumpstart, try following [Building the F8 2016 App](http://makeitopen.com/). 88 | It's a great starting point for begginers and a good refresher for intermediate React Native developers. 89 | -------------------------------------------------------------------------------- /workflow/elixir.md: -------------------------------------------------------------------------------- 1 | # Setup for Elixir projects 2 | 3 | It's mostly the same as setting up environments for Ruby or JavaScript, with some nuances: 4 | 5 | - [Postgres](#postgres): to make your life easier, create a user with name `postgres` password `postgres`. This is the default for most Phoenix projects. 6 | - [Asdf](#asdf): this is the preferred version manager for Elixir, Erlang and Node.js. 7 | 8 | All of these steps are optional, but recommended. 9 | 10 |
11 | 12 | ## Postgres 13 | 14 | > Phoenix projects default to connecting to Postgres with the username `postgres` and password `postgres`. This isn't so easy to override, so let's just keep that as the default. 15 | 16 | * __Install postgres.__ In OSX, use [Homebrew](http://brew.sh/) to install it. 17 | 18 | ```sh 19 | # OSX only 20 | brew install postgres 21 | ``` 22 | 23 | * Use [homebrew/services](http://github.com/homebrew/homebrew-services) to start Postgres. Optional but recommended. 24 | 25 | ```sh 26 | # OSX only 27 | brew tap homebrew/services 28 | brew services start postgres 29 | ``` 30 | 31 | * __Create a `postgres` user.__ Use PostgreSQL's `createuser` to create a new user. Give it a password `postgres`. 32 | 33 | ```sh 34 | $ createuser --superuser postgres -P 35 | Enter password for new role: 36 | Enter it again: 37 | ``` 38 | 39 |
40 | 41 | ## asdf 42 | 43 | > [Asdf](https://github.com/asdf-vm/asdf) is a version manager for everything: Ruby, Elixir, Erlang, Node.js, and so on. 44 | 45 | * __Install asdf__ via git. 46 | 47 | ```sh 48 | git clone https://github.com/asdf-vm/asdf.git ~/.asdf 49 | ``` 50 | 51 | * __Add it to bashrc.__ (If you're on zsh, add it to `~/.zshrc`. For fish shell and others, see [asdf setup docs](https://github.com/asdf-vm/asdf#setup)). 52 | 53 | ```sh 54 | # bash / Ubuntu 55 | echo '. $HOME/.asdf/asdf.sh' >> ~/.bashrc 56 | echo '. $HOME/.asdf/completions/asdf.bash' >> ~/.bashrc 57 | ``` 58 | 59 | ```sh 60 | # bash / OSX 61 | echo '. $HOME/.asdf/asdf.sh' >> ~/.bash_profile 62 | echo '. $HOME/.asdf/completions/asdf.bash' >> ~/.bash_profile 63 | ``` 64 | 65 | ```sh 66 | # Zsh 67 | echo '. $HOME/.asdf/asdf.sh' >> ~/.zshrc 68 | echo '. $HOME/.asdf/completions/asdf.bash' >> ~/.zshrc 69 | ``` 70 | 71 | * __Add plugins__ for Erlang, Elixir and Node.js. 72 | 73 | ```sh 74 | asdf plugin-add erlang https://github.com/asdf-vm/asdf-erlang.git 75 | asdf plugin-add elixir https://github.com/asdf-vm/asdf-elixir.git 76 | asdf plugin-add nodejs https://github.com/asdf-vm/asdf-nodejs.git 77 | ``` 78 | 79 |
80 | 81 | ## Install Erlang/Elixir/Node.js 82 | 83 | * If you have a project with a `.tool-versions`, simply run `asdf install`. 84 | 85 | ```sh 86 | cd my-project 87 | asdf install 88 | ``` 89 | 90 | * To configure "global" versions in asdf, create `~/.tool-versions`. Here's a fair starting point. 91 | 92 | ```sh 93 | # These are stable versions as of April 2017. 94 | # To check newer versions, use: `asdf list-all nodejs` 95 | cd ~ 96 | echo 'erlang 19.2' >> .tool-versions 97 | echo 'nodejs 6.10.2' >> .tool-versions 98 | echo 'elixir 1.4.2' >> .tool-versions 99 | asdf install 100 | ``` 101 | 102 |
103 | 104 | ## Alternatives 105 | 106 | * [Postgres.app](http://postgresapp.com/) is another way to install Postgres. 107 | * [Kiex](https://github.com/taylor/kiex) is an Elixir version manager. It doesn't manage Erlang installations (a dependency of Elixir), however. 108 | * You may also install Erlang and Elixir via Homebrew, though it may be difficult to switch versions later on. 109 | -------------------------------------------------------------------------------- /practices/rails.md: -------------------------------------------------------------------------------- 1 | # Rails 2 | 3 | In general: 4 | 5 | - Prefer to commit your `config/*.yml` files, except database.yml (_PRIVATE_ _REPOS_ _ONLY!_) 6 | - Make use of special Rails ANNOTATIONS like `TODO`, `FIXME`, and `OPTIMIZE` so rake notes can pick it up. 7 | - Keep README.md updated (always assume a new team member will join anytime) 8 | 9 | CSS and JS: 10 | 11 | - Prefer [sass-rails](https://github.com/rails/sass-rails) as a preprocessor 12 | - Prefer [autoprefixer-rails](https://github.com/ai/autoprefixer-rails) for vendor prefixes 13 | - Prefer [haml](http://haml.info/) for templating (via [hamlit-rails](https://rubygems.org/gems/hamlit-rails)) 14 | - Prefer [bootstrap](http://getbootstrap.com) if a CSS framework is needed 15 | - Prefer [bootstrap-sass](https://github.com/twbs/bootstrap-sass) for Bootstrap + Rails integration 16 | - Prefer [rails-assets.org](https://rails-assets.org) for managing 3rd-party JS/CSS 17 | - Prefer [konacha](github.com/jfirebaugh/konacha) for JS unit testing 18 | 19 | Server: 20 | 21 | - Prefer [puma](http://puma.io/) even in development (for multi-threaded support) 22 | 23 | Style Guides: 24 | 25 | - Adhere to [rsjs](https://github.com/rstacruz/rsjs) when writing JS 26 | 27 | Emails: 28 | 29 | - Prefer [letter_opener](https://rubygems.org/gems/letter_opener) for locally testing emails 30 | - Prefer [premailer-rails](https://rubygems.org/gems/premailer-rails) for managing inline email CSS 31 | 32 | Rake tasks: 33 | 34 | - Ensure `db:migrate` runs properly 35 | - Ensure `db:rollback` runs properly 36 | - Ensure `db:seed` runs properly (They get outdated fast!). Alternatively, provide a way to seed a newcomer's project. 37 | - Ensure painless turnovers 38 | 39 | Configuration: 40 | 41 | - Use `config/secrets.yml` to store config 42 | - Use 12-factor style when overrides are needed: `pusher_id: <%= ENV['PUSHER_ID'] || '...' %>` 43 | - Access them in your app via `Rails.application.secrets.pusher_id` 44 | 45 | Avoid: 46 | 47 | - Avoid [less-rails](https://github.com/metaskills/less-rails/). Slow to update, and doesn't support [import globbing](https://github.com/less/less.js/issues/1181) 48 | - Avoid [compass](http://compass-style.org/) unless necessary. Use autoprefixer instead 49 | - Avoid [bootstrap-on-rails](https://github.com/jasontorres/bootstrap-on-rails) because it's .less and not currently maintained 50 | - Avoid [twitter-bootstrap-rails](https://github.com/seyhunak/twitter-bootstrap-rails) because it's .less and has too many abstractions 51 | - Avoid [coffeescript](http://coffeescript.org/). Prefer to use [sprockets-es6](https://rubygems.org/gems/sprockets-es6) instead. ([article](https://robots.thoughtbot.com/replace-coffeescript-with-es6)) 52 | - Avoid [bower-rails](https://rubygems.org/gems/bower-rails). Heroku setup can be a pain, and rails-assets is a better choice nowadays. 53 | - Avoid configuration gems like [figaro](http://rubygems.org/gems/figaro), [dotenv](http://rubygems.org/gems/dotenv), etc. Rails 4.1 should render them useless now. 54 | - Avoid [teaspoon](https://github.com/modeset/teaspoon). It has more boilerplate to setup, and doesn't sandbox your test DOM unlike konacha. Use konacha instead 55 | - Avoid [Enums](http://api.rubyonrails.org/v4.1/classes/ActiveRecord/Enum.html). They can cause non-obvious problems with queries ([1](https://hackhands.com/ruby-on-enums-queries-and-rails-4-1/#queries-on-enums), [2](https://bendyworks.com/rails-enum-sharp-knife/), [3](https://github.com/proudcloud/awesome/pull/56#issuecomment-219984596)). Use strings instead. 56 | 57 | ## Also see 58 | 59 | - **[Design practices](design.md#sass)** (covers Sass) 60 | - **[JavaScript practices](javascript.md)** (covers ES6) 61 | - **[Testing practices](testing.md)** (covers Rspec) 62 | - **[Git practices](git.md)** (covers Git and GitHub) 63 | -------------------------------------------------------------------------------- /workflow/rails-ubuntu1404.md: -------------------------------------------------------------------------------- 1 | # Ubuntu 14.04 Trusty Tahr Setup for RoR Development 2 | --- 3 | ####Installing Ruby 4 | --- 5 | Install Ruby dependencies 6 | ``` 7 | sudo apt-get update 8 | sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties libffi-dev 9 | ``` 10 | Install Ruby (choose one of the methods below) 11 | 12 | * Rbenv 13 | ``` 14 | cd 15 | git clone git://github.com/sstephenson/rbenv.git .rbenv 16 | echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc 17 | echo 'eval "$(rbenv init -)"' >> ~/.bashrc 18 | exec $SHELL 19 | git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build 20 | echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc 21 | exec $SHELL 22 | git clone https://github.com/sstephenson/rbenv-gem-rehash.git ~/.rbenv/plugins/rbenv-gem-rehash 23 | rbenv install 2.2.2 24 | rbenv global 2.2.2 25 | ruby -v 26 | ``` 27 | * RVM 28 | ``` 29 | sudo apt-get install libgdbm-dev libncurses5-dev automake libtool bison libffi-dev 30 | curl -L https://get.rvm.io | bash -s stable 31 | source ~/.rvm/scripts/rvm 32 | rvm install 2.2.2 33 | rvm use 2.2.2 --default 34 | ruby -v 35 | ``` 36 | * Compile from Source 37 | ``` 38 | cd 39 | wget http://ftp.ruby-lang.org/pub/ruby/2.2/ruby-2.2.2.tar.gz 40 | tar -xzvf ruby-2.2.2.tar.gz 41 | cd ruby-2.2.2/ 42 | ./configure 43 | make 44 | sudo make install 45 | ruby -v 46 | ``` 47 | Install bundler 48 | * To skip installation of documentation for each package (Optional) 49 | ``` 50 | echo "gem: --no-ri --no-rdoc" >> ~/.gemrc 51 | ``` 52 | * Install Bundler 53 | ``` 54 | gem install bundler 55 | ``` 56 | --- 57 | ####Setting up Git 58 | --- 59 | * Setup initial git configuration 60 | ``` 61 | git config --global color.ui true 62 | git config --global user.name "YOUR NAME" 63 | git config --global user.email "YOUR@EMAIL.com" 64 | ``` 65 | * Generate SSH key 66 | ``` 67 | ssh-keygen -t rsa -C "YOUR@EMAIL.com" 68 | ``` 69 | * Or copy from existing; create directory 70 | ``` 71 | $ mkdir ~/.ssh 72 | $ cp ~/Downloads/id_rsa ~/.ssh 73 | $ cp ~/Downloads/id_rsa.pub ~/.ssh 74 | ``` 75 | * Add key to Github 76 | ``` 77 | cat ~/.ssh/id_rsa.pub 78 | ``` 79 | * Test git 80 | ``` 81 | ssh -T git@github.com 82 | ``` 83 | --- 84 | ####Installing Rails 85 | --- 86 | * Install NodeJS 87 | ``` 88 | sudo add-apt-repository ppa:chris-lea/node.js 89 | sudo apt-get update 90 | sudo apt-get install nodejs 91 | ``` 92 | * Install Rails 93 | ``` 94 | gem install rails -v 4.2.1 95 | ``` 96 | If you are using rbenv 97 | ``` 98 | rbenv rehash 99 | ``` 100 | * Check if rails has been installed 101 | ``` 102 | rails -v 103 | ``` 104 | --- 105 | ####Setting Up MySQL 106 | --- 107 | * Install MySQL 108 | ``` 109 | sudo apt-get install mysql-server mysql-client libmysqlclient-dev 110 | ``` 111 | --- 112 | ####Setting Up PostgreSQL 113 | --- 114 | * Install PostgreSQL 115 | ``` 116 | sudo sh -c "echo 'deb http://apt.postgresql.org/pub/repos/apt/ precise-pgdg main' > /etc/apt/sources.list.d/pgdg.list" 117 | wget --quiet -O - http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc | sudo apt-key add - 118 | sudo apt-get update 119 | sudo apt-get install postgresql-common 120 | sudo apt-get install postgresql-9.3 libpq-dev 121 | ``` 122 | 123 | * Run Postgres 124 | ``` 125 | sudo /etc/init.d/postgresql start 126 | ``` 127 | 128 | * Setup postgres user 129 | ``` 130 | sudo -u postgres createuser mark -s 131 | sudo -u postgres psql 132 | postgres=# \password mark 133 | ``` 134 | --- 135 | ####Setting Up MongoDB 136 | --- 137 | * Import MongoDB's public key 138 | ``` 139 | sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10 140 | ``` 141 | * Create list file for MongoDB 142 | ``` 143 | echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list 144 | ``` 145 | * Install MongoDB 146 | ``` 147 | sudo apt-get update 148 | sudo apt-get install -y mongodb-org 149 | ``` 150 | * Start MongoDB 151 | ``` 152 | sudo service mongod start 153 | ``` 154 | -------------------------------------------------------------------------------- /practices/qa.md: -------------------------------------------------------------------------------- 1 | ## QA Guidelines 2 | 3 | ###What is Testing? 4 | ####Testing includes the following activities: 5 | * Planning and control. 6 | * Choosing test conditions. 7 | * Designing and executing test cases. 8 | * Checking results. 9 | * Evaluating exit criteria. 10 | * Reporting on the testing process and system under test. 11 | * Finalizing or completing closure activities after a test phase has been completed. 12 | * Reviewing documents (including source code). 13 | * Conducting static analysis. 14 | 15 | ###Why is Testing necessary? 16 | 17 | Humans are fallible. We are prone to errors and we can be affected by time pressure, complex code, complex infrastructure, changing technologies, and/or many system interactions. So testing can have the following objectives: 18 | 19 | 1. Finding defects. 20 | 2. Gaining confidence about the level of quality of the product. 21 | 3. Providing information for decision making. 22 | 4. Preventing defects before the product is released for operational use. 23 | 24 | These objectives can change depending on the viewpoint why testing is done. For Example: 25 | 26 | 1. Development Testing (Component, Integration, System Testing) 27 | * Main objective may be to cause as many failures as possible so that they can be identified and fixed. 28 | 2. Acceptance Testing 29 | * Main objective may be to confirm that system works as expected, to gain the confidence that it has met the requirements. 30 | * In some cases it may be just to assess the quality of the software (with no intention of fixing defects), to give information to stakeholders of the risk of releasing the system at a given time. 31 | 3. Maintenance and Regression Testing. 32 | * This includes testing to ensure that no new defects have been introduced during development of changes. 33 | 34 | ###Seven Testing Principles 35 | 36 | These are general guidelines for testing. 37 | 38 | 1. Testing shows presence of defects 39 | * Testing can show that defects are present, but cannot prove that there are no defects. Testing reduces the probability of undiscovered defects remaining in the software but, even if no defects are found, it is not a proof of correctness. 40 | 2. Exhaustive testing is impossible. 41 | * Testing everything (all combinations of inputs and preconditions) is not feasible except for trivial cases. Instead of exhaustive testing, risk analysis and priorities should be used to focus testing efforts. 42 | 3. Early testing. 43 | * To find defects early, testing activities shall be started as early as possible in the software or system development life cycle, and shall be focused on defined objectives. 44 | 4. Defect clustering. 45 | * Testing effort shall be focused proportionally to the expected and later observed defect density of modules. A small number of modules usually contains most of the defects discovered during pre-release testing, or is responsible for most of the operational failures. 46 | 5. Pesticide paradox. 47 | * If the same tests are repeated over and over again, eventually the same set of test cases will no longer find any new defects. To overcome this “pesticide paradox”, test cases need to be regularly reviewed and revised, and new and different tests need to be written to exercise different parts of the software or system to find potentially more defects. 48 | 6. Testing is context dependent. 49 | * Testing is done differently in different contexts. For example, safety-critical software is tested differently from an e-commerce site. 50 | 7. Absence-of-errors fallacy. 51 | * Finding and fixing defects does not help if the system built is unusable and does not fulfill the user's’ needs and expectations. 52 | 53 | ###Fundamental Test Process 54 | 55 | Test execution is the most visible part of testing. But to be effective and efficient, test plans should include time to be spent on planning the tests, designing test cases, preparing for execution and evaluation of results. The fundamental test process is consisted of the following main activities: 56 | 57 | 1. Test planning and control. 58 | 2. Test analysis and design. 59 | 3. Test implementation and execution. 60 | 4. Evaluating exit criteria and reporting. 61 | 5. Test closure activities. 62 | 63 | Although logically sequential, the activities in the process may overlap or take place concurrently. 64 | -------------------------------------------------------------------------------- /read/README.md: -------------------------------------------------------------------------------- 1 | # Required reading 2 | 3 | This is a curated listing of all must-read resources for the builders of Proudcloud. 4 | 5 | To add a link, add an item on top (newest first). Feel free to create sections as needed. 6 | 7 | ## Design 8 | 9 | - [Design Machines: How to survive the digital apocalypse](https://louderthanten.com/coax/design-machines) 10 | - [A Book Apart](http://abookapart.com/) 11 | - [100 Things Every Designer Needs to Know About People](http://www.amazon.com/Things-Designer-People-Voices-Matter/dp/0321767535) 12 | - [Web UI Design Best Practices](http://www.uxpin.com/web-ui-design-best-practices.html) by UXPin (free) 13 | - [HTML and CSS: Design and Build Websites](http://www.htmlandcssbook.com/) by Jon Duckett 14 | - [JavaScript and JQuery: Interactive Front-End Web Development ](http://javascriptbook.com/) by Jon Duckett 15 | - [Steal Like An Artist](http://austinkleon.com/steal/) by Austin Kleon 16 | - [Design as Art](http://www.amazon.com/Design-as-Art-Bruno-Munari/dp/0141035811) by Bruno Munari 17 | - [Professional Web Typography](https://prowebtype.com) by Donny Truong 18 | - [Hacker Shelf: Collection of free books for the intellectually curious](http://hackershelf.com/browse/?popular=1) 19 | - [Optical Adjustment](https://medium.com/@lukejonesme/optical-adjustment-b55492a1165c) 20 | - [Free Books for Web Design 2014](http://speckyboy.com/2015/01/12/free-web-design-ebooks-2014/) 21 | - [Photoshop Etiquette](http://www.photoshopetiquette.com/) 22 | - [Facebook Visual Identity](http://officeofbenbarry.com/see/facebook-visual-identity) - insight on branding process 23 | - [How to be a graphic designer without losing your soul](http://www.amazon.com/Graphic-Designer-without-Expanded-Edition/dp/1568989830) by Adrian Shaughnessy 24 | - [rscss: Reasonable System for CSS Stylesheet Structure](https://github.com/rstacruz/rscss) 25 | 26 | #### Repos 27 | - [Web Design Repo](http://www.webdesignrepo.com/) 28 | - [Web Designer Depot](http://www.webdesignerdepot.com/) 29 | - [Unheap](http://www.unheap.com/) 30 | - [Design Leaks](http://designleaks.net/) 31 | - [Psddd](http://psddd.co/) 32 | - [Method & Craft](http://methodandcraft.com/) 33 | - [Makerbook](http://makerbook.net/) 34 | 35 | ## JavaScript 36 | 37 | - [Essential Javascript Links](https://github.com/ericelliott/essential-javascript-links) 38 | - [JavaScript: The Good Parts](http://shop.oreilly.com/product/9780596517748.do) 39 | - [You don't know JavaScript](https://github.com/getify/You-Dont-Know-JS) 40 | - [Things Every Javascript Developer Should Know](http://www.devbattles.com/en/sand/post-1427-Things+Every+Javascript+Developer+Should+Know) 41 | - [Airbnb JavaScript style guide](https://github.com/airbnb/javascript) 42 | - [ES6 Features](git.io/es6features) 43 | 44 | ## Ruby 45 | 46 | - [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) 47 | - [Metaprogramming Ruby](https://pragprog.com/book/ppmetr/metaprogramming-ruby) 48 | 49 | ## Vim 50 | 51 | - [A Byte of Vim](http://www.swaroopch.com/notes/vim/) 52 | - [The Vim Book](http://www.oualline.com/vim-book.html) 53 | - [Learn Vimscript the Hard Way](http://learnvimscriptthehardway.stevelosh.com/) 54 | - [Vim Galore](https://github.com/mhinz/vim-galore) 55 | 56 | ## Coding 57 | - [Pragmatic Programmer](http://www.amazon.com/Pragmatic-Programmer-Journeyman-Master/dp/020161622X) 58 | - [Clean Coder](http://www.amazon.com/The-Clean-Coder-Professional-Programmers/dp/0137081073) 59 | - [Programmers Rantings](http://www.amazon.com/Programmers-Rantings-Programming-Language-Religions-Philosophies-ebook/dp/B00AGXSIXW) 60 | 61 | ## Culture 62 | - [Onboarding](http://blog.mailchimp.com/maintaining-company-culture-through-onboarding/) 63 | - [Team Debt](https://kateheddleston.com/blog/onboarding-and-the-cost-of-team-debt) 64 | 65 | ## Life 66 | - [Personal MBA](http://www.amazon.com/Personal-MBA-Master-Art-Business/dp/1591845572/) 67 | - [Rich Dad, Poor Dad](http://www.amazon.com/Rich-Dad-Poor-Teach-Middle/dp/1612680011/) 68 | - [How to Win Friends and Influence 69 | People](http://www.amazon.com/How-Win-Friends-Influence-People/dp/0671027034) 70 | 71 | ## iOS 72 | 73 | - [The iOS Design Guidelines](http://iosdesign.ivomynttinen.com/) 74 | - [iOS Human Interface Guidelines](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/) 75 | - [Swift Style Guide](https://github.com/raywenderlich/swift-style-guide) 76 | 77 | ## Testing 78 | - [Economy of Tests](http://stakeholderwhisperer.com/posts/2015/1/economy-of-tests) 79 | 80 | ## License 81 | 82 | MIT 83 | 84 | Feel free to reuse this list for your own team! 85 | -------------------------------------------------------------------------------- /practices/i18n.md: -------------------------------------------------------------------------------- 1 | # Rails i18n practices 2 | 3 | Rails gives us [localization features](http://guides.rubyonrails.org/i18n.html) via the rails-i18n gem. While the Rails guide describes the technical details on how to use it, it doesn't prescribe any guidelines on how to name and sort your localization strings. Here's my take on how a project's I18n strings should be sorted out. 4 | 5 | * * * * 6 | 7 | ### Quote your strings 8 | While the YAML format is liberal and quotation marks aren't needed, the consistency is always welcome. It also makes it less ambiguous for non-developers who may edit the YAML file. 9 | 10 | ```coffee 11 | en: 12 | posts: 13 | index: 14 | title: "Blog posts" 15 | description: "These are the latest posts in the blog." 16 | ``` 17 | 18 | ### Don't add punctuation 19 | Some strings end in `:`. Don't place them in the YAML file. This will allow for the strings to be reusable later on. 20 | 21 | ```rb 22 | t('.categories') + ":" 23 | ``` 24 | 25 | ### Group by controller and action 26 | Place your page's strings under their respective `controller` and `action` names. This allows to you take advantage of Rails's shortcuts. Also, always name your primary title as `title`. 27 | 28 | ```rb 29 | # looks up 'posts.index.title', if you're on the posts#index view 30 | t('.title') 31 | ``` 32 | 33 | > See: [lazy lookup](http://guides.rubyonrails.org/i18n.html#lazy-lookup) (guides.rubyonrails.org) 34 | 35 | ### Group strings for partials 36 | The same concept should apply for partials. You can also use the `t('.login')` shortcut inside partial views. 37 | 38 | ```coffee 39 | en: 40 | shared: 41 | nav: 42 | back_to_home: "Back to home" 43 | login: "Log in" 44 | ``` 45 | 46 | ### Avoid top-level strings 47 | Don't place strings on the top level such as `t('and')`. Place them on a parent, even an arbitrary one. If you can't think of a parent name, use `common`. 48 | 49 | ```coffee 50 | en: 51 | actions: 52 | submit: "Submit" 53 | add: "Add" 54 | delete: "Delete" 55 | login: "Log in" 56 | common: 57 | or: "or" 58 | and: "and" 59 | ``` 60 | 61 | ### Avoid over nesting 62 | Prefer to nest with just one level. Overly-complicated nesting can seem very arbitrary and confusing. 63 | 64 | ```coffee 65 | # Avoid 66 | en: 67 | user: 68 | mail: 69 | status: 70 | delivered: "Delivered" 71 | read: "Read" 72 | ``` 73 | 74 | ```coffee 75 | # Better 76 | en: 77 | mail_status: 78 | delivered: "Delivered" 79 | read: "Read" 80 | ``` 81 | 82 | ### Familiarize yourself with defaults 83 | The default locale file is available under rails-i18n. 84 | 85 | > See: [locale/en.yml](https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en.yml). (svenfuchs/rails-i18n) 86 | 87 | 88 |
89 | 90 | ## Time and date 91 | 92 | ### Don't use .strftime 93 | Use i18n to format timestamps. Define your time formats in `time.formats`. Listed below are the default time formats available in Rails. 94 | 95 | ```rb 96 | l(Time.now, format: :short) 97 | ``` 98 | 99 | ```coffee 100 | en: 101 | time: 102 | formats: 103 | default: "%a, %d %b %Y %H:%M:%S %z" 104 | short: "%d %b %H:%M" 105 | ``` 106 | 107 | ### Same with dates 108 | The `I18n.l` method also supports dates. Also, when creating new formats, add comments on what they should look like to help your teammates along. 109 | 110 | ```rb 111 | l(Date.today, format: :long) 112 | ``` 113 | 114 | ```yml 115 | en: 116 | date: 117 | formats: 118 | default: "%Y-%m-%d" # 2015-06-25 119 | long: "%B %d, %Y" # June 25, 2015 120 | short: "%b %d" # Jun 25 121 | ``` 122 | 123 | > See: [Adding date time formats](http://guides.rubyonrails.org/i18n.html#adding-date-time-formats) (guides.rubyonrails.org) 124 | 125 |
126 | 127 | ## Forms 128 | 129 | ### Use ActiveRecord errors 130 | The Rails method [full_messages](http://devdocs.io/rails/activemodel/errors#method-i-full_messages) looks up in predefined locations in your locale file. Take advantage of them. See [the cheatsheet](http://ricostacruz.com/cheatsheets/rails-i18n.html) for more. 131 | 132 | ```rb 133 | person = Person.create 134 | person.errors.full_messages 135 | #=> ["Name is too short (minimum is 5 characters)", 136 | # "Name can't be blank", "Email can't be blank"] 137 | ``` 138 | 139 | ``` 140 | activerecord.errors.models.[model_name].attributes.[attribute_name].[error] 141 | activerecord.errors.models.[model_name].[error] 142 | activerecord.errors.messages.[error] 143 | errors.attributes.[attribute_name].[error] 144 | errors.messages.[error] 145 | ``` 146 | 147 | > See: [Translations for the error_messages_for helper](http://guides.rubyonrails.org/i18n.html#translations-for-the-active-record-error-messages-for-helper) (guides.rubyonrails.org) 148 | 149 | ### Use form labels 150 | There are also conventions on where [f.label](http://devdocs.io/rails/actionview/helpers/formbuilder#method-i-label) will look up labels. 151 | 152 | ```rb 153 | form_for @post do 154 | f.label :body 155 | ``` 156 | 157 | ```coffee 158 | helpers: 159 | # helpers.label.. 160 | label: 161 | post: 162 | body: "Your body text" 163 | ``` 164 | -------------------------------------------------------------------------------- /workflow/ios.md: -------------------------------------------------------------------------------- 1 | # iOS Development Workflow 2 | 3 | ## Setting up a new project 4 | 5 | 1. Create a new project 6 | 7 | 1. __File__ -> __New__ -> __Project__ or press `SHIFT + ⌘ + N` to create a new project. 8 | 9 | 2. Choose __Single View Application__ then click Next. 10 | 11 | 3. Type the __Name__ of your project. 12 | 13 | 4. Type your __Organization Name__. 14 | 15 | 5. Type your __Organization Identifier__. The naming convention for __Organization Identifier__ is reverse domain naming style (e.g. `net.proudcloud.ios.NowShowing`). The platform is included so we can also use this naming convention for Android ports of our apps, in this case `net.proudcloud.android.NowShowing`. 16 | 17 | 6. Choose __Swift__ as the Language 18 | 19 | 7. Choose the __Devices__ to support. Usually, it is just iPhone. Universal is selected when we need to support iPad. 20 | 21 | 2. Set up Build Number auto-updates 22 | 23 | 1. Click on your project workspace. It is the row with the little blue file icon with your project's name, targets, and SDK version. 24 | 25 | 2. Go to __Targets__ -> __Project Name__. 26 | 27 | 3. Then in the __General__ panel, change the default __Version__ of the app to `0.0.1`. 28 | 29 | 4. Then go to __Build Phases__. 30 | 31 | 5. Add a new phase by clicking the `+` on the upper left corner of the panel then click __New Run Script Phase__. 32 | 33 | 6. Collapse the newly added phase and paste the following: 34 | ``` 35 | buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "$INFOPLIST_FILE") 36 | buildNumber=$(($buildNumber + 1)) 37 | /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "$INFOPLIST_FILE" 38 | ``` 39 | 7. Rename this phase to __Auto-update Build Number__ by double-clicking __Run Script__ 40 | 41 | 8. Then drag this new phase above __Copy Bundle Resources__ so that our build number is updated before `Info.plist` is copied to our archive. This ensures that the new archive has the updated build number. 42 | 43 | 44 | 3. Update the project structure 45 | 46 | Make sure you have the following project structure: 47 | ``` 48 | ProjectName 49 | `- API 50 | `- Models 51 | `- Views 52 | `- Controllers 53 | `- Extensions 54 | AppDelegate.swift 55 | Images.xcassets 56 | Main.storyboard 57 | LaunchScreen.xib 58 | Supporting Files 59 | `- Info.plist 60 | `- BridgingHeader.h 61 | ``` 62 | 63 | 64 | 4. Check-in your project to GitHub 65 | 66 | 1. Initialize the project: 67 | ``` 68 | $ git init 69 | ``` 70 | 71 | 2. Commit your changes: 72 | ``` 73 | $ git add --all 74 | ``` 75 | 76 | 3. Set up the remote: 77 | ``` 78 | $ git remote add origin 79 | ``` 80 | 81 | 4. Push your changes 82 | ``` 83 | $ git push -u origin master 84 | ``` 85 | 86 | 87 | ## Setting up CocoaPods 88 | 89 | 1. Go to your project's directory 90 | ``` 91 | $ cd 92 | ``` 93 | 94 | 2. Create a new file named `Gemfile`. 95 | ``` 96 | $ touch Gemfile && vim Gemfile 97 | ``` 98 | 99 | 3. Add the following to your Gemfile: 100 | 101 | ``` 102 | source 'https://rubygems.org' 103 | 104 | gem 'cocoapods' 105 | ``` 106 | 107 | 4. Save and exit by typing `:wq` 108 | 109 | 5. Install CocoaPods by running: 110 | ``` 111 | $ bundle install 112 | ``` 113 | 114 | 6. When Bundler finishes installing CocoaPods, run: 115 | 116 | ``` 117 | $ pod init 118 | ``` 119 | 120 | This will create new file named __Podfile__ in your project directory. You can now add Pods in this file then run `pod install` to install them. 121 | 122 | 123 | ## Versioning 124 | 125 | We'll follow the guidelines below as our versioning system. 126 | 127 | Given we have the `x.y.z` as our version: 128 | 129 | - We increment `z` when we publish bug fixes, and really small updates like changing a text. 130 | - We increment `y` when we publish minor features that don't really affect the usage of the app. 131 | - We increment `x` when we publish really big updates (e.g. major UI overhaul, breaking changes, etc.) 132 | 133 | TLDR; `..` 134 | 135 | Also take note of our __Build Number__. The build number denotes how many times we've built the app by running (`⌘ + R`) or building the app (`⌘ + B`). 136 | 137 | __NOTE:__ In cases where you have conflicts in the build number, always choose the higher build number. 138 | 139 | ## Branching 140 | 141 | *TBA* 142 | 143 | ## Deployment 144 | 145 | Follow the following steps to submit a build to the App Store. 146 | 147 | 1. Make sure __iOS Device__ is selected as your __Destination__. This should be similar to selecting your device to run your app on. 148 | 2. On Xcode's menu bar, Click __Product__ -> __Archive__. When this finishes, Xcode should automatically open the __Organizer__ window. 149 | 3. Click on the latest archive that you created, and click __Validate__. This validates your __*.ipa file__ (iOS application archive) for App Store submission. 150 | - (Optional) Fix errors in your build, if any. 151 | 4. If there are no errors in your build, click __Submit to App Store__ to submit your app. Additional checks will be done to your app and if it passes, your app is now uploaded to the App Store. 152 | 5. Login to __iTunes Connect__ to continue your submission. 153 | 6. Complete the app details, screenshots, and all required information to be able to submit. 154 | 7. Choose a build to submit. 155 | 8. (Optional) You may choose to publish your app manually or automatically, when your app passes the review process or manually publish 156 | 9. Click __Submit for Review__ and pray that your app passes the review process. 157 | 158 | Your app should now say that it's __Waiting for Review__. This usually takes 1 to 2 weeks, and it's up to Apple now whether your app passes or gets rejected. 159 | 160 | 161 | ## Post-Deployment 162 | 163 | After publishing your app, make sure you create a release tag for the new version you published. 164 | 165 | For example, we've just published `v1.2.8` on the App Store 166 | 167 | ``` 168 | $ git tag v1.2.8 169 | ``` 170 | 171 | Then edit this release tag on GitHub and add the changes made in this build. 172 | -------------------------------------------------------------------------------- /practices/testing.md: -------------------------------------------------------------------------------- 1 | # General Philosophy 2 | 3 | - Test the **app**, not the **framework** or **library**. 4 | 5 | - **TDD** is not required, tested code is. 6 | 7 | - Code coverage doesn't mean anything. You can never know all the edge cases. 8 | 9 | - Code should be easy to test. If it's hard to test, change your code. 10 | 11 | - Fast tests are happy tests. 12 | 13 | 14 | # RSpec 15 | 16 | - The `should` syntax is [dead](https://github.com/rspec/rspec-expectations/blob/master/Should.md#why-switch-over-from-should-to-expect). Use the `expect` syntax. This also means no `shoulda`. 17 | 18 | ```ruby 19 | # ✗ Avoid 20 | user.name.should eq "Davy Jones" 21 | 22 | # ✓ OK 23 | expect(user.name).to eq "Davy Jones" 24 | ``` 25 | 26 | - You can run specific examples by providing their line number when you run your tests. 27 | 28 | ``` 29 | > rspec spec/models/user_spec.rb:11 30 | ``` 31 | 32 | - Prefer to run specs with the `--color` or `-c` and the `--format=doc` or `-f d` options. Or store it in an `.rspec` file. 33 | 34 | ``` 35 | # .rspec 36 | --color 37 | --format=doc 38 | ``` 39 | 40 | - Running specs with the `--profile` or `-p` option will display the top ten slowest examples. It also accepts a number argument. Run this in your CI, but don't place it in `.rspec`. 41 | 42 | ``` 43 | # Displays the 5 slowest examples 44 | > rspec spec/models/user_spec.rb -p 5 45 | ``` 46 | 47 | - Add `.rspec-local` to your project's `.gitignore` file. This will allow individual developers to customize their own default rspec parameters. 48 | 49 | ```sh 50 | echo .rspec-local >> .gitignore 51 | ``` 52 | 53 | - Use [shared_examples](https://www.relishapp.com/rspec/rspec-core/docs/example-groups/shared-examples) when possible. 54 | 55 | ## `describe` 56 | 57 | - Consider examples as the project's documentation. 58 | 59 | - Describe your methods properly and accurately. If you change what the code does, do **NOT** forget to update the test's description. 60 | 61 | - Use double quotes for the description string. 62 | 63 | - Your top level `describe` block should indicate the class under test. 64 | 65 | ```ruby 66 | # This is actually a smoke test 67 | describe Venue do 68 | ... 69 | end 70 | ``` 71 | 72 | - No instance varaibles. Use `let` or `let!`. If in doubt, use `let!`. 73 | 74 | - `before`, `around`, `after` and `let` blocks should come right after a `describe` block and before the next `describe` or `context` block. 75 | 76 | - Prefix your methods with `#` if it's an instance method and `.` if it's a class method or model scope. 77 | 78 | ```ruby 79 | describe "#instance_method" 80 | describe ".class_method" 81 | ``` 82 | 83 | ## `context` 84 | 85 | - Use `context` for branching code. Prefer using `with` and `without` or `when`. 86 | 87 | ```ruby 88 | describe "#has_comments?" do 89 | context "in a post with comments" do 90 | let!(:comment) { create :comment, post: post } 91 | it "returns true" do 92 | expect(post.has_comments?).to eq true 93 | end 94 | end 95 | 96 | context "in a post without comments" do 97 | it "returns false" do 98 | expect(post.has_comments?).to eq false 99 | end 100 | end 101 | ``` 102 | 103 | ## `it` 104 | 105 | - Prefer one expectation per `it` block. 106 | 107 | - Be explicit with your descriptions. Say what the code *does*, not what it *should* do. (aka: don't start descriptions with "should") 108 | 109 | ```ruby 110 | # ✓ OK 111 | it "returns true" 112 | it "sends the email" 113 | 114 | # ✗ Avoid 115 | it "should be true" 116 | it "should send the email" 117 | ``` 118 | 119 | - Prefer `eq` over `be` and magic matchers. 120 | 121 | ```ruby 122 | # ✓ OK 123 | expect(user.admin?).to eq true 124 | expect(user.age).to eq 12 125 | 126 | # ✗ Avoid 127 | expect(user).to be_admin 128 | expect(user.age).to be 12 129 | ``` 130 | 131 | - Prefer multiline blocks over one liners. 132 | 133 | - If you must use one liners, use `is_expected`. Again, no `shoulda`. 134 | 135 | 136 | ## `pending` 137 | 138 | - Mark incomplete tests with `pending`. 139 | 140 | ```ruby 141 | it "publishes the event" do 142 | pending "because reasons" 143 | event.publish! 144 | expect(event.published?).to eq true 145 | end 146 | ``` 147 | 148 | - For methods that don't have tests yet (but should), use an `it` with no block. Don't use `pending`. 149 | 150 | ```ruby 151 | # ✗ Avoid 152 | describe "#untested_method" do 153 | pending "because reasons" 154 | end 155 | 156 | # ✓ OK 157 | it "#untested_method" 158 | 159 | # ❤ BETTER 160 | describe "#untested_method" do 161 | it "succeeds with valid data" 162 | it "returns nil when given invalid options" 163 | end 164 | ``` 165 | 166 | ## Metaprogramming Tests 167 | 168 | - Don't. 169 | 170 | # Rails 171 | 172 | - Follow the `rspec-rails` [directory structure](https://relishapp.com/rspec/rspec-rails/docs/directory-structure) and naming conventions. 173 | 174 | - `cucumber` can be cucumbersome. Use RSpec `features` specs with [capybara](https://github.com/jnicklas/capybara) instead. 175 | 176 | - Delegate routing and view specs to `features` specs. 177 | 178 | - Only write controller specs for actions that cannot be covered by `features` specs. Otherwise, write `features` specs. 179 | 180 | - Use [`requests` or `api` specs](https://github.com/rspec/rspec-rails#request-specs) for testing API requests. 181 | 182 | - Do not forget to test helpers and rake tasks. 183 | 184 | - Prefer `spec_helper` over `rails_helper`. Only require `rails_helper` for tests that need Rails to work. 185 | 186 | - Always include the [database_cleaner](https://github.com/DatabaseCleaner/database_cleaner) gem or it's faster cousin, [database_rewinder](https://github.com/amatsuda/database_rewinder). 187 | 188 | - Use [factory_girl_rails](https://github.com/thoughtbot/factory_girl_rails) over fixtures. 189 | 190 | - In your `rails_helper`, always set `config.use_transactional_fixtures` to `false`. This isn't necessary if you're using database_rewinder. 191 | 192 | - External HTTP requests are slow. Always mock them or use gems like [vcr](https://github.com/vcr/vcr) and [WebMock](https://github.com/bblimke/webmock). 193 | 194 | - When mocking/stubbing, never mock/stub the unit you are testing. 195 | 196 | ```ruby 197 | # ✗ Avoid 198 | allow(User).to receive(:count).and_return(2) 199 | expect(User.count).to eq 2 200 | ``` 201 | 202 | 203 | ## Model specs 204 | 205 | - No mocking. Test the actual models. 206 | 207 | - Skip association tests. 208 | 209 | - Test validations. Presence validation specs are optional. 210 | ```ruby 211 | # Validations 212 | expect(valid_project.errors.full_messages).to eq [] 213 | expect(invalid_project.errors.full_messages).to include "Video url is not a valid Youtube/Vimeo url" 214 | ``` 215 | 216 | - Test scopes for both inclusion and exclusion. 217 | ```ruby 218 | # Scopes 219 | expect(Project.published).to include published_project 220 | expect(Project.published).to_not include unpublished_project 221 | ``` 222 | 223 | - Callbacks testing can be done in a couple of ways. 224 | ```ruby 225 | # Assumes an `#ensure_default_role` callback that sets the default role if not provided 226 | 227 | # You can use a proc 228 | user.role = nil 229 | expect { user.save }.to change(user, :role).to("default") 230 | 231 | # or test the effect 232 | user.role = "admin" 233 | user.save 234 | expect(user.reload.role).to eq "admin" 235 | 236 | # or test for the just the call 237 | expect_any_instance_of(User).to receive(:ensure_default_role) 238 | user.save 239 | 240 | # then test the functionality 241 | user.nil 242 | user.send :ensure_default_role 243 | expect(user.role).to eq "default" 244 | ``` 245 | 246 | - Testing `private` methods can be optional, but only if there is a public method spec that covers it. 247 | 248 | 249 | ## View specs 250 | 251 | Don't. Prefer to use this time to write feature specs instead. 252 | 253 | 254 | ## Controller specs 255 | 256 | - See [Features](#feature-specs). 257 | 258 | 259 | ## Lib specs 260 | 261 | - Unless you autoloaded the file you're testing, you will need to `require` it. 262 | 263 | - Do not require `rails_helper` if you can avoid it. Mock what you can. 264 | 265 | 266 | ## Helper specs 267 | 268 | - RSpec provides a `helper` object so you don't have to include the module in a dummy class to test it. 269 | ```ruby 270 | expect(helper.image_url_for user).to eq "http://wat.com/img/fifi" 271 | ``` 272 | 273 | 274 | ## Mailer specs 275 | 276 | - Always mock the models. 277 | 278 | - Do not test `#deliver`. 279 | 280 | - Test for addresses, subject and attachments. 281 | ```ruby 282 | expect(mailer.to).to eq recipient.email 283 | expect(mailer.from).to eq sender.email 284 | expect(mailer.reply_to).to eq sender.reply_to_email 285 | expect(mailer.attachments.size).to eq 1 286 | ``` 287 | 288 | 289 | ## Request specs 290 | 291 | - Request specs are considered as integration tests. Treat them as such. 292 | 293 | - Only use these specs for testing APIs. Use [Features](#feature-specs) for pages. 294 | 295 | - Test the body and status in the same example. 296 | ```ruby 297 | it "returns the correct user" do 298 | get user_path(user) 299 | expect(response.body["id"]).to eq user.id 300 | expect(response.status).to eq 200 301 | end 302 | ``` 303 | 304 | - Use helpers to reduce duplication. For example, assuming you're working on a JSON API, this helper will clean up the parsing logic for you. 305 | ```ruby 306 | # support/api_helpers.rb 307 | module ApiHelpers 308 | def json 309 | JSON.parse(response.body) 310 | end 311 | end 312 | 313 | # rails_helper.rb 314 | config.include ApiHelpers, type: :request 315 | 316 | # usage 317 | expect(json["id"]).to eq user.id 318 | ``` 319 | 320 | 321 | ## Feature Specs 322 | 323 | - Use `feature` and `scenario` blocks. 324 | 325 | ```ruby 326 | feature "User Authentication" do 327 | scenario "with valid credentials" do 328 | ... 329 | end 330 | end 331 | ``` 332 | 333 | - Prefer to test for element visibility instead of testing model effects when possible. 334 | 335 | ```ruby 336 | expect(page).to have_link "Log Out" 337 | 338 | # ✗ Avoid 339 | expect(user.signed_in?).to eq true # This should be in a unit test 340 | ``` 341 | 342 | - Try to be more selective of tests. Using `expect(page).to have_content` will lead to really long error messages. 343 | ```ruby 344 | # ✗ Avoid 345 | expect(page).to have_content "Log Out" 346 | 347 | # ✓ OK 348 | expect(page).to have_selector '#nav', text: /Log Out/ 349 | 350 | # ❤ BETTER, if it works 351 | within '#nav' do 352 | expect(page).to have_content "Log Out" 353 | end 354 | ``` 355 | - Multiple expectations per `scenario` is encouraged. Each scenario takes time to spin up, so using less scenarios means faster tests. 356 | 357 | - Helper methods inside `feature` blocks or within the spec file is allowed. 358 | 359 | - Limit the usage of the `js: true` tag only to blocks that have javascript interaction. 360 | 361 | - Use [konacha](https://github.com/jfirebaugh/konacha) for unit javascript testing. 362 | 363 | - Prefer [poltergeist](https://github.com/teampoltergeist/poltergeist) over the default javascript driver, `selenium`. Avoid [capybara-webkit](https://github.com/thoughtbot/capybara-webkit). 364 | 365 | - There will be cases where you will be needing `selenium` to see what's going on. This snippet provides you with a `selenium: true` tag. 366 | 367 | ```ruby 368 | # rails_helper.rb 369 | Capybara.javascript_driver = :poltergeist 370 | 371 | config.before(:each) do |example| 372 | Capybara.current_driver = :selenium if example.metadata[:selenium] 373 | end 374 | ``` 375 | 376 | - Don't use `sleep` in your specs. If you feel like you really need to, ask first. 377 | 378 | - Use `find_button('Save').trigger('click')` instead of `click_button('Save')` for javascript enabled specs. 379 | 380 | ## Factories 381 | 382 | - Always include the syntax helpers in your tests. This makes `build` and `create` available in your test cases. 383 | 384 | ```ruby 385 | # rails_helper.rb 386 | config.include FactoryGirl::Syntax::Methods 387 | ``` 388 | 389 | - Prefer `build` over `create`, if you can get away with it. This can lead to faster tests. 390 | 391 | - Avoid `build_stubbed`. 392 | 393 | - Never hard-code emails and similar fields that must be unique. Use `sequence`. 394 | 395 | ```ruby 396 | factory :user do 397 | sequence(:email) { |i| "user-#{i}@email.com" } 398 | ... 399 | end 400 | ``` 401 | 402 | - Place reusable sequences in a separate file. 403 | 404 | ```ruby 405 | # spec/factories/factory_sequences.rb 406 | FactoryGirl.define do 407 | sequence(:uid) { |i| SecureRandom.uuid } 408 | sequence(:email) { |i| "user-#{i}@email.com" } 409 | end 410 | 411 | factory :admin do 412 | uid 413 | email 414 | end 415 | 416 | factory :client do 417 | uid 418 | email 419 | end 420 | ``` 421 | 422 | - [Traits](https://github.com/thoughtbot/factory_girl/blob/master/GETTING_STARTED.md#traits) can be used to remove duplication. But use them sparingly. 423 | 424 | - Make sure that factories are always up to date. 425 | 426 | - Always provide the simplest defaults for your factories. Prefer to only add fields that are validated such that records built through the factory will pass validation. Other fields would only serve to make for confusing future tests and make it difficult to test default behavior. 427 | 428 | ```ruby 429 | class Profile < ActiveRecord::Base 430 | validates :name, presence: true 431 | validates :gender, inclusion: %w(male female) 432 | end 433 | 434 | factory :profile do 435 | name "Jack Sparrow" 436 | gender "male" 437 | occupation "Pirate" # <- Don't 438 | bio "Jack is a pirate lord of the seven seas." # <- Don't 439 | end 440 | ``` 441 | 442 | - Test your factories. This will make it easy to spot any factories that may be out of date. 443 | 444 | ```ruby 445 | EXCLUDED = [:factories, :to, :exclude, :if, :any] 446 | 447 | FactoryGirl.factories.map(&:name).each do |factory_name| 448 | next if EXCLUDED.include?(factory_name) 449 | 450 | it "the #{factory_name} factory is valid" do 451 | expect(build factory_name).to be_valid 452 | end 453 | end 454 | ``` 455 | --------------------------------------------------------------------------------