Ruby On Rails Notes For Professionals
Ruby On Rails Notes For Professionals
Ruby On Rails Notes For Professionals
Ruby on Rails
Notes for Professionals
®
Rails
Notes for Professionals
200+ pages
of professional hints and tricks
Disclaimer
GoalKicker.com This is an unocial free book created for educational purposes and is
not aliated with ocial Ruby® on Rails group(s) or company(s).
Free Programming Books All trademarks and registered trademarks are
the property of their respective owners
Contents
About ................................................................................................................................................................................... 1
Chapter 1: Getting started with Ruby on Rails .............................................................................................. 2
Section 1.1: Creating a Ruby on Rails Application ...................................................................................................... 2
Section 1.2: Create a new Rails app with your choice of database and including the RSpec Testing Tool
.................................................................................................................................................................................. 3
Section 1.3: Generating A Controller ............................................................................................................................ 4
Section 1.4: Installing Rails ............................................................................................................................................ 5
Section 1.5: Create a new Rails app with a non-standard database adapter ........................................................ 7
Section 1.6: Creating Rails APIs in JSON ...................................................................................................................... 7
Section 1.7: Generate a Resource with Scaolds ....................................................................................................... 8
Chapter 2: Routing ....................................................................................................................................................... 9
Section 2.1: Resource Routing (Basic) ......................................................................................................................... 9
Section 2.2: Constraints .............................................................................................................................................. 10
Section 2.3: Scoping routes ........................................................................................................................................ 12
Section 2.4: Concerns .................................................................................................................................................. 14
Section 2.5: Root route ............................................................................................................................................... 15
Section 2.6: Split routes into multiple files ................................................................................................................ 15
Section 2.7: Additional RESTful actions ..................................................................................................................... 16
Section 2.8: Member and Collection Routes ............................................................................................................. 16
Section 2.9: Mount another application .................................................................................................................... 17
Section 2.10: Nested Routes ....................................................................................................................................... 17
Section 2.11: Redirection .............................................................................................................................................. 17
Section 2.12: Redirects and Wildcard Routes ........................................................................................................... 18
Section 2.13: Scope available locales ........................................................................................................................ 18
Section 2.14: URL params with a period ................................................................................................................... 18
Chapter 3: ActiveRecord ......................................................................................................................................... 19
Section 3.1: Creating a Model via generator ............................................................................................................. 19
Section 3.2: Introduction to Callbacks ....................................................................................................................... 19
Section 3.3: Creating a Model manually ................................................................................................................... 20
Section 3.4: Manually Testing Your Models .............................................................................................................. 21
Section 3.5: Creating A Migration .............................................................................................................................. 21
Section 3.6: Create a Join Table using Migrations ................................................................................................... 22
Section 3.7: Using a model instance to update a row ............................................................................................. 23
Chapter 4: Views ......................................................................................................................................................... 24
Section 4.1: Structure ................................................................................................................................................... 24
Section 4.2: Partials ..................................................................................................................................................... 24
Section 4.3: AssetTagHelper ...................................................................................................................................... 25
Section 4.4: Replace HTML code in Views ................................................................................................................ 26
Section 4.5: HAML - an alternative way to use in your views ................................................................................. 27
Chapter 5: ActiveRecord Migrations ................................................................................................................. 29
Section 5.1: Adding multiple columns to a table ....................................................................................................... 29
Section 5.2: Add a reference column to a table ...................................................................................................... 29
Section 5.3: Rollback migrations ................................................................................................................................ 30
Section 5.4: Add a new column with an index .......................................................................................................... 30
Section 5.5: Run specific migration ........................................................................................................................... 31
Section 5.6: Redo migrations ..................................................................................................................................... 31
Section 5.7: Add a new column to a table ................................................................................................................ 31
Section 5.8: Remove an existing column from a table ............................................................................................ 32
Section 5.9: Add column with default value ............................................................................................................. 32
Section 5.10: Running migrations in dierent environments .................................................................................. 32
Section 5.11: Create a new table ................................................................................................................................. 33
Section 5.12: Running migrations ............................................................................................................................... 33
Section 5.13: Change an existing column’s type ....................................................................................................... 33
Section 5.14: Create a hstore column ........................................................................................................................ 34
Section 5.15: Create a join table ................................................................................................................................. 34
Section 5.16: Add a self reference .............................................................................................................................. 34
Section 5.17: Create an array column ....................................................................................................................... 35
Section 5.18: Add an unique column to a table ........................................................................................................ 35
Section 5.19: Checking migration status ................................................................................................................... 35
Section 5.20: Changing Tables .................................................................................................................................. 36
Section 5.21: Adding a NOT NULL constraint to existing data ................................................................................ 36
Section 5.22: Forbid null values ................................................................................................................................. 37
Chapter 6: Rails Best Practices ............................................................................................................................ 38
Section 6.1: Fat Model, Skinny Controller .................................................................................................................. 38
Section 6.2: Domain Objects (No More Fat Models) ............................................................................................... 38
Section 6.3: Beware of default_scope ...................................................................................................................... 40
Section 6.4: Convention Over Configuration ............................................................................................................ 42
Section 6.5: Don't Repeat Yourself (DRY) ................................................................................................................. 43
Section 6.6: You Ain’t Gonna Need it (YAGNI) ........................................................................................................... 43
Chapter 7: Naming Conventions ......................................................................................................................... 45
Section 7.1: Controllers ................................................................................................................................................ 45
Section 7.2: Models ...................................................................................................................................................... 45
Section 7.3: Filenames and autoloading ................................................................................................................... 45
Section 7.4: Views and Layouts ................................................................................................................................. 46
Section 7.5: Models class from Controller name ...................................................................................................... 46
Chapter 8: ActionCable ............................................................................................................................................ 47
Section 8.1: User Authentication ................................................................................................................................. 47
Section 8.2: [Basic] Server Side ................................................................................................................................. 47
Section 8.3: [Basic] Client Side (Coeescript) .......................................................................................................... 47
Chapter 9: ActiveModel ............................................................................................................................................ 49
Section 9.1: Using ActiveModel::Validations .............................................................................................................. 49
Chapter 10: User Authentication in Rails ........................................................................................................ 50
Section 10.1: Authentication using Devise .................................................................................................................. 50
Section 10.2: Devise Controller Filters & Helpers ...................................................................................................... 50
Section 10.3: Omniauth ................................................................................................................................................ 51
Section 10.4: has_secure_password ......................................................................................................................... 51
Section 10.5: has_secure_token ................................................................................................................................ 51
Chapter 11: ActiveRecord Associations ............................................................................................................ 53
Section 11.1: Polymorphic association ........................................................................................................................ 53
Section 11.2: Self-Referential Association .................................................................................................................. 53
Section 11.3: belongs_to .............................................................................................................................................. 54
Section 11.4: has_one .................................................................................................................................................. 54
Section 11.5: has_many ............................................................................................................................................... 54
Section 11.6: The has_many :through association ................................................................................................... 55
Section 11.7: The has_one :through association ....................................................................................................... 55
Section 11.8: The has_and_belongs_to_many association ................................................................................... 56
Chapter 12: ActiveRecord Validations .............................................................................................................. 57
Section 12.1: Validating length of an attribute .......................................................................................................... 57
Section 12.2: Validates format of an attribute .......................................................................................................... 57
Section 12.3: Validating presence of an attribute .................................................................................................... 57
Section 12.4: Custom validations ................................................................................................................................ 58
Section 12.5: Validates inclusion of an attribute ....................................................................................................... 58
Section 12.6: Grouping validation ............................................................................................................................... 59
Section 12.7: Validating numericality of an attribute ............................................................................................... 59
Section 12.8: Validate uniqueness of an attribute .................................................................................................... 60
Section 12.9: Skipping Validations .............................................................................................................................. 60
Section 12.10: Confirmation of attribute .................................................................................................................... 60
Section 12.11: Using :on option .................................................................................................................................... 61
Section 12.12: Conditional validation .......................................................................................................................... 61
Chapter 13: ActiveRecord Query Interface .................................................................................................... 62
Section 13.1: .where ...................................................................................................................................................... 62
Section 13.2: .where with an array ............................................................................................................................. 62
Section 13.3: Scopes .................................................................................................................................................... 63
Section 13.4: Get first and last record ........................................................................................................................ 64
Section 13.5: Ordering ................................................................................................................................................. 65
Section 13.6: where.not ................................................................................................................................................ 65
Section 13.7: Includes ................................................................................................................................................... 66
Section 13.8: Joins ........................................................................................................................................................ 66
Section 13.9: Limit and Oset ..................................................................................................................................... 67
Section 13.10: .find_by ................................................................................................................................................. 67
Section 13.11: .delete_all .............................................................................................................................................. 67
Section 13.12: ActiveRecord case insensitive search ................................................................................................ 67
Section 13.13: .group and .count ................................................................................................................................. 68
Section 13.14: .distinct (or .uniq) .................................................................................................................................. 68
Chapter 14: ActionMailer ......................................................................................................................................... 69
Section 14.1: Basic Mailer ............................................................................................................................................. 69
Section 14.2: Generating a new mailer ...................................................................................................................... 70
Section 14.3: ActionMailer Interceptor ....................................................................................................................... 70
Section 14.4: Adding Attachments ............................................................................................................................. 70
Section 14.5: ActionMailer Callbacks .......................................................................................................................... 71
Section 14.6: Generate a Scheduled Newsletter ....................................................................................................... 71
Chapter 15: Rails generate commands ........................................................................................................... 77
Section 15.1: Rails Generate Controller ...................................................................................................................... 77
Section 15.2: Rails Generate Migration ...................................................................................................................... 78
Section 15.3: Rails Generate Scaold ........................................................................................................................ 78
Section 15.4: Rails Generate Model ............................................................................................................................ 79
Chapter 16: Configuration ...................................................................................................................................... 80
Section 16.1: Custom configuration ............................................................................................................................ 80
Chapter 17: I18n - Internationalization ............................................................................................................. 82
Section 17.1: I18n with arguments ............................................................................................................................... 82
Section 17.2: Translating ActiveRecord model attributes ........................................................................................ 82
Section 17.3: Get locale from HTTP request .............................................................................................................. 84
Section 17.4: Pluralization ............................................................................................................................................ 85
Section 17.5: Set locale through requests ................................................................................................................. 85
Section 17.6: Use I18n with HTML Tags and Symbols .............................................................................................. 87
Section 17.7: Use I18n in views .................................................................................................................................... 87
Chapter 18: Using GoogleMaps with Rails ...................................................................................................... 89
Section 18.1: Add the google maps javascript tag to the layout header ............................................................... 89
Section 18.2: Geocode the model ............................................................................................................................... 89
Section 18.3: Show addresses on a google map in the profile view ....................................................................... 90
Section 18.4: Set the markers on the map with javascript ...................................................................................... 91
Section 18.5: Initialize the map using a coee script class ...................................................................................... 92
Section 18.6: Initialize the map markers using a coee script class ...................................................................... 92
Section 18.7: Auto-zoom a map using a coee script class .................................................................................... 93
Section 18.8: Exposing the model properties as json ............................................................................................... 94
Chapter 19: File Uploads .......................................................................................................................................... 96
Section 19.1: Single file upload using Carrierwave .................................................................................................... 96
Section 19.2: Nested model - multiple uploads ........................................................................................................ 96
Chapter 20: Caching .................................................................................................................................................. 98
Section 20.1: Russian Doll Caching ............................................................................................................................ 98
Section 20.2: SQL Caching ......................................................................................................................................... 98
Section 20.3: Action caching ...................................................................................................................................... 99
Section 20.4: Fragment caching ................................................................................................................................ 99
Section 20.5: Page caching ...................................................................................................................................... 100
Section 20.6: HTTP caching ..................................................................................................................................... 100
Chapter 21: ActionController ............................................................................................................................... 101
Section 21.1: Basic REST Controller .......................................................................................................................... 101
Section 21.2: Filters .................................................................................................................................................... 102
Section 21.3: Generating a controller ...................................................................................................................... 104
Section 21.4: Rescuing ActiveRecord::RecordNotFound with redirect_to ........................................................... 105
Section 21.5: Display error pages for exceptions ................................................................................................... 105
Section 21.6: Output JSON instead of HTML .......................................................................................................... 106
Section 21.7: Controllers (Basic) ............................................................................................................................... 106
Section 21.8: Parameters .......................................................................................................................................... 106
Section 21.9: Filtering parameters (Basic) .............................................................................................................. 107
Section 21.10: Redirecting ......................................................................................................................................... 107
Section 21.11: Using Views ......................................................................................................................................... 107
Chapter 22: Configuration .................................................................................................................................... 109
Section 22.1: Rails General Configuration ............................................................................................................... 109
Section 22.2: Configuring assets ............................................................................................................................. 109
Section 22.3: Configuring generators ..................................................................................................................... 109
Section 22.4: Environments in Rails ......................................................................................................................... 110
Section 22.5: Database Configuration .................................................................................................................... 110
Chapter 23: Safe Constantize ............................................................................................................................. 112
Section 23.1: Successful safe_constantize .............................................................................................................. 112
Section 23.2: Unsuccessful safe_constantize ........................................................................................................ 112
Chapter 24: Rails 5 .................................................................................................................................................. 113
Section 24.1: How to install Ruby on Rails 5 on RVM ............................................................................................. 113
Section 24.2: Creating a Ruby on Rails 5 API ......................................................................................................... 113
Chapter 25: Authorization with CanCan ........................................................................................................ 116
Section 25.1: Getting started with CanCan .............................................................................................................. 116
Section 25.2: Handling large number of abilities ................................................................................................... 116
Section 25.3: Defining abilities ................................................................................................................................. 118
Section 25.4: Quickly test an ability ........................................................................................................................ 118
Chapter 26: Mongoid ............................................................................................................................................... 120
Section 26.1: Fields ..................................................................................................................................................... 120
Section 26.2: Installation ........................................................................................................................................... 120
Section 26.3: Creating a Model ................................................................................................................................ 120
Section 26.4: Classic Associations ........................................................................................................................... 121
Section 26.5: Embedded Associations .................................................................................................................... 121
Section 26.6: Database Calls .................................................................................................................................... 122
Chapter 27: Gems ..................................................................................................................................................... 123
Section 27.1: Gemfiles ................................................................................................................................................ 123
Section 27.2: What is a gem? ................................................................................................................................... 123
Section 27.3: Bundler ................................................................................................................................................ 124
Section 27.4: Gemsets ............................................................................................................................................... 124
Chapter 28: Change default timezone .......................................................................................................... 127
Section 28.1: Change Rails timezone AND have Active Record store times in this timezone ........................... 127
Section 28.2: Change Rails timezone, but continue to have Active Record save in the database in UTC
............................................................................................................................................................................. 127
Chapter 29: Asset Pipeline .................................................................................................................................... 128
Section 29.1: Manifest Files and Directives ............................................................................................................. 128
Section 29.2: Rake tasks ........................................................................................................................................... 129
Section 29.3: Basic Usage ........................................................................................................................................ 129
Chapter 30: Upgrading Rails .............................................................................................................................. 130
Section 30.1: Upgrading from Rails 4.2 to Rails 5.0 ............................................................................................... 130
Chapter 31: ActiveRecord Locking ................................................................................................................... 132
Section 31.1: Optimistic Locking ................................................................................................................................ 132
Section 31.2: Pessimistic Locking ............................................................................................................................. 132
Chapter 32: Debugging .......................................................................................................................................... 133
Section 32.1: Debugging Rails Application .............................................................................................................. 133
Section 32.2: Debugging Ruby on Rails Quickly + Beginner advice .................................................................... 133
Section 32.3: Debugging ruby-on-rails application with pry ................................................................................ 135
Section 32.4: Debugging in your IDE ....................................................................................................................... 136
Chapter 33: Configure Angular with Rails .................................................................................................... 138
Section 33.1: Angular with Rails 101 .......................................................................................................................... 138
Chapter 34: Rails logger ....................................................................................................................................... 141
Section 34.1: Rails.logger .......................................................................................................................................... 141
Chapter 35: Prawn PDF .......................................................................................................................................... 142
Section 35.1: Advanced Example ............................................................................................................................. 142
Section 35.2: Basic Example ..................................................................................................................................... 143
Chapter 36: Rails API ............................................................................................................................................... 144
Section 36.1: Creating an API-only application ....................................................................................................... 144
Chapter 37: Deploying a Rails app on Heroku .......................................................................................... 145
Section 37.1: Deploying your application ................................................................................................................ 145
Section 37.2: Managing Production and staging environments for a Heroku ................................................... 147
Chapter 38: ActiveSupport .................................................................................................................................. 149
Section 38.1: Core Extensions: String Access .......................................................................................................... 149
Section 38.2: Core Extensions: String to Date/Time Conversion ......................................................................... 149
Section 38.3: Core Extensions: String Exclusion ...................................................................................................... 150
Section 38.4: Core Extensions: String Filters ........................................................................................................... 150
Section 38.5: Core Extensions: String Inflection ...................................................................................................... 151
Chapter 39: Form Helpers .................................................................................................................................... 154
Section 39.1: Creating a search form ...................................................................................................................... 154
Section 39.2: Dropdown ............................................................................................................................................ 154
Section 39.3: Helpers for form elements ................................................................................................................ 154
Chapter 40: ActiveRecord Transactions ...................................................................................................... 157
Section 40.1: Basic example ..................................................................................................................................... 157
Section 40.2: Dierent ActiveRecord classes in a single transaction .................................................................. 157
Section 40.3: Multiple database connections ......................................................................................................... 157
Section 40.4: save and destroy are automatically wrapped in a transaction ................................................... 157
Section 40.5: Callbacks ............................................................................................................................................. 158
Section 40.6: Rolling back a transaction ................................................................................................................ 158
Chapter 41: RSpec and Ruby on Rails ........................................................................................................... 159
Section 41.1: Installing RSpec .................................................................................................................................... 159
Chapter 42: Decorator pattern ........................................................................................................................ 160
Section 42.1: Decorating a Model using Draper ..................................................................................................... 160
Section 42.2: Decorating a Model using SimpleDelegator ................................................................................... 160
Chapter 43: Elasticsearch .................................................................................................................................... 162
Section 43.1: Searchkick ............................................................................................................................................ 162
Section 43.2: Installation and testing ...................................................................................................................... 162
Section 43.3: Setting up tools for development ..................................................................................................... 163
Section 43.4: Introduction ......................................................................................................................................... 163
Chapter 44: React with Rails using react-rails gem .............................................................................. 164
Section 44.1: React installation for Rails using rails_react gem ........................................................................... 164
Section 44.2: Using react_rails within your application ........................................................................................ 164
Section 44.3: Rendering & mounting ....................................................................................................................... 165
Chapter 45: Rails Cookbook - Advanced rails recipes/learnings and coding techniques
............................................................................................................................................................................................ 166
Section 45.1: Playing with Tables using rails console ............................................................................................ 166
Section 45.2: Rails methods - returning boolean values ....................................................................................... 166
Section 45.3: Handling the error - undefined method `where' for #<Array:0x000000071923f8> ..................... 167
Chapter 46: Multipurpose ActiveRecord columns ................................................................................... 168
Section 46.1: Saving an object .................................................................................................................................. 168
Section 46.2: How To ................................................................................................................................................ 168
Chapter 47: Class Organization ........................................................................................................................ 169
Section 47.1: Service Class ........................................................................................................................................ 169
Section 47.2: Model Class ......................................................................................................................................... 171
Chapter 48: Shallow Routing ............................................................................................................................. 172
Section 48.1: Use of shallow ..................................................................................................................................... 172
Chapter 49: Model states: AASM ...................................................................................................................... 173
Section 49.1: Basic state with AASM ........................................................................................................................ 173
Chapter 50: Rails 5 API Authetication ............................................................................................................ 175
Section 50.1: Authentication with Rails authenticate_with_http_token .............................................................. 175
Chapter 51: Testing Rails Applications ........................................................................................................... 176
Section 51.1: Unit Test ................................................................................................................................................ 176
Section 51.2: Request Test ........................................................................................................................................ 176
Chapter 52: Active Jobs ........................................................................................................................................ 177
Section 52.1: Introduction .......................................................................................................................................... 177
Section 52.2: Sample Job ......................................................................................................................................... 177
Section 52.3: Creating an Active Job via the generator ....................................................................................... 177
Chapter 53: Rails frameworks over the years .......................................................................................... 178
Section 53.1: How to find what frameworks are available in the current version of Rails? ............................... 178
Section 53.2: Rails versions in Rails 1.x .................................................................................................................... 178
Section 53.3: Rails frameworks in Rails 2.x ............................................................................................................. 178
Section 53.4: Rails frameworks in Rails 3.x ............................................................................................................. 178
Chapter 54: Nested form in Ruby on Rails ................................................................................................. 179
Section 54.1: How to setup a nested form in Ruby on Rails ................................................................................. 179
Chapter 55: Factory Girl ....................................................................................................................................... 180
Section 55.1: Defining Factories ............................................................................................................................... 180
Chapter 56: Import whole CSV files from specific folder .................................................................... 181
Section 56.1: Uploads CSV from console command .............................................................................................. 181
Chapter 57: Tools for Ruby on Rails code optimization and cleanup ........................................... 182
Section 57.1: If you want to keep your code maintainable, secure and optimized, look at some gems for
code optimization and cleanup : ..................................................................................................................... 182
Chapter 58: ActiveJob ............................................................................................................................................ 183
Section 58.1: Create the Job ..................................................................................................................................... 183
Section 58.2: Enqueue the Job ................................................................................................................................ 183
Chapter 59: Active Model Serializers .............................................................................................................. 184
Section 59.1: Using a serializer ................................................................................................................................. 184
Chapter 60: Rails Engine - Modular Rails ..................................................................................................... 185
Section 60.1: Create a modular app ........................................................................................................................ 185
Chapter 61: Single Table Inheritance .............................................................................................................. 188
Section 61.1: Basic example ...................................................................................................................................... 188
Section 61.2: Custom inheritance column ............................................................................................................... 188
Section 61.3: Rails model with type column and without STI ................................................................................ 189
Chapter 62: ActiveRecord Transactions ....................................................................................................... 190
Section 62.1: Getting Started with Active Record Transactions ............................................................................ 190
Chapter 63: Turbolinks ........................................................................................................................................... 191
Section 63.1: Binding to turbolink's concept of a page load ................................................................................. 191
Section 63.2: Disable turbolinks on specific links ................................................................................................... 191
Section 63.3: Understanding Application Visits ...................................................................................................... 192
Section 63.4: Cancelling visits before they begin ................................................................................................... 192
Section 63.5: Persisting elements across page loads ............................................................................................ 193
Chapter 64: Friendly ID ......................................................................................................................................... 194
Section 64.1: Rails Quickstart ................................................................................................................................... 194
Chapter 65: Securely storing authentication keys .................................................................................. 196
Section 65.1: Storing authentication keys with Figaro ........................................................................................... 196
Chapter 66: Authenticate Api using Devise ................................................................................................. 197
Section 66.1: Getting Started .................................................................................................................................... 197
Chapter 67: Integrating React.js with Rails Using Hyperloop ........................................................... 199
Section 67.1: Adding a simple react component (written in ruby) to your Rails app ......................................... 199
Section 67.2: Callbacks ............................................................................................................................................. 199
Section 67.3: Declaring component parameters (props) ..................................................................................... 199
Section 67.4: HTML Tags .......................................................................................................................................... 199
Section 67.5: Event Handlers .................................................................................................................................... 200
Section 67.6: States ................................................................................................................................................... 200
Chapter 68: Change a default Rails application enviornment ......................................................... 201
Section 68.1: Running on a local machine .............................................................................................................. 201
Section 68.2: Running on a server ........................................................................................................................... 201
Chapter 69: Rails -Engines ................................................................................................................................... 202
Section 69.1: Famous examples are ........................................................................................................................ 202
Chapter 70: Adding an Amazon RDS to your rails application ......................................................... 203
Section 70.1: Consider we are connecting MYSQL RDS with your rails application ........................................... 203
Chapter 71: Payment feature in rails ............................................................................................................. 204
Section 71.1: How to integrate with Stripe ............................................................................................................... 204
Chapter 72: Rails on docker ................................................................................................................................ 206
Section 72.1: Docker and docker-compose ............................................................................................................ 206
Appendix A: Reserved Words ............................................................................................................................. 208
Section A.1: Reserved Word List .............................................................................................................................. 208
Credits ............................................................................................................................................................................ 214
You may also like ...................................................................................................................................................... 218
About
Please feel free to share this PDF with anyone for free,
latest version of this book can be downloaded from:
http://GoalKicker.com/RubyOnRailsBook
This Ruby® on Rails Notes for Professionals book is compiled from Stack Overflow
Documentation, the content is written by the beautiful people at Stack Overflow.
Text content is released under Creative Commons BY-SA, see credits at the end
of this book whom contributed to the various chapters. Images may be copyright
of their respective owners unless otherwise specified
This is an unofficial free book created for educational purposes and is not
affiliated with official Ruby® on Rails group(s) or company(s) nor Stack Overflow.
All trademarks and registered trademarks are the property of their respective
company owners
Open up a command line or terminal. To generate a new rails application, use rails new command followed by the
name of your application:
If you want to create your Rails application with a specific Rails version then you can specify it at the time of
generating the application. To do that, use rails _version_ new followed by the application name:
This will create a Rails application called MyApp in a my_app directory and install the gem dependencies that are
already mentioned in Gemfile using bundle install.
To switch to your newly created app's directory, use the cd command, which stands for change directory.
$ cd my_app
The my_app directory has a number of auto-generated files and folders that make up the structure of a Rails
application. Following is a list of files and folders that are created by default:
File/Folder Purpose
app/ Contains the controllers, models, views, helpers, mailers and assets for your application.
Contains the rails script that starts your app and can contain other scripts you use to setup,
bin/
update, deploy or run your application.
config/ Configure your application's routes, database, and more.
config.ru Rack configuration for Rack based servers used to start the application.
db/ Contains your current database schema, as well as the database migrations.
Gemfile These files allow you to specify what gem dependencies are needed for your Rails application.
Gemfile.lock These files are used by the Bundler gem.
lib/ Extended modules for your application.
Version ≥ 5.0
rake db:create
# OR
rails db:create
Version < 5.0
rake db:create
Now that we've created the database, we need to run migrations to set up the tables:
Version ≥ 5.0
rake db:migrate
# OR
rails db:migrate
Version < 5.0
rake db:migrate
$ rails server
# OR
$ rails s
By default, rails will start the application at port 3000. To start the application with different port number, we need
to fire up the server like,
$ rails s -p 3010
If you navigate to http://localhost:3000 in your browser, you will see a Rails welcome page, showing that your
application is now running.
If that still throws an error, then you should check your config/database.yml
mysql
oracle
postgresql
sqlite3
frontbase
ibm_db
sqlserver
jdbcmysql
jdbcsqlite3
jdbcpostgresql
jdbc
The -T command indicate to skip the installation of minitest. To install an alternative test suite like RSpec, edit the
Gemfile and add
You can shorten this code by replacing generate with g, for example:
If you open up the newly generated app/controllers/posts_controller.rb you'll see a controller with no actions:
It's possible to create default methods for the controller by passing in controller name arguments.
To create a controller within a module, specify the controller name as a path like parent_module/controller_name.
For example:
Controller: app/controllers/credit_cards_controller.rb
Test: test/controllers/credit_cards_controller_test.rb
Views: app/views/credit_cards/debit.html.erb [...etc]
Helper: app/helpers/credit_cards_helper.rb
It's inside this class that you'll define methods that will become the actions for this controller.
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
Installing ruby version manager. In this case the easy one is using rbenv
Restart Shell
exec $SHELL
Install ruby
Installing rails
We need Ruby programming language installed. We can use a precompiled version of Ruby called RubyInstaller.
After installing Ruby, we can try to install Rails. But some of the libraries Rails depends on need some build tools in
order to be compiled, and Windows lacks those tools by default. You can identify this if you see an error while
attempting to install Rails Gem::InstallError: The ‘[gem name]’ native gem requires installed build
tools. To fix this, we need to install the Ruby Development Kit.
In your command prompt, change to the DevKit directory. cd C:\RubyDevKit or whatever directory you
installed it in.
We need to run a Ruby script to initialize the DevKit setup. Type ruby dk.rb init. Now we’ll tell that same
script to add the DevKit to our Ruby installation. Type ruby dk.rb install.
The DevKit should now be available for your Ruby tools to use when installing new libraries.
Step 3: Rails
Now we can install Rails. Rails comes as a Ruby gem. In your command prompt, type:
Once you press Enter, the gem program will download and install that version of the Rails gem, along with all the
other gems Rails depends on.
Step 4: Node.js
Some libraries that Rails depends on require a JavaScript runtime to be installed. Let’s install Node.js so that those
libraries work properly.
As an ORM, it is built to handle relational-mapping, and more precisely by handling SQL requests for you, hence the
limitation to SQL databases only.
However, you can still create a Rails app with another database management system:
3. bundle install and follow the installation steps from the desired database.
In this example, mongoid is an object mapping for MongoDB and - as many other database gems built for rails - it also
inherits from ActiveModel the same way as ActiveRecord, which provides a common interface for many features
such as validations, callbacks, translations, etc.
datamapper
sequel-rails
gem 'active_model_serializers'
bundle install
# config/initializers/active_model_serializer.rb
ActiveModelSerializers.config.adapter = :json_api
Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest
Controller: app/controllers/tasks_controller.rb
Test: test/models/task_test.rb
test/controllers/tasks_controller_test.rb
Routes: resources :tasks added in routes.rb
Migration: db/migrate/_create_tasks.rb
Model: app/models/task.rb
Serializer: app/serializers/task_serializer.rb
Controller: app/controllers/tasks_controller.rb
Instead of generating a model directly . . . let's set up a scaffold. A scaffold in Rails is a full set of model,
database migration for that model, controller to manipulate it, views to view and manipulate the data,
and a test suite for each of the above.
Here's an example of scaffolding a resource called Task with a string name and a text description:
Controller: app/controllers/tasks_controller.rb
Test: test/models/task_test.rb
test/controllers/tasks_controller_test.rb
Routes: resources :tasks added in routes.rb
Views: app/views/tasks
app/views/tasks/index.html.erb
app/views/tasks/edit.html.erb
app/views/tasks/show.html.erb
app/views/tasks/new.html.erb
app/views/tasks/_form.html.erb
Helper: app/helpers/tasks_helper.rb
JS: app/assets/javascripts/tasks.coffee
CSS: app/assets/stylesheets/tasks.scss
app/assets/stylesheets/scaffolds.scss
example to delete files generated by scaffold for the resource called Task
resources :users creates the following seven routes, all mapping to actions of UsersController:
Action names are shown after the # in the to parameter above. Methods with those same names must be defined
in app/controllers/users_controller.rb as follows:
def create
end
You can limit the actions that gets generated with only or except:
You can view all the routes of your application at any given time by running:
# OR
You can search through routes using the -g option. This shows any route that partially matches the helper method
name, the URL path or the HTTP verb:
Additionally, when running rails server in development mode, you can access a web page that shows all your
routes with a search filter, matched in priority from top to bottom, at <hostname>/rails/info/routes. It will look
like this:
Routes can be declared available for only members (not collections) using the method resource instead of
resources in routes.rb. With resource, an index route is not created by default, but only when explicitly asking for
one like this:
segment constraints,
For example, a requested based constraint to only allow a specific IP address to access a route:
constraints(ip: /127\.0\.0\.1$/) do
get 'route', to: "controller#action"
end
If you want to do something more complex you can use more advanced constraints and create a class to wrap the
logic:
# lib/api_version_constraint.rb
class ApiVersionConstraint
def initialize(version:, default:)
@version = version
@default = default
end
def version_header
"application/vnd.my-app.v#{@version}"
end
def matches?(request)
@default || request.headers["Accept"].include?(version_header)
end
end
# config/routes.rb
require "api_version_constraint"
Rails.application.routes.draw do
namespace :v1, constraints: ApiVersionConstraint.new(version: 1, default: true) do
resources :users # Will route to app/controllers/v1/users_controller.rb
end
You can also use the value of the submit tags of a form as a constraint to route to a different action. If you have a
form with multiple submit buttons (eg "preview" and "submit"), you could capture this constraint directly in your
routes.rb, instead of writing javascript to change the form destination URL. For example with the
commit_param_routing gem you can take advantage of rails submit_tag
Rails submit_tag first parameter lets you change the value of your form commit parameter
# app/views/orders/mass_order.html.erb
<%= form_for(@orders, url: mass_create_order_path do |f| %>
<!-- Big form here -->
<%= submit_tag "Preview" %>
<%= submit_tag "Submit" %>
# => <input name="commit" type="submit" value="Preview" />
# => <input name="commit" type="submit" value="Submit" />
# config/routes.rb
resources :orders do
# Both routes below describe the same POST URL, but route to different actions
post 'mass_order', on: :collection, as: 'mass_order',
constraints: CommitParamRouting.new('Submit'), action: 'mass_create' # when the user presses
"submit"
post 'mass_order', on: :collection,
constraints: CommitParamRouting.new('Preview'), action: 'mass_create_preview' # when the user
presses "preview"
# Note the `as:` is defined only once, since the path helper is mass_create_order_path for the form
url
# CommitParamRouting is just a class like ApiVersionContraint
end
Scope by URL:
scope 'admin' do
get 'dashboard', to: 'administration#dashboard'
resources 'employees'
end
It may make more sense, on the server side, to keep some views in a different subfolder, to separate admin views
from user views.
Scope by module
module looks for the controller files under the subfolder of the given name
Rails provides a convenient way to do all the above, using the namespace method. The following declarations are
equivalent
namespace :admin do
end
Scope by controller
Shallow Nesting
Resource routes accept a :shallow option that helps to shorten URLs where possible. Resources shouldn't be
nested more than one level deep. One way to avoid this is by creating shallow routes. The goal is to leave off parent
collection URL segments where they are not needed. The end result is that the only nested routes generated are for
the :index , :create , and :new actions. The rest are kept in their own shallow URL context. There are two options
for scope to custom shallow routes:
If you analyze the routes generated carefully, you’ll notice that the nested parts of the URL are only included when
they are needed to determine what data to display.
concern :commentable do
resources :comments
end
While not creating any routes itself, this code allows using the :concerns attribute on a resource. The simplest
example would be:
/pages/#{page_id}/comments
/pages/#{page_id}/comments/#{comment_id}
For concerns to be meaningful, there must be multiple resources that utilize the concern. Additional resources
could use any of the following syntax to call the concern:
# config/routes.rb
Rails.application.routes.draw do
root "application#index"
# equivalent to:
# get "/", "application#index"
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
def index
render "homepage"
end
end
Because the homepage is usually the most important route, and routes are prioritized in the order they appear, the
root route should usually be the first in your routes file.
config/routes.rb:
YourAppName::Application.routes.draw do
require_relative 'routes/admin_routes'
require_relative 'routes/sidekiq_routes'
require_relative 'routes/api_routes'
require_relative 'routes/your_app_routes'
end
config/routes/api_routes.rb:
YourAppName::Application.routes.draw do
resources :photos do get 'preview', on: :member get 'dashboard', on: :collection end
Be mindful when adding actions to your RESTful routes, probably you are missing another resource!
resources :posts do
member do
get 'preview'
end
end
Collection routes allow for creating routes that can act on a collection of resource objects:
resources :posts do
collection do
get 'search'
end
end
An alternate syntax:
resources :posts do
get 'preview', on: :member
get 'search', on: :collection
end
syntax:
Now you can access above mounted application using route helper some_rack_app_path or some_rack_app_url.
But if you want to rename this helper name you can do it as:
This will generate the myapp_path and myapp_url helpers which can be used to navigate to this mounted app.
resources :admins do
resources :employees
end
Version ≥ 4.0
match '*path' => redirect('/'), via: :get
# or
get '*path' => redirect('/')
Version < 4.0
match '*path' => redirect('/')
# config/routes.rb
TestApp::Application.routes.draw do
get 'courses/:course_name' => redirect('/courses/%{course_name}/lessons'), :as => "course"
end
Well, that got interesting fast. The basic principle here is to just use the #redirect method to send one route to
another route. If your route is quite simple, it's a really straightforward method. But if you want to also send the
original parameters, you need to do a bit of gymnastics by capturing the parameter inside %{here}. Note the single
quotes around everything.
In the example above, we've also renamed the route for convenience by using an alias with the :as parameter. This
lets us use that name in methods like the #_path helpers. Again, test out your $ rake routes with questions.
You can work around this limitation by using a constraint to broaden the accepted input.
For example, if you want to reference a user record by email address in the url:
In addition to the model file in app/models, the generator will also create:
You can also generate some fields for the model when generating it.
This will create the columns email, sign_in_count and birthday in your database, with the appropriate types.
For instance, say you have a listing that expires within 30 days of creation.
private
def set_expiry_date
expiry_date = Date.today + 30.days
self.update_column(:expires_on, expiry_date)
end
end
All of the available methods for callbacks are as follows, in the same order that they are called during the operation
of each object:
Creating an Object
before_validation
after_validation
before_save
around_save
before_create
around_create
after_create
after_save
Updating an Object
before_validation
after_validation
before_save
around_save
before_update
around_update
after_update
after_save
after_commit/after_rollback
Destroying an Object
before_destroy
around_destroy
after_destroy
after_commit/after_rollback
NOTE: after_save runs both on create and update, but always after the more specific callbacks after_create and
after_update, no matter the order in which the macro calls were executed.
Model files are stored in app/models/, and the file name corresponds to the singular name of the class:
# user
app/models/user.rb
# SomeModel
app/models/some_model.rb
The class will inherit all the ActiveRecord features: query methods, validations, callbacks, etc.
Note: Make sure that the table for the corresponding model exists. If not, you can create the table by creating a
Migration
You can generate a model and it's migration by terminal from the following command
and can also assign foreign key(relationship) to the model by following command
For example, if you had a database schema with a Users table having a name:string column and email:string, you
could run:
Or if this is your first or only record, you could simply get the first record by running:
User.first
This will create a migration that adds a title column to a categories table:
Similarly, you can generate a migration to remove a column: rails generate migration
RemoveTitleFromCategories title:string
This will create a migration that removes a title column from the categories table:
While, strictly speaking, specifying type (:string in this case) is not necessary for removing a column, it's helpful,
since it provides the information necessary for rolling it back.
Rails recognizes the intent to create a table from the Create prefix, the rest of the migration name will be used as a
table name. The given example generates the following:
Notice that the creation command didn't specify types of columns and the default string was used.
Rails detects the intent to create a join table by finding JoinTable in migration name. Everything else is determined
from the names of the fields you give after the name.
Precedence
Notice that the example migration name CreateJoinTableParticipation matches the rule for table creation: it has
a Create prefix. But it did not generate a simple create_table. This is because migration generator (source code)
uses a first match of the following list:
(Add|Remove)<ignored>(To|From)<table_name>
<ignored>JoinTable<ignored>
Create<table_name>
The actual name of the table needs to follow this convention: the model which alphabetically precedes the other
must go first. Project preceds Tags so the name of the table is projects_tags.
Also since the purpose of this table is to route the association between the instances of two models, the actual id of
every record in this table is not necessary. You specify this by passing id: false
Finally, as is convention in Rails, the table name must be the compound plural form of the individual models, but
the column of the table must be in singular form.
Now to update the first_name and last_name of a user with id = 1, you can write the following code.
user = User.find(1)
user.update(first_name: 'Kashif', last_name: 'Liaqat')
Calling update will attempt to update the given attributes in a single transaction, returning true if successful and
false if not.
Let's say you have a controller articles_controller.rb. For this controller you would have a folder in views called
app/views/articles:
app
|-- controllers
| '-- articles_controller.rb
|
'-- views
'-- articles
| |- index.html.erb
| |- edit.html.erb
| |- show.html.erb
| |- new.html.erb
| '- _partial_view.html.erb
|
'-- [...]
This structure allows you to have a folder for each controller. When calling an action in your controller the
appropriate view will be rendered automatically.
// articles_controller.rb
class ArticlesController < ActionController::Base
def show
end
end
// show.html.erb
<h1>My show view</h1>
To create a partial, create a new file that begins with an underscore: _form.html.erb
To render a partial as part of a view, use the render method within the view: <%= render "form" %>
To pass a variable into the partial as a local variable, use this notation:
Partials are also useful when you need to reuse exactly the same code (DRY philosophy).
For example, to reuse <head> code, create a partial named _html_header.html.erb, enter your <head> code to be
Object Partials
Objects that respond to to_partial_path can also be rendered, as in <%= render @post %>. By default, for
ActiveRecord models, this will be something like posts/post, so by actually rendering @post, the file
views/posts/_post.html.erb will be rendered.
A local named post will be automatically assigned. In the end, <%= render @post %> is a short hand for <%= render
'posts/post', post: @post %>.
Collections of objects that respond to to_partial_path can also be provided, such as <%= render @posts %>. Each
item will be rendered consecutively.
Global Partials
To create a global partial that can be used anywhere without referencing its exact path, the partial has to be located
in the views/application path. The previous example has been modified below to illustrate this feature.
To render this global partial anywhere, use <%= render 'html_header' %>
Image helpers
image_path
image_url
image_tag
Use this helper if you want to include an <img src="" />-tag with the source set.
JavaScript helpers
javascript_include_tag
javascript_path
javascript_url
Stylesheet helpers
stylesheet_link_tag
stylesheet_path
stylesheet_url
Example usage
When creating a new rails app you will automatically have two of these helpers in
app/views/layouts/application.html.erb
This outputs:
// CSS
<link rel="stylesheet" media="all" href="/assets/application.self-
e19d4b856cacba4f6fb0e5aa82a1ba9aa4ad616f0213a1259650b281d9cf6b20.css?body=1" data-turbolinks-
track="reload" />
// JavaScript
<script
src="/assets/application.self-619d9bf310b8eb258c67de7af745cafbf2a98f6d4c7bb6db8e1b00aed89eb0b1.js?b
ody=1" data-turbolinks-track="reload"></script>
Declare content_for
<div>
<%= yield :header %>
</div>
Examples:
#myview.html.erb
<h1><%= @the_title %></h1>
<p>This is my form</p>
<%= render "form" %>
And in HAML:
#myview.html.haml
%h1= @the_title
%p
This is my form
= render 'form'
You see, the structure of the layout is much clearer than using HTML and ERB.
Installation
gem "haml"
For using HAML instead of HTML/ERB, just replace the file extensions of your views from something.html.erb to
something.html.haml.
Quick tipps
HTML
HAML
%div.myclass
.myclass
Attributes
HTML
HAML
Code starting with = will be executed and embedded into the document.
Code starting with - will be executed, but not inserted into the document.
Full documentation
HAML is very easy to start with, but is also very complex, so that I'll recommend reading the documentation.
For example, the following will add name, salary and email fields to the users table:
If you want to add an appropriate index and foreign_key on the added column, change the command to rails
generate migration AddTeamRefToUsers team:references:index. This will generate the following migration:
If you want to name your reference column other than what Rails auto generates, add the following to your
migration: (E.g.: You might want to call the User who created the Post as Author in the Post table)
Up a specific migration:
The version number in the above commands is the numeric prefix in the migration’s filename. For example, to
migrate to the migration 20160515085959_add_name_to_users.rb, you would use 20160515085959 as the version
number.
Run command:
You can use the STEP parameter to go back more than one version.
When the migration name is of the form AddXXXToTABLE_NAME followed by list of columns with data types, the
generated migration will contain the appropriate add_column statements.
When the migration name is of the form RemoveXXXFromYYY followed by list of columns with data types then the
generated migration will contain the appropriate remove_column statements.
While it’s not required to specify the data type (e.g. :string) as a parameter to remove_column, it is highly
recommended. If the data type is not specified, then the migration will not be reversible.
Migrations with defaults might take a long time in large tables with for example PostgreSQL. This is because each
row will have to be updated with the default value for the newly added column. To circumvent this (and reduce
downtime during deployments), you can split your migration into three steps:
When the migration name is of the form CreateXXX followed by list of columns with data types, then a migration
will be generated that creates the table XXX with the listed columns.
Specifying target version will run the required migrations (up, down, change) until it has reached the specified
version. Here, version number is the numerical prefix on the migration's filename.
This will create a new migration file in db/migration directory (if it doesn’t exist already), which will contain the file
prefixed with timestamp and migration file name which contains the below content:
def change
The above code prevents the user from ever rolling back the migration. You can avoid this problem by splitting the
change method into separate up and down methods:
def up
change_column :my_table, :my_column, :new_type
end
def down
change_column :my_table, :my_column, :old_type
end
The foreign key column will be pages_id. If you want to decide about the foreign key column name, you have to
create the column first and add the reference after.
rake db:migrate:status
Under the status field, up means the migration has been run and down means that we need to run the migration.
The above migration changes a table orders. Here is a line-by-line description of the changes:
1. t.remove :ordered_at removes the column ordered_at from the table orders.
2. t.string :skew_number adds a new string-type column named skew_number in the orders table.
3. t.index :skew_number adds an index on the skew_number column in the orders table.
4. t.rename :location, :state renames the location column in the orders table to state.
In practice, this can require a range of different types of refactoring, but it all comes down to one idea: by moving
any logic that isn’t about the response to the model (instead of the controller), not only have you promoted reuse
where possible but you’ve also made it possible to test your code outside of the context of a request.
Let’s look at a simple example. Say you have code like this:
def index
@published_posts = Post.where('published_at <= ?', Time.now)
@unpublished_posts = Post.where('published_at IS NULL OR published_at > ?', Time.now)
end
def index
@published_posts = Post.published
@unpublished_posts = Post.unpublished
end
Then, you can move the logic to your post model, where it might look like this:
Let's think on the Single Responsibility of models. What is the single responsibility of models? Is it to hold business
logic? Is it to hold non-response-related logic?
No. Its responsibility is to handle the persistence layer and its abstraction.
Business logic, as well as any non-response-related logic and non-persistence-related logic, should go in domain
objects.
Domain objects are classes designed to have only one responsibility in the domain of the problem. Let your classes
"Scream Their Architecture" for the problems they solve.
In practice, you should strive towards skinny models, skinny views and skinny controllers. The architecture of your
solution shouldn't be influenced by the framework you're choosing.
For example
Let's say you're a marketplace which charges a fixed 15% commission to your customers via Stripe. If you charge a
fixed 15% commission, that means that your commission changes depending on the order's amount because Stripe
The amount you charge as commission should be: amount*0.15 - (amount*0.029 + 0.30).
# app/models/order.rb
class Order < ActiveRecord::Base
SERVICE_COMMISSION = 0.15
STRIPE_PERCENTAGE_COMMISSION = 0.029
STRIPE_FIXED_COMMISSION = 0.30
...
def commission
amount*SERVICE_COMMISSION - stripe_commission
end
private
def stripe_commission
amount*STRIPE_PERCENTAGE_COMMISSION + STRIPE_FIXED_COMMISSION
end
end
As soon as you integrate with a new payment method, you won't be able to scale this functionality inside this
model.
Also, as soon as you start to integrate more business logic, your Order object will start to lose cohesion.
Prefer domain objects, with the calculation of the commission completely abstracted from the responsibility of
persisting orders:
# app/models/order.rb
class Order < ActiveRecord::Base
...
# No reference to commission calculation
end
# lib/commission.rb
class Commission
SERVICE_COMMISSION = 0.15
private
# lib/stripe_commission.rb
class StripeCommission
STRIPE_PERCENTAGE_COMMISSION = 0.029
STRIPE_FIXED_COMMISSION = 0.30
# app/controllers/orders_controller.rb
class OrdersController < ApplicationController
def create
@order = Order.new(order_params)
@order.commission = Commission.calculate("Stripe", @order)
...
end
end
it's extremely easy to unit test, as no fixtures or factories are required to instantiate the objects with the logic.
works with everything that accepts the message amount.
keeps each domain object small, with clearly defined responsibilities, and with higher cohesion.
easily scales with new payment methods by addition, not modification.
stops the tendency to have an ever-growing User object in each Ruby on Rails application.
I personally like to put domain objects in lib. If you do so, remember to add it to autoload_paths:
# config/application.rb
config.autoload_paths << Rails.root.join('lib')
You may also prefer to create domain objects more action-oriented, following the Command/Query pattern. In such
case, putting these objects in app/commands might be a better place as all app subdirectories are automatically
added to the autoload path.
class Post
default_scope ->{ where(published: true).order(created_at: :desc) }
end
The above code will serve posts which are already published when you perform any query on the model.
That scope, while innocuous-looking, has multiple hidden side-effect that you may not want.
Since you declared an order in the default_scope, calling order on Post will be added as additional orders instead
of overriding the default.
Post.order(updated_at: :desc)
SELECT "posts".* FROM "posts" WHERE "posts"."published" = 't' ORDER BY "posts"."created_at" DESC,
"posts"."updated_at" DESC
This is probably not the behavior you wanted; you can override this by excluding the order from the scope first
SELECT "posts".* FROM "posts" WHERE "posts"."published" = 't' ORDER BY "posts"."updated_at" DESC
As with any other ActiveRecord::Relation, default_scope will alter the default state of models initialized from it.
In the above example, Post has where(published: true) set by default, and so new models from Post will also
have it set.
default_scope can nominally be cleared by calling unscoped first, but this also has side-effects. Take, for example,
an STI model:
By default, queries against Post will be scoped to type columns containing 'Post'. But unscoped will clear this
along with your own default_scope, so if you use unscoped you have to remember to account for this as well.
By getting an individual User, you can see the posts related to it:
user = User.find(1)
user.posts
SELECT "posts".* FROM "posts" WHERE "posts"."published" = 't' AND "posts"."user_id" = ? ORDER BY
"posts"."created_at" DESC [["user_id", 1]]
But you want to clear the default_scope from the posts relation, so you use unscoped
user.posts.unscoped
Despite all of that, there are situations where using default_scope is justifiable.
subclass.class_eval do
default_scope ->{ where(tenant_id: Tenant.current_id) }
end
end
end
All you need to do is set Tenant.current_id to something early in the request, and any table that contains
tenant_id will automatically become scoped without any additional code. Instantiating records will automatically
inherit the tenant id they were created under.
The important thing about this use-case is that the scope is set once per request, and it doesn't change. The only
cases you will need unscoped here are special cases like background workers that run outside of a request scope.
To reduce the need for heavy configuration, Rails implements rules to ease up working with the application. You
may define your own rules but for the beginning (and for later on) it's a good idea to stick to conventions that Rails
offers.
These conventions will speed up development, keep your code concise and readable, and allow you an easy
navigation inside your application.
Conventions also lower the barriers to entry for beginners. There are so many conventions in Rails that a beginner
doesn’t even need to know about, but can just benefit from in ignorance. It’s possible to create great applications
without knowing why everything is the way it is.
For Example
If you have a database table called orders with the primary key id, the matching model is called order and the
controller that handles all the logic is named orders_controller. The view is split in different actions: if the
controller has a new and edit action, there is also a new and edit view.
For Example
To create an app you simply run rails new app_name. This will generate roughly 70 files and folders that comprise
the infrastructure and foundation for your Rails app.
It includes:
It involves whenever possible, re-using as much code as possible rather than duplicating similar code in multiple
places (for example, using partials). This reduces errors, keeps your code clean and enforces the principle of writing
code once and then reusing it. It is also easier and more efficient to update code in one place than to update
multiple parts of the same code. Thus making your code more modular and robust.
Also Fat Model, Skinny Controller is DRY, because you write the code in your model and in the controller only do the
call, like:
# Post model
scope :unpublished, ->(timestamp = Time.now) { where('published_at IS NULL OR published_at > ?',
timestamp) }
# Any controller
def index
....
@unpublished_posts = Post.unpublished
....
end
def others
...
@unpublished_posts = Post.unpublished
...
end
This also helps lead to an API driven structure where internal methods are hidden and changes are achieved
through passing parameters in an API fashion.
Problems
Overengineering
If a product is more complicated than it has to be, it is over engineered. Usually these “not yet used” features will
never be used in the intended way they were written and have to be refactored if they ever get used. Premature
optimisations, especially performance optimisations, often lead to design decisions which will be proved wrong in
the future.
Code Bloat
Code Bloat means unnecessary complicated code. This can occur for example by abstraction, redundancy or
incorrect application of design patterns. The code base becomes difficult to understand, confusing and expensive
to maintain.
Feature Creep
The time which could be used to develop necessary features is spent to develop unnecessary features. The product
takes longer to deliver.
Solutions
KISS - Keep it simple, stupid
According to KISS, most systems work the best if they are designed simple. Simplicity should be a primary design
goal to reduce complexity. It can be achieved by following the “Single Responsibility Principle” for example.
Less is more. Think about every feature, is it really needed? If you can think of any way that it’s YAGNI, leave it away.
It’s better to develop it when it’s needed.
Continuous Refactoring
The product is being improved steadily. With refactoring, we can make sure that the product is being done
according to best practice and does not degenerate to a patch work.
For Example: OrdersController would be the controller for an orders table. Rails will then look for the class
definition in a file called orders_controller.rb in the /app/controllers directory.
If the controller class name has multiple capitalized words, the table name is assumed to have underscores
between these words.
For Example: If a controller is named PendingOrdersController then assumed file name for this controller will be
pending_orders_controller.rb.
For Example: If a table was named orders, the associated model would be named Order
For Example: If a table was named posts, the associated model would be named Post
Rails will then look for the class definition in a file called order.rb in the /app/models directory.
If the model class name has multiple capitalized words, the table name is assumed to have underscores between
these words.
For Example: If a model is named BlogPost then assumed table name will be blog_posts.
app/controllers/application_controller.rb
is the file that contains the ApplicationController class definition. Note that while PascalCase is used for class
and module names, the files in which they reside should still be lower_snake_case.
Consistent naming is important since Rails makes use of auto-loading files as needed, and uses "inflection" to
transform between different naming styles, such as transforming application_controller to
ApplicationController and back again.
E.g. if Rails sees that the BlogPost class doesn't exist (hasn't been loaded yet), it'll look for a file named
blog_post.rb and attempt to load that file.
It is therefore also important to name files for what they contain, since the autoloader expects file names to match
content. If, for instance, the blog_post.rb instead contains a class named just Post, you'll see a LoadError:
Expected [some path]/blog_post.rb to define BlogPost.
One more thing to pay attention to (especially if English is not your first language) is the fact that Rails accounts for
irregular plural nouns in English. So if you have model named "Foot" the corresponding controller needs to be
called "FeetController" rather than "FootsController" if you want rails "magic" routing (and many more such
features) to work.
def connect
self.current_user = find_verified_user
logger.add_tags 'ActionCable', current_user.id
# Can replace current_user.id with usernames, ids, emails etc.
end
protected
def find_verified_user
if verified_user = env['warden'].user
verified_user
else
reject_unauthorized_connection
end
end
end
end
def unsubscribed
end
def notify(data)
ActionCable.server.broadcast "notifications", { title: 'New things!', body: data }
end
end
disconnected: ->
# Called when the subscription has been terminated by the server
$(document).off "change", "input"
notify: (data)->
@perform('notify', data: data)
(function() {
this.App || (this.App = {});
App.cable = ActionCable.createConsumer();
}).call(this);
class User
include ActiveModel::Validations
gem 'devise'
Set up the default URL options for the Devise mailer in each environment In development environment add this
line:
to your config/environments/development.rb
Then create a model using:$ rails generate devise USER Where USER is the class name for which you want to
implement authentication.
Custom views
If you need to configure your views, you can use the rails generate devise:views generator that will copy all
views to your application. Then you can edit them as desired.
If you have more than one Devise model in your application (for example User and Admin), you will notice that
Devise uses the same views for all models. Devise offers an easy way to customize views. Set config.scoped_views
= true inside the config/initializers/devise.rb file.
You can also use the generator to create scoped views: rails generate devise:views users
If you would like to generate only a few sets of views, such as the ones for the registerable and confirmable module
use the -v flag: rails generate devise:views -v registrations confirmations
before_action :authenticate_user!
user_signed_in?
current_user
user_session
Note that if your Devise model is called Member instead of User, replace user above with member
Rails.application.config.middleware.use OmniAuth::Builder do
require 'openid/store/filesystem'
provider :github, ENV['GITHUB_KEY'], ENV['GITHUB_SECRET']
provider :openid, :store => OpenID::Store::Filesystem.new('/tmp')
end
By default, OmniAuth will add /auth/:provider to your routes and you can start by using these paths.
user.authenticate('somepassword')
Now when you create a new user a token and auth_token are automatically generated
user = User.new
user.save
user.token # => "pX27zsMN2ViQKta1bGfLmVJE"
user.auth_token # => "77TMHrHJFvFDwodq8w7Ev2m7"
Without this association, you’d have all these foreign keys in your Address table but you only would ever have a
value for one of them because an address, in this scenario, can only belong to one entity (Human or Company).
Here is what it would look like:
ex.
For example, if your application includes users and posts, and each post can be assigned to exactly one user, you'd
declare the post model this way:
For example, if each user in your application has only one account, you'd declare the user model like this:
In Active Record, when you have a has_one relation, active record ensures that the only one record exists with the
foreign key.
Here in our example: In accounts table, there can only be one record with a particular user_id. If you try to associate
one more account for the same user, it makes the previous entry's foreign key as null(making it orphan) and
creates a new one automatically. It makes the previous entry null even if the save fails for the new entry to maintain
consistency.
user = User.first
user.build_account(name: "sample")
user.save [Saves it successfully, and creates an entry in accounts table with user_id 1]
user.build_account(name: "sample1") [automatically makes the previous entry's foreign key null]
user.save [creates the new account with name sample 1 and user_id 1]
This association indicates that each instance of the model has zero or more instances of another model.
For example, in an application containing users and posts, the user model could be declared like this:
The table structure of Post would remain the same as in the belongs_to example; in contrast, User would not
require any schema changes.
If you want to get the list of all the published posts for the User, then you can add the following (i.e. you can add
scopes to your association objects):
For example, consider a medical practice where patients make appointments to see physicians. The relevant
association declarations could look like this:
For example, if each supplier has one account, and each account is associated with one account history, then the
supplier model could look like this:
For example, if your application includes assemblies and parts, with each assembly having many parts and each
part appearing in many assemblies, you could declare the models this way:
:minimum - The attribute cannot have less than the specified length.
:maximum - The attribute cannot have more than the specified length.
:in (or :within) - The attribute length must be included in a given interval. The value for this option must be
a range.
:is - The attribute length must be equal to the given value.
You can also define a constant and set its value to a regular expression and pass it to the with: option. This might
be more convenient for really complex regular expressions
PHONE_REGEX = /\A\(\d{3}\)\d{3}-\d{4}\z/
validates :phone, format: { with: PHONE_REGEX }
The default error message is is invalid. This can be changed with the :message option.
validates :bio, format: { with: /\A\D+\z/, message: "Numbers are not allowed" }
The reverse also replies, and you can specify that a value should not match a regular expression with the without:
option
You can use the absence helper to validate that the specified attributes are absent. It uses the present? method to
check for nil or empty values.
Note: In case the attribute is a boolean one, you cannot make use of the usual presence validation (the attribute
would not be valid for a false value). You can get this done by using an inclusion validation:
Implement the validate method which takes a record as an argument and performs the validation on it. Then use
validates_with with the class on the model.
# app/validators/starts_with_a_validator.rb
class StartsWithAValidator < ActiveModel::Validator
def validate(record)
unless record.name.starts_with? 'A'
record.errors[:name] << 'Need a name starting with A please!'
end
end
end
If you prefer to use your new validator using the common validate method on a single param, create a class
inheriting from ActiveModel::EachValidator and implement the validate_each method which takes three
arguments: record, attribute, and value:
All validations inside of the with_options block will have automatically passed the condition if: :is_admin?
Besides :only_integer, this helper also accepts the following options to add constraints to acceptable values:
:greater_than - Specifies the value must be greater than the supplied value. The default error message for
this option is "must be greater than %{count}".
:greater_than_or_equal_to - Specifies the value must be greater than or equal to the supplied value. The
default error message for this option is "must be greater than or equal to %{count}".
:equal_to - Specifies the value must be equal to the supplied value. The default error message for this
option is "must be equal to %{count}".
:less_than - Specifies the value must be less than the supplied value. The default error message for this
option is "must be less than %{count}".
:less_than_or_equal_to - Specifies the value must be less than or equal to the supplied value. The default
error message for this option is "must be less than or equal to %{count}".
:other_than - Specifies the value must be other than the supplied value. The default error message for this
option is "must be other than %{count}".
:odd - Specifies the value must be an odd number if set to true. The default error message for this option is
"must be odd".
:even - Specifies the value must be an even number if set to true. The default error message for this option is
"must be even".
By default, numericality doesn't allow nil values. You can use allow_nil: true option to permit it.
There is a :scope option that you can use to specify one or more attributes that are used to limit the uniqueness
check:
There is also a :case_sensitive option that you can use to define whether the uniqueness constraint will be case
sensitive or not. This option defaults to true.
decrement!
decrement_counter
increment!
increment_counter
toggle!
touch
update_all
update_attribute
update_column
update_columns
update_counters
You can also skip validation while saving by passing validate as an argument to save
User.save(validate: false)
To require confirmation, make sure to add a presence check for the confirmation attribute.
Source
def admin?
conditional here that returns boolean value
end
end
You can also pass a string, which will be executed via instance_eval:
ActiveRecord will perform queries on the database for you and is compatible with most database systems.
Regardless of which database system you're using, the ActiveRecord method format will always be the same.
The where method accepts a hash where the keys correspond to the column names on the table that the model
represents.
To find all people with the first name of Sven and last name of Schrodinger:
In the above example, the sql output shows that records will only be returned if both the first_name and the
last_name match.
If the array contains a nil, the SQL will be modified to check if the column is null:
end
minors = Person.minors
peters_children = Person.minors.with_last_name('Peters')
The where method and other query type methods can also be chained:
Behind the scenes, scopes are simply syntactic sugar for a standard class method. For example, these methods are
functionally identical:
def self.with_last_name(name)
where(name: name)
end
Default Scope
in your model to set a default scope for all operations on the model.
To get the first record from users table we need to type following command:
User.first
#<User:0x007f8a6db09920 id: 1, first_name: foo, created_at: Thu, 16 Jun 2016 21:43:03 UTC +00:00,
updated_at: Thu, 16 Jun 2016 21:43:03 UTC +00:00 >
To get the last record from users table we need to type following command:
User.last
#<User:0x007f8a6db09920 id: 10, first_name: bar, created_at: Thu, 16 Jun 2016 21:43:03 UTC +00:00,
updated_at: Thu, 16 Jun 2016 21:43:03 UTC +00:00 >
Passing an integer to first and last method creates a LIMIT query and returns array of objects.
User.first(5)
And
User.last(5)
User.order(:created_at)
#=> => [#<User id: 2, created_at: "2015-08-12 21:36:23">, #<User id: 11, created_at: "2015-08-15
10:21:48">]
If not specified, ordering will be performed in ascending order. You can specify it by doing:
User.order(created_at: :asc)
#=> => [#<User id: 2, created_at: "2015-08-12 21:36:23">, #<User id: 11, created_at: "2015-08-15
10:21:48">]
User.order(created_at: :desc)
#=> [#<User id: 7585, created_at: "2016-07-13 17:15:27">, #<User id: 7583, created_at: "2016-07-13
16:51:18">]
User.order("created_at DESC")
#=> [#<User id: 7585, created_at: "2016-07-13 17:15:27">, #<User id: 7583, created_at: "2016-07-13
16:51:18">]
As the string is raw SQL, you can also specify a table and not only an attribute. Assuming you want to order users
according to their role name, you can do this:
User.includes(:role).order("roles.name ASC")
User.includes(:role).order(User.arel_table[:name].asc)
Author.joins(:books).where(books: { bestseller: true } ) will load only authors with conditions into
memory without loading books. Use joins when additional information about nested associations isn't required.
User.joins(:posts)
Pay attention on plural form. If your relation is :has_many, then the joins() argument should be pluralized.
Otherwise, use singular.
Nested joins:
"SELECT "users".* FROM "users" INNER JOIN "posts" ON "posts"."user_id" = "users"."id" INNER JOIN
"images" ON "images"."post_id" = "images"."id""
For Example
As offset is not mentioned in above query so it will return first three records.
So, if you have a User model with a first_name attribute you can do:
User.find_by(first_name: "John")
#=> #<User id: 2005, first_name: "John", last_name: "Smith">
Mind that find_by doesn't throw any exception by default. If the result is an empty set, it returns nil instead of
find.
If the exception is needed may use find_by! that raises an ActiveRecord::RecordNotFound error like find.
User.delete_all
#=> 39 <-- .delete_all return the number of rows deleted
User.where(name: "John").delete_all
You can use ActiveRecord's underlying Arel matches method to do this in a safe way:
Arel will apply the appropriate LIKE or ILIKE construct for the database engine configured.
Product.select(:category).group(:category)
Make sure that the grouped field is also selected. Grouping is especially useful for counting the occurrence - in this
case - of categories.
Product.select(:category).group(:category).count
As the query shows, it will use the database for counting, which is much more efficient, than retrieving all record
first and do the counting in the code:
Customers.select(:country).distinct
.uniq() has the same effect. With Rails 5.0 it got deprecated and it will be removed from Rails with version 5.1. The
reason is, that the word unique doesn't have the same meaning as distinct and it can be misleading. Furthermore
distinct is closer to the SQL syntax.
In this case, the user model calls the approved method in the mailer and passes the post that has been approved
(the approved method in the model may be called by a callback, from a controller method, etc). Then, the mailer
generates the email from either the html or plain-text template using the information from the passed-in post (e.g.
the title). By default, the mailer uses the template with the same name as the method in the mailer (which is why
both the mailer method and the templates have the name 'approved').
user_mailer.rb
class UserMailer < ActionMailer::Base
default from: "[email protected]"
def approved(post)
@title = post.title
@user = post.user
mail(to: @user.email, subject: "Your Post was Approved!")
end
end
user.rb
def approved(post)
UserMailer.approved(post)
end
approved.html.erb
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Post Approved</title>
</head>
<body>
<h2>Congrats <%= @user.name %>! Your post (#<%= @title %>) has been approved!</h2>
<p>We look forward to your future posts!</p>
</body>
</html>
approved.text.erb
Congrats <%= @user.name %>! Your post (#<%= @title %>) has been approved!
We look forward to your future posts!
Two layout files will also be generated for the email view, one for the html format and one for the text format.
If you prefer not to use the generator, you can create your own mailers. Make sure they inherit from
ActionMailer::Base
An interceptor class must implement the :delivering_email(message) method which will be called before the email is
sent, allowing you to make modifications to the email before it hits the delivery agents. Your class should make any
needed modifications directly to the passed in Mail::Message instance.
It can be useful for developers to send email to themselves not real users.
# config/initializers/override_mail_recipient.rb
if Rails.env.development? or Rails.env.test?
class OverrideMailRecipient
def self.delivering_email(mail)
mail.subject = 'This is dummy subject'
mail.bcc = '[email protected]'
mail.to = '[email protected]'
end
end
ActionMailer::Base.register_interceptor(OverrideMailRecipient)
end
attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
By default, attachments will be encoded with Base64. To change this, you can add a hash to the attachments
method.
attachments['filename.jpg'] = {
mime_type: 'application/gzip',
encoding: 'SpecialEncoding',
content: encoded_content
attachments.inline['image.jpg'] = File.read('/path/to/image.jpg')
before_action
after_action
around_action
private
def set_delivery_options
end
def prevent_delivery_to_guests
end
def set_business_headers
end
end
subl app/models/newsletter.rb
def create
@newsletter = Newsletter.create(newsletter_params)
if @newsletter.save
redirect_to blog_index_path
else
private
def set_newsletter
@newsletter = Newsletter.find(params[:id])
end
def newsletter_params
params.require(:newsletter).permit(:name, :email)
end
end
After that, change the create.html.erb view to the nex name. We will convert this file to and partial view which will
be stored inside the Footer. The name will be _form.html.erb.
subl app/config/routes.rb
resources :newsletters
Later on, we need to set the form we will use to save each mail:
subl app/views/newsletters/_form.html.erb
subl app/views/layouts/_footer.html.erb
Now, install the -letter_opener- to can preview email in the default browser instead of sending it. This means you
do not need to set up email delivery in your development environment, and you no longer need to worry about
accidentally sending a test email to someone else's address.
subl your_project/Gemfile
subl your_project/app/config/environments/development.rb
config.action_mailer.delivery_method = :letter_opener
Now, create an Mailer Structure to manage the whole mailers which we will work. In terminal
And inside the UserMailer, we have to create a method called Newsletter Mailer which will be created to contain
inside on the lastest blog post and will be fired with a rake action. We will assume that you had a blog structure
created before.
subl your_project/app/mailers/user_mailer.rb
def newsletter_mailer
@newsletter = Newsletter.all
@post = Post.last(3)
emails = @newsletter.collect(&:email).join(", ")
mail(to: emails, subject: "Hi, this is a test mail.")
end
end
subl your_project/app/views/user_mailer/newsletter_mailer.html.erb
<br/>
<table>
<% @post.each do |post| %>
<%#= link_to blog_url(post) do %>
<tr style="display:flex; float:left; clear:both;">
<td style="display:flex; float:left; clear:both; height: 80px; width: 100px;">
<% if post.cover_image.present? %>
<%= image_tag post.cover_image.fullsize.url, class:"principal-home-image-slider" %>
<%# else %>
<%#= image_tag 'http://your_site_project.com' + post.cover_video, class:"principal-home-
image-slider" %>
<%#= raw(video_embed(post.cover_video)) %>
<% end %>
</td>
</tr>
<%# end %>
<% end %>
</table>
Since we want to send the email as a separate process, let’s create a Rake task to fire off the email. Add a new file
called email_tasks.rake to lib/tasks directory of your Rails application:
touch lib/taks/email_tasks.rake
The send_digest_email: :environment means to load the Rails environment before running the task, so you can
access the application classes (like UserMailer) within the task.
Now, running the command rake -T will list the newly created Rake task. Test everything works by running the task
and checking whether the email is sent or not.
rake weekly_newsletter_email
At this point, we have a working rake task which can be scheduled using crontab. So we will install the Whenever
Gem which is used to provide a clear syntax for writing and deploying cron jobs.
subl your_project/Gemfile
After that, run the next command to create an initial config/schedule.rb file for you (as long as the config folder is
already present in your project).
wheneverize .
Now, inside the schedule file, we have to create our CRON JOB and call the mailer method inside determining the
CRON JOB to operate some tasks without assistance and in a selected range of time. You can use different types of
syntax as is explained on this link.
Now to test the Cron Job was succesfully created we can use the next command to read since terminal, our
scheduled job in CRON SYNTAX:
Now, to run the test in Development Environment, is wise to set the next line on the application.rb principal file to
let the application knows where are the models it will use.
subl your_project/config/application.rb
Now to let Capistrano V3 save the new Cron Job inside the server and the trigger which will fired up the execution
of this task, we have to add the next requirement:
subl your_project/Capfile
require 'whenever/capistrano'
And insert into the deploy file the identifier which CRON JOB will use about the environment and the name of the
application.
subl your_project/config/deploy.rb
And ready, after save changes on each file, run the capistrano deploy command:
And now your JOB was created and calendarize to run the Mailer Method which is what i want and in the range of
time we set on this files.
The controller generator is expecting parameters in the form of generate controller ControllerName action1
action2.
create app/controllers/greetings_controller.rb
route get "greetings/hello"
invoke erb
create app/views/greetings
create app/views/greetings/hello.html.erb
invoke test_unit
create test/controllers/greetings_controller_test.rb
invoke helper
create app/helpers/greetings_helper.rb
invoke assets
invoke coffee
create app/assets/javascripts/greetings.coffee
invoke scss
create app/assets/stylesheets/greetings.scss
File Example
Controller File greetings_controller.rb
View File hello.html.erb
Functional Test File greetings_controller_test.rb
View Helper greetings_helper.rb
JavaScript File greetings.coffee
For a list of all the options supported by the command, you could run the command without any arguments as in
rails generate migration.
For example, if you want to add first_name and last_name fields to users table, you can do:
Now, apply the pending migrations to the database by running the following in the terminal:
Note: For even less typing, you can replace generate with g.
To generate a fully working scaffold for a new object, including model, controller, views, assets, and tests, use the
rails g scaffold command.
Then you can run rake db:migrate to set up the database table.
Then you can visit http://localhost:3000/widgets and you'll see a fully functional CRUD scaffold.
'NAME' is the name of the model. 'field' is the name of the column in the DB table and 'type' is the column type (e.g.
name:string or body:text). Check the Remarks section for a list of supported column types.
So say you wanted to setup a User model that has a username, email and belongs to a School, you would type in
the following
rails g is shorthand for rails generate. This would produce the same result
The content of neo4j.yml can be something like the below (for simplicity, default is used for all environments):
default: &default
host: localhost
port: 7474
username: neo4j
password: root
development:
<<: *default
test:
<<: *default
production:
<<: *default
in config/application.rb:
module MyApp
class Application < Rails::Application
config.neo4j = config_for(:neo4j)
end
end
Rails.configuration.neo4j['host']
#=> localhost
Rails.configuration.neo4j['port']
#=> 7474
More info
You can configure your own code through the Rails configuration object with custom configuration under the
config.x property.
Example
config.x.payment_processing.schedule = :daily
config.x.payment_processing.retries = 3
config.x.super_debugger = true
# Example config/locales/en.yml
en:
page:
users: "%{users_count} users currently online"
# In views
# ERB
<%= t('page.users', users_count: 12) %>
#SLIM
= t('page.users', users_count: 12)
gem 'activemodel-serializers-xml'
Model translations allow you to translate your models' attribute values, for example:
I18n.locale = :en
post.title # => Globalize rocks!
I18n.locale = :he
post.title # => שולט2!גלובאלייז
For this migration you need to use up and down, and not change. Also, in order to run this migration successfully,
you have to define the translated attributes in your model first, like shown above. A proper migration for the
previous Post model is this:
def down
Post.drop_translation_table!
end
end
def down
Post.drop_translation_table!
end
end
In case you already have any existing data in your needing translation columns, you can easily migrate it to the
translations table, by adjusting your migration:
end
def down
Post.drop_translation_table! migrate_data: true
end
end
Make sure you drop the translated columns from the parent table after all your data is safely migrated. To
automatically remove the translated columns from the parent table after the data migration, add the option
remove_source_columns to the migration:
end
def down
Post.drop_translation_table! migrate_data: true
end
end
You may also add new fields to a previously created translations table:
def down
remove_column :post_translations, :author
end
end
# Gemfile
gem 'geocoder'
Geocoder adds location and safe_location methods to the standard Rack::Request object so you can easily look
up the location of any HTTP request by IP address. You can use this methods in a before_action in your
ApplicationController:
def set_locale_from_request
country_code = request.location.data["country_code"] #=> "US"
country_sym = country_code.underscore.to_sym #=> :us
# If request locale is available use it, otherwise use I18n default locale
if I18n.available_locales.include? country_sym
I18n.locale = country_sym
end
end
Beware that this will not work in development and test environments, as things like 0.0.0.0 and localhost are
valid valid Internet IP addresses.
Geocoder is very powerful and flexible, but needs to be configured to work with a geocoding service (see more
details); many of which place limits on usage. It's also worth bearing in mind that calling an external service on
every request could impact performance.
1. An offline solution
Using a gem like GeoIP (see here) allows lookups to happen against a local datafile. There may be a trade-off in
terms of accuracy, as these datafiles need to be kept up-to-date.
2. Use CloudFlare
Pages served through CloudFlare have the option of being geocoded transparently, with the country code being
added to the header (HTTP_CF_IPCOUNTRY). More detail can be found here.
# config/locales/en.yml
en:
online_users:
one: "1 user is online"
other: "%{count} users are online"
And then use the key you just created by passing the count argument to I18n.t helper:
I18n.t("online_users", count: 1)
#=> "1 user is online"
I18n.t("online_users", count: 4)
#=> "4 users are online"
protected
def set_locale
# Remove inappropriate/unnecessary ones
I18n.locale = params[:locale] || # Request parameter
session[:locale] || # Current session
(current_user.preferred_locale if user_signed_in?) || # Model saved configuration
extract_locale_from_accept_language_header || # Language header - browser config
I18n.default_locale # Set in your config files, english by super-default
end
URL-based
http://yourapplication.com/products?locale=en
Or
http://yourapplication.com/en/products
To achieve the latter, you need to edit your routes, adding a scope:
# config/routes.rb
scope "(:locale)", locale: /en|fr/ do
resources :products
end
By doing this, visiting http://yourapplication.com/en/products will set your locale to :en. Instead, visiting
http://yourapplication.com/fr/products will set it to :fr. Furthermore, you won't get a routing error when
missing the :locale param, as visiting http://yourapplication.com/products will load the default I18n locale.
Session-based or persistence-based
This assumes the user can click on a button/language flag to change the language. The action can route to a
controller that sets the session to the current language (and eventually persist the changes to a database if the user
is connected)
You have to define sanitize_language_param with your list of available languages, and eventually handle
errors in case the language doesn't exist.
If you have very few languages, it may be worth defining them like this instead:
def fr
I18n.locale = :fr
set_session_and_redirect
end
def en
private
def set_session_and_redirect
session[:locale] = I18n.locale
redirect_to :back
end
def set_preferred_locale
if user_signed_in?
current_user.preferred_locale = I18n.locale.to_s
current_user.save if current_user.changed?
end
end
end
Default Locale
Remember that you need to set your application default locale. You can do it by either setting it in
config/application.rb:
config.i18n.default_locale = :de
# config/initializers/locale.rb
I18n.default_locale = :it
And in Views,
# ERB
<h2><%= t(:title_html, scope: [:stackoverflow, :header]) %></h2>
# config/locales/en.yml
en:
header:
title: "My header title"
# in ERB files
<%= t('header.title') %>
# in SLIM files
= t('header.title')
# app/views/layouts/my_layout.html.haml
!!!
%html{:lang => 'en'}
%head
- # ...
= google_maps_api_script_tag
# app/helpers/google_maps_helper.rb
module GoogleMapsHelper
def google_maps_api_script_tag
javascript_include_tag google_maps_api_source
end
def google_maps_api_source
"https://maps.googleapis.com/maps/api/js?key=#{google_maps_api_key}"
end
def google_maps_api_key
Rails.application.secrets.google_maps_api_key
end
end
You can register your application with google and get your api key in the google api console. Google has a short
guide how to request an api key for the google maps javascript api.
# config/secrets.yml
development:
google_maps_api_key: '...'
# ...
production:
google_maps_api_key: '...'
# ...
Don't forget to add config/secrets.yml to your .gitignore file and makre sure you don't commit the api key to
the repository.
# app/models/profile_fields/address.rb
class ProfileFields::Address < ProfileFields::Base
# Attributes:
# label, e.g. "Work address"
A great way to geocode the addresses, i.e. provide longitude and latitude is the geocoder gem.
# Gemfile
gem 'geocoder', '~> 1.3'
Add database columns for latitude and longitude in order to save the location in the database. This is more
efficient than querying the geocoding service every time you need the location. It's faster and you're not hitting the
query limit so quickly.
Add the geocoding mechanism to your model. In this example, the address string is stored in the value attribute.
Configure the geocoding to perform when the record has changed, and only whan a value is present:
# app/models/profile_fields/address.rb
class ProfileFields::Address < ProfileFields::Base
geocoded_by :value
after_validation :geocode, if: ->(address_field){
address_field.value.present? and address_field.value_changed?
}
end
By default, geocoder uses google as lookup service. It has lots of interesting features like distance calculations or
proximity search. Fore more information, have a look at the geocoder README.
- # app/views/profiles/show.html.haml
%h1 Contact Information
.profile_fields
= render @profile_fields
.google_map{data: address_fields: @address_fields.to_json }
# app/controllers/profiles_controller.rb
class ProfilesController < ApplicationController
def show
# ...
@profile_fields = @user_or_group.profile_fields
@address_fields = @profile_fields.where(type: 'ProfileFields::Address')
end
end
For example:
To make use of the $(document).ready event with turbolinks without managing the turbolinks events by hand, use
the jquery.turbolinks gem.
If you want to perform some other operations with the map, later, for example filtering or info windows, it's
convenient to have the map managed by a coffee script class.
# app/assets/javascripts/google_maps.js.coffee
window.App = {} unless App?
class App.GoogleMap
constructor: (map_div)->
# TODO: initialize the map
# TODO: set the markers
When using several coffee script files, which are namespaced by default, it's convenient to define a global App
namespace, which is shared by all coffee script files.
# app/assets/javascripts/google_maps.js.coffee
# ...
$(document).ready ->
App.google_maps = []
$('.google_map').each ->
map_div = $(this)
map = new App.GoogleMap map_div
App.google_maps.push map
# app/assets/javascripts/google_maps.js.coffee
# ...
class App.GoogleMap
map_div: {}
map: {}
constructor: (map_div)->
@map_div = map_div
@init_map()
@reference_the_map_as_data_attribute
init_map: ->
@map = new google.maps.Map(@dom_element, @map_configuration) if google?
map_configuration: -> {
scrollWheel: true
}
To learn more about the possible map_configuration options, have a look at google's MapOptions documentation
and their guide to adding control elements.
# app/assets/javascripts/google_maps.js.coffee
# ...
class App.GoogleMap
# ...
markers: []
constructor: (map_div)->
# ...
@init_markers()
address_fields: ->
@map_div.data('address-fields')
init_markers: ->
self = this # to reference the instance as `self` when `this` is redefined.
self.markers = []
for address_field in self.address_fields()
marker = new google.maps.Marker {
map: self.map,
position: {
lng: address_field.longitude,
lat: address_field.latitude
},
# # or, if `position` is defined in `ProfileFields::Address#as_json`:
# position: address_field.position,
title: address_field.value
}
self.markers.push marker
To learn more about marker options, have a look at google's MarkerOptions documentation and their guide to
markers.
# app/assets/javascripts/google_maps.js.coffee
# ...
class App.GoogleMap
# ...
bounds: {}
constructor: (map_div)->
# ...
@auto_zoom()
auto_zoom: ->
@init_bounds()
# TODO: Maybe, adjust the zoom to have a maximum or
# minimum zoom level, here.
init_bounds: ->
When calling to_json on an ApplicationRecord object, the database attributes are automatically exposed.
Given a ProfileFields::Address model with label, value, longitude and latitude attributes,
address_field.as_json results in a Hash, e.g. representation,
address_field.as_json # =>
{label: "Work address", value: "Willy-Brandt-Straße 1\n10557 Berlin",
longitude: ..., latitude: ...}
address_field.to_json # =>
"{\"label\":\"Work address\",\"value\":\"Willy-Brandt-Straße 1\\n
10557 Berlin\",\"longitude\":...,\"latitude\":...}"
This is useful because it allows to use label and value later in javascript, for example to show tool tips for the map
markers.
Other attributes
For example, to expose a title attribute, include it in the merged as_json hash:
# app/models/profile_fields/address.rb
class ProfileFields::Address < ProfileFields::Base
# ...
def as_json
super.merge {
title: self.title
}
end
end
The above example uses super to call the original as_json method, which returns the original attribute hash of the
object, and merges it with the required position hash.
Position
To render markers, the google maps api, by default, requires a position hash which has longitude and latitude
stored as lng and lat respectively.
This position hash can be created in javascript, later, or here when defining the json representation of the address
field:
To provide this position as json attribute of the address field, just override the as_json method on the model.
# app/models/profile_fields/address.rb
class ProfileFields::Address < ProfileFields::Base
# ...
def as_json
super.merge {
# ...
position: {
lng: self.longitude,
lat: self.latitude
}
}
end
end
Let's have an look on example with simple avatar upload image with Carrierwave
Here you can set up storage (i.e local or cloud), apply extensions for image manipulations (i.e. generting thumbs via
MiniMagick) and set server-side extension white list
Next, create new migration with string tipe for user_pic and mount uploader for it in user.rb model.
Next, display an form to upload avatar (may be an edit view for the user)
Make sure to include { multipart: true } in order form can process uploads. Accept is an optional to set client-side
extension white-list.
Let's say you want an multiple images for the Product model. Create an new model and make it belongs_to your
parent model
#product.rb
has_many :product_photos, dependent: :destroy
accepts_nested_attributes_for :product_photos
#product_photo.rb
belongs_to :product
mount_uploader :image_url, ProductPhotoUploader # make sure to include uploader (Carrierwave
example)
Controller is nothing special, if you don't want to create an new one, just make an new one inside your product
controller
# create an action
def upload_file
printer = Product.find_by_id(params[:id])
@product_photo = printer.prodcut_photos.create(photo_params)
end
# strong params
private
def photo_params
params.require(:product_photos).permit(:image)
end
The advantage of Russian doll caching is that if a single product is updated, all the other inner fragments can be
reused when regenerating the outer fragment.
As explained in the previous section, a cached file will expire if the value of updated_at changes for a record on
which the cached file directly depends. However, this will not expire any cache the fragment is nested within.
If any attribute of game is changed, the updated_at value will be set to the current time, thereby expiring the cache.
However, because updated_at will not be changed for the product object, that cache will not be expired and your
app will serve stale data. To fix this, we tie the models together with the touch method:
For example:
def index
# Run a find query
@products = Product.all
...
The second time the same query is run against the database, it's not actually going to hit the database. The first
time the result is returned from the query it is stored in the query cache (in memory) and the second time it's
pulled from memory.
However, it's important to note that query caches are created at the start of an action and destroyed at the end of
that action and thus persist only for the duration of the action. If you'd like to store query results in a more
persistent fashion, you can with low level caching.
def index
@secret_ingredients = Recipe.find(params[:recipe_id]).secret_ingredients
end
end
Options include :expires_in, a custom :cache_path (for actions with multiple routes that should be cached
differently) and :if/:unless to control when the action should be cached.
When the layout has dynamic content, cache only the action content by passing layout: false.
To fetch a value from the cache for a given key, use cache.read:
Rails.cache.read('city')
# => nil
Rails.cache.write('city', 'Duckburgh')
Rails.cache.read('city')
# => 'Duckburgh'
Alternatively, use cache.fetch to read a value from the cache and optionally write a default if there is no value:
Rails.cache.fetch('user') do
The return value of the passed block will be assigned to the cache under the given key, and then returned.
Use expire_page to force expiration of the cache by deleting the stored HTML file:
def index
@users = User.all
end
def create
expire_page :action => :index
end
end
In a controller action, use expires_in to set the length of caching for that action:
def show
@user = User.find params[:id]
expires_in 30.minutes, :public => true
end
Use expires_now to force immediate expiration of a cached resource on any visiting client or intermediary:
def show
@users = User.find params[:id]
expires_now if params[:id] == 1
end
The controller will receive the request, fetch or save data from a model and use a view to create output. A controller
can be thought of as a middleman between models and views. It makes the model data available to the view so it
can display to the user, and it saves or updates user data to the model.
def index
@posts = Post.all
end
def show
end
def new
@post = Post.new
end
def edit
end
def create
@post = Post.new(post_params)
respond_to do |format|
if @post.save
format.html { redirect_to @post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: @post }
else
format.html { render :new }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @post.update(post_params)
format.html { redirect_to @post.company, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: @post }
else
format.html { render :edit }
format.json { render json: @post.errors, status: :unprocessable_entity }
end
end
end
def destroy
@post.destroy
respond_to do |format|
private
def set_post
@post = Post.find(params[:id])
end
def post_params
params.require(:post).permit(:title, :body, :author)
end
end
Before Filter
Before filters are executed before the controller action and can halt the request (and/or redirect). A common use is
to verify if a user is logged in:
def authenticate_user!
redirect_to some_path unless user_signed_in?
end
end
Before filters are run on requests before the request gets to the controller’s action. It can return a response itself
and completely bypass the action.
Other common uses of before filters is validating a user’s authentication before granting them access to the action
designated to handle their request. I’ve also seen them used to load a resource from the database, check
permissions on a resource, or manage redirects under other circumstances.
After Filter
After filters are similar to "before" ones, but as they get executed after the action run they have access the
response object that's about to be sent. So in short after filters are run after the action completes. It can modify the
response. Most of the time if something is done in an after filter, it can be done in the action itself, but if there is
some logic to be run after running any of a set of actions, then an after filter is a good place to do it.
Generally, I’ve seen after and around filters used for logging.
Around Filter
Around filters may have logic before and after the action being run. It simply yields to the action in whatever place
is necessary. Note that it doesn’t need to yield to the action and may run without doing so like a before filter.
Around filters are responsible for running their associated actions by yielding, similar to how Rack middlewares
work.
around_filter :catch_exceptions
private
def catch_exceptions
begin
yield
rescue Exception => e
logger.debug "Caught exception! #{e.message}"
end
end
This will catch exception of any action and put the message in your log. You can use around filters for exception
handling, setup and teardown, and a myriad of other cases.
All filters can be applied to specific actions, using :only and :except:
def set_product
@product = Product.find(params[:id])
end
end
Skipping Filter
All filters (inherited ones too) can also be skipped for some specific actions:
def authenticate_user!
redirect_to some_path unless user_signed_in?
end
end
def index
end
end
# config/routes.rb
namespace :admin do
resources :products
end
# app/controllers/admin_controller.rb
class AdminController < ApplicationController
before_action :authenticate_admin_user!
private
def authenticate_admin_user!
redirect_to root_path unless current_user.admin?
end
end
# app/controllers/admin/products_controller.rb
class Admin::ProductsController < AdminController
# This controller will inherit :authenticate_admin_user! filter
end
Beware that in Rails 4.x you could use before_filter along with before_action, but before_filter is currently
deprecated in Rails 5.0.0 and will be removed in 5.1.
You can generate a new controller by running this command in your app folder
Note: You can also use rails g alias to invoke rails generate
For example, to generate a controller for a Product model, with #index and #show actions you would run
This will create the controller in app/controllers/products_controller.rb, with both the actions you specified
def show
end
end
It will also create a products folder inside app/views/, containing the two templates for your controller's actions
(i.e. index.html.erb and show.html.erb, note that the extension may vary according to your template engine, so if
you're using slim, for example, generator will create index.html.slim and show.html.slim )
Furthermore, if you specified any actions they will also be added to your routes file
Rails creates a helper file for you, in app/helpers/products_helper.rb, and also the assets files in
app/assets/javascripts/products.js and app/assets/stylesheets/products.css. As for views, the generator
changes this behaviour according to what's specified in your Gemfile: i.e., if you're using Coffeescript and Sass in
your application, the controller generator will instead generator products.coffee and products.sass.
At last, but not least, Rails also generates test files for your controller, your helper and your views.
If you don't want any of these to be created for you can tell Rails to skip them, just prepend any option with
--no-
If you need to create a controller for a specific namespace add it in front of NAME:
Open the file app/controllers/application_controller.rb and you should find something like this:
It's recommended not to rescue from Exception or StandardError otherwise Rails won't be able to display helpful
pages in case of errors.
If you visit /users or /users.html, it will show an html page with the content Hello World
If you visit /users.json, it will display a JSON object containing:
You can omit format.html { render inline: "Hello World" } if you want to make sure that your route will
answer only to JSON requests.
This is a basic controller, with the addition of the following route (in routes.rb):
Will display the Hello World message in a webpage when you access the URL /users
Access the URL /users?name=john and the output will be Hello John, access /users?name=whatever and the
output will be Hello someone
You can allow (or reject) some params so that only what you want will pass through and you won't have bad
surprises like user setting options not meant to be changed.
You can go back to the previous page the user visited using:
redirect_to :back
Which will try to redirect to the previous page and in case not possible (the browser is blocking the HTTP_REFERRER
header), it will redirect to :fallback_location
class UsersController < ApplicationController def index respond_to do |format| format.html { render } end end end
render "pages/home"
class UsersController < ApplicationController def index @name = "john" respond_to do |format| format.html {
render } end end end
An important note around the render syntax, you can omit the render syntax entirely, Rails assumes that if you
omit it. So:
class UsersController < ApplicationController def index respond_to do |format| format.html { render } end end end
class UsersController < ApplicationController def index respond_to do |format| format.html end end end
Rails is smart enough to figure out that it must render the file app/views/users/index.html.erb.
config.after_initialize: Takes a block which will be run after rails has initialized the application.
config.asset_host: This sets the host for the assets. This is useful when using a Content Delivery Network. This
is shorthand for config.action_controller.asset_host
config.autoload_once_paths: This option accepts an array of paths where Rails autoloads constants. The
default value is an empty array
config.autoload_paths: This accepts an array of paths where Rails autoloads constants. It defaults to all
directories under app
config.cache_classes: Determines if classes and modules should be reloaded on each request. In
development mode, this defaults to false and in the production and test modes it defaults to true
config.action_view.cache_template_loading: This determines if templates should be reloaded on each
request. It defaults to the config.cache_classes setting
config.beginning_of_week: This sets the default beginning of week. It requires a valid week day symbol
(:monday)
config.cache_store: Choose which cache store to use. Options include :file_store, :memory_store,
mem_cache_store or null_store.
config.colorize_logging: This controls whether logging information is colorized
config.eager_load: Eager-loads all registered
config.encoding: Specifies the application encoding. The default value is UTF-8
config.log_level: Sets the verbosity of the Rails Logger. It defaults to :debug in all environments.
config.middleware: Use this to configure the application's middleware
config.time_zone: This sets the application's default time zone.
config.assets.enabled: Determines whether the asset pipeline is enabled. This defaults to true
config.assets.raise_runtime_errors: This enables runtime error checking. It's useful for development mode
config.assets.compress: Lets assets be compressed. In production mode, this defaults to true
config.assets.js_compressor: Specifies which JS compressor to use. Options include :closure, :uglifier
and :yui
config.assets.paths: Specifies which paths to search for assets.
config.assets.precompile: Lets you choose additional assets to be precompiled when rake
assets:precompile is run
config.assets.digest: This option allows the use of MD-5 fingerprints in the asset names. It defaults to true in
development mode
config.assets.compile: Toggles live Sprockets compilation in production mode
config.generators do |g|
g.orm :active_record
Rails also has a configuration file in config/application.rb. This is a common configuration file as any settings
defined here are overwritten by the config specified in each environment.
You add or modify configuration options within the Rails.application.configure do block and configuration
options start with config.
development:
<<: *default
database: db/development.sqlite3
production:
If you want to change the default database while creating a new project you can specify database: rails new
hello_world --database=mysql
my_string = "Array"
# => 'Array'
my_constant = my_string.safe_constantize
# => Array
my_constant.new(4)
# => [nil, nil, nil, nil]
my_string = "not_a_constant"
# => 'not_a_constant'
my_string.safe_constantize
# => nil
Assuming you already have RVM installed, to get the latest version of ruby, which is needed for these examples,
open a terminal and run:
$ ruby -v
> ruby 2.3.0p0
To install Rails 5, first create a new gemset using the latest ruby version and then install rails:
$ rails -v
> Rails 5.0.0
create
create README.rdoc
create Rakefile
create config.ru
create .gitignore
create Gemfile
create app
create app/assets/javascripts/application.js
create app/assets/stylesheets/application.css
create app/controllers/application_controller.rb
create app/helpers/application_helper.rb
create app/views/layouts/application.html.erb
create app/assets/images/.keep
create app/mailers/.keep
create app/models/.keep
create app/controllers/concerns/.keep
create app/models/concerns/.keep
create bin
create bin/bundle
create bin/rails
create bin/rake
This file structure will be created inside a new folder called app_name. It contains all the assets and code needed to
start your project.
cd app_name
bundle install
You should also start your database. Rails uses SQLite as a default database. To create it, run:
rake db:setup
$ rails server
When you open your browser at http://localhost:3000, your shiny new (empty) API should be running!
Permissions are defined in the Ability class and can be used from controllers, views, helpers, or any other place in
the code.
To add authorization support to an app, add the CanCanCan gem to the Gemfile:
gem 'cancancan'
# app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
end
end
Then check authorization using load_and_authorize_resource to load authorized models into the controller:
def show
# @article is already loaded and authorized
end
end
def show
@article = Article.find(params[:id])
authorize! :read, @article
end
can? to check if an object is authorized against a particular action anywhere in the controllers, views, or helpers
Note: This assumes the signed user is provided by the current_user method.
The first strategy to handle these issue is to move abilities into meaningful methods, as per this example:
class Ability
include CanCan::Ability
def initialize(user)
anyone_abilities
if user
if user.admin?
admin_abilities
else
authenticated_abilities
end
else
guest_abilities
end
end
private
def anyone_abilities
# define abilities for everyone, both logged users and visitors
end
def guest_abilities
# define abilities for visitors only
end
def authenticated_abilities
# define abilities for logged users only
end
def admin_abilities
# define abilities for admins only
end
end
Once this class grow large enough, you can try breaking it into different classes to handle the different
responsibilities like this:
# app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
self.merge Abilities::Everyone.new(user)
if user
if user.admin?
self.merge Abilities::Admin.new(user)
else
self.merge Abilities::Authenticated.new(user)
end
else
self.merge Abilities::Guest.new(user)
end
end
# app/models/abilities/guest.rb
module Abilities
class Guest
include CanCan::Ability
def initialize(user)
# Abilities for anonymous visitors only
end
end
end
class Ability
include CanCan::Ability
def initialize(user)
# for any visitor or user
can :read, Article
if user
if user.admin?
# admins can do any action on any model or action
can :manage, :all
else
# regular users can read all content
can :read, :all
# and edit, update and destroy their own user only
can [:edit, :destroy], User, id: user_id
# but cannot read hidden articles
cannot :read, Article, hidden: true
end
else
# only unlogged visitors can visit a sign_up page:
can :read, :sign_up
end
end
end
test_ability = Ability.new(User.first)
test_ability.can?(:show, Post) #=> true
other_ability = Ability.new(RestrictedUser.first)
other_ability.cannot?(:show, Post) #=> true
Array
BigDecimal
Boolean
Date
DateTime
Float
Hash
Integer
BSON::ObjectId
BSON::Binary
Range
Regexp
String
Symbol
Time
TimeWithZone
To add a field (let's call it name and have it be a String), add this to your model file:
$ rails g mongoid:config
class User
include Mongoid::Document
end
This is all you need to have a model (albeit nothing but an id field). Unlike ActiveRecord, there is no migration files.
All the database information for the model is contained in the model file.
Timestamps are not automatically included in your model when you generate it. To add created_at and
updated_at to your model, add
include Mongoid::Timestamps
class User
include Mongoid::Document
include Mongoid::Timestamps
end
To add an association (lets say the User has_many posts), you can add this to your User model file:
has_many :posts
belongs_to :user
This will add a user_id field in your Post model, add a user method to your Post class, and add a posts method to
your User class.
To add an association (lets say the User embeds_many addresses), add this to your User file:
embeds_many :addresses
embedded_in :user
This will embed Address in your User model, adding a addresses method to your User class.
User.where(name: "Bob").entries #Returns all objects with name "Bob" from database
User.where(:name.in => ['Bob', 'Alice']).entries #Returns all objects with name "Bob" or "Alice"
from database
User.any_in(name: ["Bob", "Joe"]).first #Returns the first object with name "Bob" or "Joe"
User.where(:name => 'Bob').exists? # will return true if there is one or more users with name bob
Generate a Gemfile with the default rubygems.org source by running bundle init. Use https so your connection to
the server will be verified with SSL.
source 'https://rubygems.org'
Next, declare the gems that you need, including version numbers.
Most of the version specifiers, like >= 1.0, are self-explanatory. The specifier ~> has a special meaning. ~> 2.0.3 is
identical to >= 2.0.3 and < 2.1. ~> 2.1 is identical to >= 2.1 and < 3.0. ~> 2.2.beta will match prerelease versions like
2.2.beta.12.
Git repositories are also valid gem sources, as long as the repo contains one or more valid gems. Specify what to
check out with :tag, :branch, or :ref. The default is the master branch.
If you would like to use an unpacked gem directly from the filesystem, simply set the :path option to the path
containing the gem's files.
Dependencies can be placed into groups. Groups can be ignored at install-time (using --without) or required all at
once (using Bundler.require).
You can specify the required version of Ruby in the Gemfile with ruby. If the Gemfile is loaded on a different Ruby
version, Bundler will raise an exception with an explanation.
ruby '2.3.1'
To be exact even rails is nothing more than a gem. A lot of gems are built on rails or other gems (they are
dependent of said gem) or are standalone.
For your Rails project you have a file called Gemfile. In here you can add gems you want to include and use in your
project. Once added you need to install the gem by using bundler (See Bundler section).
Gemfile.lock
Once you have done this, your Gemfile.lock will be updated with your newly added gems and their dependencies.
This file locks your used gems so they use that specific version declared in that file.
GEM
remote: https://rubygems.org/
specs:
devise (4.0.3)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0, < 5.1)
responders
warden (~> 1.2.3)
This example is for the gem devise. In the Gemfile.lock the version 4.0.3 is declared, to tell when installing your
project on an other machine or on your production server which specified version to use.
Development
Either a single person, a group or a whole community works on and maintains a gem. Work done is usually released
after certain issues have been fixed or features have been added.
After you have bundler up and running all you need to do is add gems to your Gemfile and run
bundle
in your terminal. This installs your newly added gems to your project. Should an issue arise, you would get a
prompt in your terminal.
If you are interested in more details, I suggest you have a look at the docs.
Creating gemsets
Suppose you already have ruby-2.3.1 installed and you have selected it using this command:
where the new_gemset is the name of gemset. To see the list of available gemsets for a ruby version:
to use a gemset from the list (suppose new_gemset is the gemset I want to use):
you can also specify the ruby version with the gemset if you want to shift to some other ruby version:
to remove all the installed gems from a gemset you can empty it by:
to delete a gemset:
When you install a new ruby, RVM not only creates two gemsets (the default, empty gemset and the global gemset),
it also uses a set of user-editable files to determine which gems to install.
Working in ~/.rvm/gemsets, rvm searchs for global.gems and default.gems using a tree-hierachy based on the
ruby string being installed. Using the example of ree-1.8.7-p2010.02, rvm will check (and import from) the
following files:
~/.rvm/gemsets/ree/1.8.7/p2010.02/global.gems
~/.rvm/gemsets/ree/1.8.7/p2010.02/default.gems
~/.rvm/gemsets/ree/1.8.7/global.gems
~/.rvm/gemsets/ree/1.8.7/default.gems
~/.rvm/gemsets/ree/global.gems
~/.rvm/gemsets/ree/default.gems
~/.rvm/gemsets/global.gems
~/.rvm/gemsets/default.gems
bundler
awesome_print
every time you install a new ruby, these two gems are installed into your global gemset. default.gems and
global.gems files are usually overwritten during update of rvm.
In this example the application.coffee and application.scss are so called 'Manifest Files'. This files should be
used to include other JavaScript or CSS assets. The following command are available:
require <path>: The require directive functions similar to Ruby's own require. It provides a way to declare
a dependency on a file in your path and ensures it's only loaded once before the source file.
require_directory <path>: requires all the files inside a single directory. It's similar to path/* since it does
not follow nested directories.
require_tree <path>: requires all the nested files in a directory. Its glob equivalent is path/**/*.
require_self: causes the body of the current file to be inserted before any subsequent require directives.
Useful in CSS files, where it's common for the index file to contain global styles that need to be defined
before other dependencies are loaded.
stub <path>: remove a file from being included
depend_on <path>: Allows you to state a dependency on a file without including it. This is used for caching
purposes. Any changes made to the dependency file will invalidate the cache of the source file.
/*
*= require bootstrap
*= require_directory .
*= require_self
*/
Another example is the application.coffee file. Here with including jquery and Turbolinks:
#= require jquery2
#= require jquery_ujs
#= require turbolinks
#= require_tree .
If you don't use CoffeeScript, but plain JavaScript, the syntax would be:
1. When running a server in development mode, it automatically pre-processes and prepares your assets on-
the-fly.
2. In production mode, you’ll probably use it to pre-process, versionize, and compress and compile your assets.
You can do so by running the following command:
To upgrade from Rails 4.2 to Rails 5.0, you must be using Ruby 2.2.2 or newer. After upgrading your Ruby version if
required, go to your Gemfile and change the line:
to:
$ bundle update
$ rake rails:update
This will help you to update configuration files. You will be prompted to overwrite files and you have several options
to input:
Y – yes, overwrite
n – no, do not overwrite
a – all, overwrite this and all others
q – quit, abort
d – diff, show the differences between the old and the new
h – help
Typically, you should check the differences between the old and new files to make sure you aren't getting any
unwanted changes.
Rails 5.0 ActiveRecord models inherit from ApplicationRecord, rather than ActiveRecord::Base.
ApplicationRecord is the superclass for all models, similar to how ApplicationController is the superclass for
controllers. To account for this new way in which models are handled, you must create a file in your app/models/
folder called application_record.rb and then edit that file's contents to be:
Rails 5.0 also handles callbacks slightly different. Callbacks that return false won't halt the callback chain, which
means subsequent callbacks will still run, unlike Rails 4.2. When you upgrade, the Rails 4.2 behavior will remain,
though you can switch to the Rails 5.0 behavior by adding:
ActiveSupport.halt_callback_chains_on_return_false = false
to the config/application.rb file. You can explicitly halt the callback chain by calling throw(:abort).
Then, you must change all of your jobs to inherit from ApplicationJob rather than ActiveJob::Base.
One of the other biggest changes of Rails 5.0 doesn't require any code changes, but will change the way you use the
command line with your Rails apps. You will be able to use bin/rails, or just rails, to run tasks and tests. For
example, instead of using $ rake db:migrate, you can now do $ rails db:migrate. If you run $ bin/rails, you
can view all the available commands. Note that many of the tasks that can now be run with bin/rails still work
using rake.
user_one.name = "John"
user_one.save
# Run at the same instance
user_two.name = "Doe"
user_two.save # Raises a ActiveRecord::StaleObjectError
If you want to debug .html.erb files, break point will be added as <% debugger %>
The fastest way to debug Ruby (especially Rails) code is to raise an exception along the execution path of your code
while calling .inspect on the method or object (e.g. foo):
raise foo.inspect
In the above code, raise triggers an Exception that halts execution of your code, and returns an error message that
conveniently contains .inspect information about the object/method (i.e. foo) on the line that you're trying to
debug.
This technique is useful for quickly examining an object or method (e.g. is it nil?) and for immediately confirming
whether a line of code is even getting executed at all within a given context.
Only after you have information about the state of your codes execution flow should you consider moving to a ruby
gem irb debugger like pry or byebug where you can delve more deeply into the state of objects within your
execution path.
This byebug variable when executed will open up an ruby IRB session of your code, giving you direct access to the
state of objects as they are at that point in the code's execution.
IRB debuggers like Byebug are useful for deeply analyzing the state of your code as it executes. However, they are
more time consuming procedure compared to raising errors, so in most situations they should not be your first
step.
When you are trying to debug a problem, good advice is to always: Read The !@#$ing Error Message (RTFM)
That means reading error messages carefully and completely before acting so that you understand what it's trying to
tell you. When you debug, ask the following mental questions, in this order, when reading an error message:
1. What class does the error reference? (i.e. do I have the correct object class or is my object nil?)
2. What method does the error reference? (i.e. is their a type in the method; can I call this method on this type/class
of object?)
3. Finally, using what I can infer from my last two questions, what lines of code should I investigate? (remember:
the last line of code in the stack trace is not necessarily where the problem lies.)
In the stack trace pay particular attention to lines of code that come from your project (e.g. lines starting with
app/... if you are using Rails). 99% of the time the problem is with your own code.
@foo = Foo.new
...
@foo.bar
Beginners see this error and think the problem is that the method bar is undefined. It's not. In this error the real
part that matters is:
for Nil:nilClass
for Nil:nilClass means that @foo is Nil! @foo is not a Foo instance variable! You have an object that is Nil. When
you see this error, it's simply ruby trying to tell you that the method bar doesn't exist for objects of the class Nil.
(well duh! since we are trying to use a method for an object of the class Foo not Nil).
Unfortunately, due to how this error is written (undefined method "bar" for Nil:nilClass) its easy to get tricked
into thinking this error has to do with bar being undefined. When not read carefully this error causes beginners to
mistakenly go digging into the details of the bar method on Foo, entirely missing the part of the error that hints that
the object is of the wrong class (in this case: nil). It's a mistake that's easily avoided by reading error messages in
their entirety.
Always carefully read the entire error message before beginning any debugging. That means: Always check the
class type of an object in an error message first, then its methods, before you begin sleuthing into any stacktrace or
line of code where you think the error may be occurring. Those 5 seconds can save you 5 hours of frustration.
tl;dr: Don't squint at print logs: raise exceptions instead. Avoid rabbit holes by reading errors carefully before
debugging.
Setup
Navigate to the application's root directory on terminal console and run bundle install. You're all set to
start using it anywhere on your application.
Use
Using pry in your application is just including binding.pry on the breakpoints you want to inspect while debugging.
You can add binding.pry breakpoints anywhere in your application that is interpreted by ruby interpreter (any
app/controllers, app/models, app/views files)
i) Debugging a Controller
app/controllers/users_controller.rb
In this example, the rails server pauses with a pry console at the break-point when you try to visit a page routing to
show action on UsersController. You can inspect params object and make ActiveRecord query on User model from
that breakpoint
app/views/users/show.html.haml
In this example, the break-point pauses with pry console when the users/show page is pre-compiled in the rails
server before sending it back to the client's browser. This break-point allows to debug correctness of
@user.logged_in? when it is misbehaving.
app/models/user.rb
In this example, the break-point can be used to debug User model's instance method full_name when this method
is called from anywhere in the application.
In conclusion, pry is a powerful debugging tool for rails application with easy setup and straightforward debugging
guideline. Give this a try.
For example, take a look at one of the best Ruby IDE's, RubyMine's debugging features on the picture
gem 'turbolinks'
In order to get Angular to work with the Rails asset pipeline we need to add to the Gemfile:
gem 'angular-rails-templates'
gem 'bower-rails'
bundle install
{
"name": "bower-rails generated dependencies",
"dependencies": {
"angular": "latest",
"angular-resource": "latest",
"bourbon": "latest",
"angular-bootstrap": "latest",
"angular-ui-router": "latest"
}
}
Now that bower.json is setup with the right dependencies, let’s install them:
templates/
In app/assets/javascripts/application.js, add require for Angular, the template helper, and the Angular app
file structure. Like this:
Create app/assets/javascripts/angular-app/app.js.coffee:
In app/controllers/example_controller.rb:
In the view, we need to specify which Angular app and which Angular controller will drive this page. So in
app/views/example/index.html.erb:
</div>
To view the app, start your Rails server and visit http://localhost:3000/example.
You can easily rotating rails production logs with LogRotate.You just have to do small configuration as below
Open /etc/logrotate.conf with your favourite linux editor vim or nano and add the below code in this file at
bottom.
/YOUR/RAILSAPP/PATH/log/*.log {
daily
missingok
rotate 7
compress
delaycompress
notifempty
copytruncate
}
So, How It Works This is fantastically easy. Each bit of the configuration does the following:
daily – Rotate the log files each day. You can also use weekly or monthly here instead.
missingok – If the log file doesn’t exist,ignore it
rotate 7 – Only keep 7 days of logs around
compress – GZip the log file on rotation
delaycompress – Rotate the file one day, then compress it the next day so we can be sure that it won’t
interfere with the Rails server
notifempty – Don’t rotate the file if the logs are empty
copytruncate – Copy the log file and then empties it. This makes sure that the log file Rails is writing to
always exists so you won’t get problems because the file does not actually change. If you don’t use this, you
would need to restart your Rails application each time.
Running Logrotate Since we just wrote this configuration, you want to test it.
That's it.
def index
@funds = Fund.all_funds(current_user)
end
def show
@fund = Fund.find(params[:id])
respond_to do |format|
format.html
format.pdf do
pdf = FundsPdf.new(@fund, view_context)
send_data pdf.render, filename:
"fund_#{@fund.created_at.strftime("%d/%m/%Y")}.pdf",
type: "application/pdf"
end
end
end
end
I above code we have this line FundsPdf.new(@fund, view_context). Here we are initializing FundsPdf class with
@fund instance and view_context to use helper methods in FundsPdf. FundsPdf wuld look like this
def upper_half
logopath = "#{Rails.root}/app/assets/images/logo.png"
image logopath, :width => 197, :height => 91
move_down 10
draw_text "Receipt", :at => [220, 575], size: 22
move_down 80
text "Hello #{@invoice.customer.profile.first_name.capitalize},"
end
def thanks_message
move_down 15
text "Thank you for your order.Print this receipt as
confirmation of your order.",
:indent_paragraphs => 40, :size => 13
end
end
This is one of the best approach to generate PDF with classes using Prawn gem.
After that we can generate Pdf with Prawn in following basic ways
What --api does is to remove functionality that is not needed when building an API. This includes sessions, cookies,
assets, and anything that makes Rails work on a browser.
It will also configure the generators so that they don't generate views, helpers, and assets when generating a new
resource.
When you compare the ApplicationController on a web app versus an API app, you will see that the web version
extends from ActionController::Base, whereas the API version extends from ActionController::API, which
includes a much smaller subset of functionality.
The first URL of the output, http://example.herokuapp.com, is the location the app is available at. The second URL,
[email protected]:example.git, is the remote git repository URL.
This command should only be used on an initialized git repository. The heroku create command automatically adds
a git remote named “heroku” pointing at this URL.
The app name argument (“example”) is optional. If no app name is specified, a random name will be generated.
Since Heroku app names are in a global namespace, you can expect that common names, like “blog” or “wiki”, will
already be taken. It’s often easier to start with a default name and rename the app later.
If you are using the database in your application you need to manually migrate the database by running:
Any commands after heroku run will be executed on a Heroku dyno. You can obtain an interactive shell session by
running:
Ensure you have one dyno running the web process type:
$ heroku ps
=== web (Standard-1X): bin/rails server -p $PORT -e $RAILS_ENV (1)
web.1: starting 2016/07/08 12:09:06 -0500 (~ 2s ago)
You can now visit the app in our browser with heroku open.
$ heroku open
Heroku gives you a default web URL in the herokuapp.com domain. When you are ready to scale up for production,
you can add your own custom domain.
The solution is to have a staging environment that is as similar to production as is possible. This can be achieved by
creating a second Heroku application that hosts your staging application. With staging, you can check your code in a
Assume you have an application running on your local machine, and you’re ready to push it to Heroku. We’ll need
to create both remote environments, staging and production. To get in the habit of pushing to staging first, we’ll
start with this:
By default, the heroku CLI creates projects with a heroku git remote. Here, we’re specifying a different name with
the --remote flag, so pushing code to Heroku and running commands against the app look a little different than the
normal git push heroku master:
Once your staging app is up and running properly, you can create your production app:
And with that, you’ve got the same codebase running as two separate Heroku apps – one staging and one
production, set up identically. Just remember you will have to specify which app you are going to operate on your
daily work. You can either use flag '--remote' or use your git config to specify a default app.
str = "hello" str.at(0) # => "h" str.at(1..3) # => "ell" str.at(-2) # => "l" str.at(-2..-1) # => "lo" str.at(5) # => nil str.at(5..-1)
# => "" String#from
Returns a substring from the given position to the end of the string.
str = "hello" str.from(0) # => "hello" str.from(3) # => "lo" str.from(-2) # => "lo" String#to
Returns a substring from the beginning of the string to the given position.
If the position is negative, it is counted from the end of the string.
str = "hello" str.to(0) # => "h" str.to(3) # => "hell" str.to(-2) # => "hell"
Returns the first character, or a given number of characters up to the length of the string.
str = "hello" str.first # => "h" str.first(1) # => "h" str.first(2) # => "he" str.first(0) # => "" str.first(6) # => "hello"
String#last
Returns the last character, or a given number of characters from the end of the string counting backwards.
str = "hello" str.last # => "o" str.last(1) # => "o" str.last(2) # => "lo" str.last(0) # => "" str.last(6) # => "hello"
Converts a string to a Time value. The form parameter can be either :utc or :local, defaults to :local.
"13-12-2012".to_time # => 2012-12-13 00:00:00 +0100 "06:12".to_time # => 2012-12-13 06:12:00 +0100 "2012-12-13
06:12".to_time # => 2012-12-13 06:12:00 +0100 "2012-12-13T06:12".to_time # => 2012-12-13 06:12:00 +0100
"2012-12-13T06:12".to_time(:utc) # => 2012-12-13 06:12:00 UTC "12/13/2012".to_time # => ArgumentError:
argument out of range String#to_date
"1-1-2012".to_date # => Sun, 01 Jan 2012 "01/01/2012".to_date # => Sun, 01 Jan 2012 "2012-12-13".to_date # =>
Thu, 13 Dec 2012 "12/13/2012".to_date # => ArgumentError: invalid date String#to_datetime
"1-1-2012".to_datetime # => Sun, 01 Jan 2012 00:00:00 +0000 "01/01/2012 23:59:59".to_datetime # => Sun, 01 Jan
2012 23:59:59 +0000 "2012-12-13 12:50".to_datetime # => Thu, 13 Dec 2012 12:50:00 +0000
"12/13/2012".to_datetime # => ArgumentError: invalid date
"hello".exclude? "lo" # => false "hello".exclude? "ol" # => true "hello".exclude? ?h # => false
Returns a version of the given string without leading or trailing whitespace, and combines all consecutive
whitespace in the interior to single spaces. Destructive version squish! operates directly on the string instance.
%{ Multi-line string }.squish # => "Multi-line string" " foo bar \n \t boo".squish # => "foo bar boo" String#remove
Returns a new string with all occurrences of the patterns removed. Destructive version remove! operates directly on
the given string.
str = "foo bar test" str.remove(" test") # => "foo bar" str.remove(" test", /bar/) # => "foo " String#truncate
Returns a copy of a given string truncated at a given length if the string is longer than the length.
'Once upon a time in a world far far away'.truncate(27) # => "Once upon a time in a wo..."
'Once upon a time in a world far far away'.truncate(27, separator: ' ') # => "Once upon a time in a..." 'Once upon a
time in a world far far away'.truncate(27, separator: /\s/) # => "Once upon a time in a..." String#truncate_words
'Once upon a time in a world far far away'.truncate_words(4) # => "Once upon a time..."
The last characters will be replaced with the :omission string (defaults to "...")
'And they found that many people were sleeping better.'.truncate_words(5, omission: '... (continued)') # => "And
they found that many... (continued)" String#strip_heredoc
Strips indentation in heredocs. Looks for the least-indented non-empty line and removes that amount of leading
whitespace.
if options[:usage] puts <<-USAGE.strip_heredoc This command does such and such. Supported options are: -h This
message ... USAGE end
Returns of plural form of the string. Optionally takes a count parameter and returns singular form if count == 1.
Also accepts a locale parameter for language-specific pluralization.
String#singularize
Returns the singular form of the string. Accepts an optional locale parameter.
String#constantize
Tries to find a declared constant with the name specified in the string. It raises a NameError when the name is not in
CamelCase or is not initialized.
String#safe_constantize
String#camelize
Converts strings to UpperCamelCase by default, if :lower is given as param converts to lowerCamelCase instead.
alias: camelcase
Note: will also convert / to :: which is useful for converting paths to namespaces.
String#titleize
Capitalizes all the words and replaces some characters in the string to create a nicer looking title.
alias: titlecase
String#underscore
Makes an underscored, lowercase form from the expression in the string. The reverse of camelize.
String#dasherize
String#demodulize
Removes the module part from the constant expression in the string.
String#deconstantize
Removes the rightmost segment from the constant expression in the string.
String#parameterize
Replaces special characters in a string so that it may be used as part of a 'pretty' URL.
Preserve the case of the characters in a string with the :preserve_case argument.
A very common use-case for parameterize is to override the to_param method of an ActiveRecord model to
support more descriptive url slugs.
String#tableize
Creates the name of a table like Rails does for models to table names. Pluralizes the last word in the string.
String#classify
Returns a class name string from a plural table name like Rails does for table names to models.
String#humanize
Capitalizes the first word, turns underscores into spaces, and strips a trailing _id if present.
String#upcase_first
String#foreign_key
Creates a foreign key name from a class name. Pass false param to disable adding _ between name and id.
form_tag: This is the default helper for creating a form. It's first parameter, /search is the action and the
second parameter specifies the HTTP method. For search forms, it is important to always use the method get
label_tag: This helper creates an html <label> tag.
text_field_tag: This will create an input element with type text
submit_tag: This creates an input element with type submit
The last argument are options, which accepts the following: { multiple: false, disabled: false, include_blank: false,
prompt: false }
Radio Buttons
<%= radio_button_tag(:age, "child") %>
<%= label_tag(:age_child, "I am younger than 18") %>
<%= radio_button_tag(:age, "adult") %>
<%= label_tag(:age_adult, "I'm over 18") %>
Text Area
Number Field
Password Field
Sometimes you want the characters typed by the user to be masked. This will generate an <input
type="password">
Email Field
Telephone Field
Date Helpers
input[type="date"]
input[type="week"]
input[type="year"]
input[type="time"]
ActiveRecord::Base.transaction do
david.withdrawal(100)
mary.deposit(100)
end
This example will only take money from David and give it to Mary if neither withdrawal nor deposit raise an
exception. Exceptions will force a ROLLBACK that returns the database to the state before the transaction began.
Be aware, though, that the objects will not have their instance data returned to their pre-transactional state.
In this example a balance record is transactionally saved even though transaction is called on the Account class:
Account.transaction do
balance.save!
account.save!
end
The transaction method is also available as a model instance method. For example, you can also do this:
balance.transaction do
balance.save!
account.save!
end
Student.transaction do
Course.transaction do
course.enroll(student)
student.units += course.units
end
end
This is a poor solution, but fully distributed transactions are beyond the scope of ActiveRecord.
As a consequence changes to the database are not seen outside your connection until the operation is complete.
For example, if you try to update the index of a search engine in after_save the indexer won't see the updated
record. The after_commit callback is the only one that is triggered once the update is committed.
after_commit callbacks are called on every record saved or destroyed within a transaction immediately after the
transaction is committed. after_rollback callbacks are called on every record saved or destroyed within a
transaction immediately after the transaction or savepoint is rolled back.
These callbacks are useful for interacting with other systems since you will be guaranteed that the callback is only
executed when the database is in a permanent state. For example, after_commit is a good spot to put in a hook to
clearing a cache since clearing it from within a transaction could trigger the cache to be regenerated before the
database is updated.
Add rspec-rails to both the :development and :test groups in the Gemfile:
Initialize it with:
This will create a spec/ folder for your tests, along with the following configuration files:
All these files are written with sensible defaults to get you started, but you can add features and change
configurations to suit your needs as your test suite grows.
# app/decorators/user_decorator.rb
class UserDecorator < Draper::Decorator
def full_name
"#{object.first_name} #{object.last_name}"
end
def created_at
Time.use_zone(h.current_user.timezone) do
object.created_at.strftime("%A, %d %b %Y %l:%M %p")
end
end
end
Given a @user variable containing an ActiveRecord object, you can access your decorator by calling #decorate on
the @user, or by specifying the Draper class if you want to be specific.
For models with a lot of data, this can quickly become cumbersome and lead to copy-pasting logic from one
template to another.
All requests to a SimpleDelegator object are passed to the parent object by default. You can override any method
with presentation logic, or you can add new methods that are specific to this view.
SimpleDelegator provides two methods: __setobj__ to set what object is being delegated to, and __getobj__ to
get that object.
Some decorators rely on magic to wire-up this behavior, but you can make it more obvious where the presentation
logic is coming from by initializing the object on the page.
By passing a reference to the view object into the decorator, we can still access all of the rest of the view helpers
while building the presentation logic without having to include it.
Now the view template is only concerned with inserting data into the page, and it is much more clear.
gem 'searchkick'
Product.reindex
For testing it, the easiest way is with curl. It might take a few seconds for it to start, so don't panic if you don't get
any response at first.
curl localhost:9200
Example response:
{
"name" : "Hydro-Man",
"cluster_name" : "elasticsearch_gkbonetti",
"version" : {
"number" : "2.3.5",
"build_hash" : "90f439ff60a3c0f497f91663701e64ccd01edbb4",
"build_timestamp" : "2016-07-27T10:36:52Z",
"build_snapshot" : false,
"lucene_version" : "5.5.0"
},
"tagline" : "You Know, for Search"
}
If everything worked as expected you should be seeing a nice GUI where you can explore your data.
Elasticsearch - the official low level wrapper for the HTTP API
Elasticsearch-rails - the official high level Rails integration that helps you to connect your Rails models
with ElasticSearch using either ActiveRecord or Repository pattern
Chewy - An alternative, non-official high level Rails integration that is very popular and arguably has better
documentation
require 'elasticsearch'
client.transport.reload_connections!
client.cluster.health
client.search q: 'test'
gem 'react-rails'
And install:
bundle install
rails g react:install
This will:
create a components.js manifest file and a app/assets/javascripts/components/ directory, where you will put your
components place the following in your application.js:
You can pick which React.js build (development, production, with or without add-ons) to serve in each environment
by adding a config. Here are the defaults:
# config/environments/development.rb
MyApp::Application.configure do
config.react.variant = :development
end
# config/environments/production.rb
MyApp::Application.configure do
config.react.variant = :production
end
MyApp::Application.configure do
config.react.addons = true # defaults to false
end
After restarting your Rails server, //= require react will provide the build of React.js which was specified by the
configurations.
JSX
After installing react-rails, restart your server. Now, .js.jsx files will be transformed in the asset pipeline.
BabelTransformer options
You can use babel's transformers and custom plugins, and pass options to the babel transpiler adding following
configurations:
config.react.jsx_transform_options = {
blacklist: ['spec.functionName', 'validation.react', 'strict'], # default options
optional: ["transformerName"], # pass extra babel options
whitelist: ["useStrict"] # even more options[enter link description here][1]
}
The view helper puts a div on the page with the requested component class & props. For example:
On page load, the react_ujs driver will scan the page and mount components using data-react-class and data-react-
props.
If Turbolinks is present components are mounted on the page:change event, and unmounted on page:before-
unload. Turbolinks >= 2.4.0 is recommended because it exposes better events.
In case of Ajax calls, the UJS mounting can be triggered manually by calling from javascript:
component_class_name is a string which names a globally-accessible component class. It may have dots (eg,
"MyApp.Header.MenuItem").
html_options may include: tag: to use an element other than a div to embed data-react-class and data-react-
props. prerender: true to render the component on the server. **other Any other arguments (eg class:, id:) are
passed through to content_tag.
ActiveRecord::Base.connection.tables
ActiveRecord::Base.connection.drop_table("users")
------------OR----------------------
ActiveRecord::Migration.drop_table(:users)
------------OR---------------------
ActiveRecord::Base.connection.execute("drop table users")
where country is a column name in the migration file with already added index in users table as shown below:
ActiveRecord::Base.connection.remove_foreign_key('food_items', 'menus')
Add column
for example:
simple method-
So,the same method will now return boolean instead of anything else :).
EXAMPLE:
Suppose i need to find all user profiles(UserProfile) which are active which is not a user(User) with an
id=10.
UserProfiles.includes(:user=>:profile_pictures]).where(:active=>true).map(&:user).where.not(:id=>10
)
So above query will fail after map as map will return an array which will not work with where clause.
UserProfiles.includes(:user=>:profile_pictures]).where(:active=>true).joins(:user).where.not(:id=>1
0)
As joins will output similar records like map but they will be ActiveRecord and not an Array.
In the model you must declare the type of the field (Hash or Array)
In your model
class User < ActiveRecord::Base
serialize :preferences, Hash
serialize :tags, Array
end
Rake tasks
background jobs
console
tests
If I throw my logic into a controller it won’t be accessible from all these places. So let’s try “skinny controller, fat
model” approach and move the logic to a model. But which one? If a given piece of logic involves User, Cart and
Product models – where should it live?
A class which inherits from ActiveRecord::Base already has a lot of responsibilities. It handles query interface,
associations and validations. If you add even more code to your model it will quickly become an unmaintainable
mess with hundreds of public methods.
A service is just a regular Ruby object. Its class does not have to inherit from any specific class. Its name is a verb
phrase, for example CreateUserAccount rather than UserCreation or UserCreationService. It lives in app/services
directory. You have to create this directory by yourself, but Rails will autoload classes inside for you.
A service object (aka method object) performs one action. It holds the business logic to perform that action. Here is
an example:
# app/services/accept_invite.rb
class AcceptInvite
def self.call(invite, user)
invite.accept!(user)
UserMailer.invite_accepted(invite).deliver
end
end
Services go under the app/services directory. I encourage you to use subdirectories for business logic-heavy
domains. For instance:
Benefits
A quick look into a service object and I know what business logic is involved. I don’t have to go through the
controllers, ActiveRecord model callbacks and observers to understand what “approving a transaction” involves.
Controllers turn the request (params, session, cookies) into arguments, pass them down to the service and redirect
or render according to the service response.
This makes models and controllers much easier to test and maintain!
Reach for Service Objects when an action meets one or more of these criteria:
The action is complex (e.g. closing the books at the end of an accounting period)
The action reaches across multiple models (e.g. an e-commerce purchase using Order, CreditCard and
Customer objects)
The action interacts with an external service (e.g. posting to social networks)
The action is not a core concern of the underlying model (e.g. sweeping up outdated data after a certain time
period).
There are multiple ways of performing the action (e.g. authenticating with an access token or password).
Sources
before_save :update_slug
after_create :send_welcome_email
def publish!
update(published_at: Time.now, published: true)
end
def self.find_by_slug(slug)
find_by(slug: slug)
end
private
def update_slug
self.slug = title.join('-')
end
def send_welcome_email
WelcomeMailer.welcome(self).deliver_now
end
end
setting up relationships
validating data
providing access to data via scopes and methods
Performing actions around persistence of data.
At the highest level, models describe domain concepts and manages their persistence.
The shallow method of the DSL creates a scope inside of which every nesting is shallow. This generates the same
routes as the previous example:
shallow do
resources :articles do
resources :comments
resources :quotes
resources :drafts
end
end
There exist two options for scope to customize shallow routes. :shallow_path prefixes member paths with the
specified parameter:
rake routes
AASM is a finite state machine enabler library that can help you out with dealing with having an easy passing
through the process design of your objects.
Having something like this in your model goes pretty aligned with the Fat Model, Skinny Controller idea, one of Rails
best practices. The model is the sole responsible of managing its state, its changes and of generating the events
triggered by those changes.
To install, in Gemfile
gem 'aasm'
class Quote
include AASM
aasm do
state :requested, initial: true # User sees a product and requests a quote
state :priced # Seller sets the price
state :payed # Buyer pays the price
state :canceled # The buyer is not willing to pay the price
state :completed # The product has been delivered.
event :price do
transitions from: requested, to: :priced
end
event :pay do
transitions from: :priced, to: :payed, success: :set_payment_date
end
event :complete do
transitions from: :payed, to: :completed, guard: product_delivered?
end
event :cancel do
transitions from: [:requested, :priced], to: :canceled
transitions from: :payed, to: canceled, success: :reverse_charges
end
end
private
def set_payment_date
update payed_at: Time.zone.now
end
end
You can think of the states as being past, like in the previous example or algo in other tense, for example: pricing,
paying, delivering, etc. The naming of the states depends on you. From a personal point a view, past states work
better because your end state will surely be a past action and links up better with the event names, which will be
explained later.
NOTE: Be careful what names you use, you have to worry about not using Ruby or Ruby on Rails reserved
keywords, like valid, end, being, etc.
Having defined the states and transitions we can now access some methods created by AASM.
For example:
As you can see the event has transitions, this transitions determine the way the state will change upon the event
call. If the event is invalid due to the current state an Error will be raised.
The events and transitions also have some other callbacks, for example
guard: product_delivered?
Will call the product_delivered? method which will return a boolean. If it turns out false, the transition will not be
applied and if the no other transitions are available, the state won't change.
success: :reverse_charges
There are several other methods in AASM with more callbacks in the process but this will help you creating your
first models with finite states.
You can test this endpoint with curl by making a request like
describe '#find' do
subject { described_class.find(user, Time.zone.now.to_date) }
it { is_expected.to eq gift }
end
source
source
This kind of test focuses on user flows and runs through all layers of the system sometimes even rendering
javascript.
def perform(user)
# this will happen later
user.unsubscribe
end
end
config.frameworks
In ProjectsController:
In a nested form, you can create child objects with a parent object at the same time.
As we initialized @project with Project.new to have something for creating a new Project object, same way for
creating a Todo object, we have to have something like this, and there are multiple ways to do so:
2. You can also do this in view: <%= f.fields_for :todos, @project.todos.build %>
For strong params, you can include them in the following way:
def project_params
params.require(:project).permit(:name, todo_attributes: [:name])
end
Since, the Todo objects will be created through the creation of a Project object, so you have to specify this thing in
Project model by adding the following line:
accepts_nested_attributes_for :todos
FactoryGirl.define do
factory :user do # it will guess the User class
name "John"
email "[email protected]"
end
end
FactoryGirl.define do
factory :user_jack, class: User do
name "Jack"
email "[email protected]"
end
end
Then in your spec you can use the FactoryGirl's methods with these, like this:
# To create a non saved instance of the User class filled with John's data
build(:user)
# and to create a non saved instance of the User class filled with Jack's data
build(:user_jack)
Terminal Commands:
Controller Code:
Model:
routes.rb
resources :products
app/config/application.rb
require 'csv'
=> ProductsController.new.create #=> Uploads your whole CSV files from your folder directory
This one particularly blew my mind. The bullet gem helps you kill all the N+1 queries, as well as unnecessarily eager
loaded relations. Once you install it and start visiting various routes in development, alert boxes with warnings
indicating database queries that need to be optimized will pop out. It works right out of the box and is extremely
helpful for optimizing your application.
Static code analyzer for finding Rails specific code smells. It offers a variety of suggestions; use scope access, restrict
auto-generated routes, add database indexes, etc. Nevertheless, it contains lots of nice suggestions that will give
you a better perspective on how to re-factor your code and learn some best practices.
Rubocop
A Ruby static code analyzer which you can use to check if your code complies with the Ruby community code
guidelines. The gem reports style violations through the command line, with lots of useful code refactoring goodies
such as useless variable assignment, redundant use of Object#to_s in interpolation or even unused method
argument.
A good thing is that it's highly configurable, since the analyzer can be quite irritating if you're not following the Ruby
style guide 100% (i.e. you have lots of trailing whitespaces or you double quote your strings even when not
interpolating, etc.).
It's divided into 4 sub-analyzers (called cops): Style, Lint, Metrics and Rails.
def perform(*guests)
# Do something later
end
end
Engines are small Rails applications that can be used to add functionalities to the application hosting them. The
class defining a Ruby on Rails application is Rails::Application which actually inherits a lot of its behavior from
Rails::Engine, the class defining an engine. We can say that a regular Rails application is simply an engine with
more features.
# Getting started
We will also create an ‘engines’ folder to store the engines (even if we just have one!).
Engines, just like gems, come with a gemspec file. Let’s put some real values to avoid warnings.
#ModularTodo/engines/todo/todo.gemspec
$:.push File.expand_path("../lib", __FILE__)
#Moar stuff
#...
end
Now we need to add the Todo engine to the parent application Gemfile.
#ModularTodo/Gemfile
#Other gems
gem 'todo', path: 'engines/todo'
Great, our Todo engine is loaded correctly! Before we start coding, we have one last thing to do: mount the Todo
engine. We can do that in the routes.rb file in the parent app.
Rails.application.routes.draw do
mount Todo::Engine => "/", as: 'todo'
end
We are mounting it at / but we could also make it accessible at /todo. Since we have only one module, / is fine.
Now you can fire up your server and check it in your browser. You should see the default Rails view because we
didn’t define any controllers/views yet. Let’s do that now!
We are going to scaffold a model named Task inside the Todo module but to correctly migrate the database from
the parent application, we need to add a small initializer to the engine.rb file.
#ModularTodo/engines/todo/lib/todo/engine.rb
module Todo
class Engine < ::Rails::Engine
isolate_namespace Todo
end
end
That’s it, now when we run migrations from the parent application, the migrations in the Todo engine will be loaded
too.
Let’s create the Task model. The scaffold command needs to be run from the engine folder.
rake db:migrate
Now, we just need to define the root route inside the Todo engine:
#ModularTodo/engines/todo/config/routes.rb
Todo::Engine.routes.draw do
resources :tasks
root 'tasks#index'
end
// ModularTodo/engines/todo/app/assets/javascripts/todo/application.js
//= require jquery
//= require jquery_ujs
//= require_tree .
t.timestamps
end
end
end
When you do a Guest.create(name: 'Bob') ActiveRecord will translate this to create an entry in the Users table
with type: 'Guest'.
When you retrieve the record bob = User.where(name: 'Bob').first the object returned will be an instance of
Guest, which can be forcibly treated as a User with bob.becomes(User)
becomes is most useful when dealing with shared partials or routes/controllers of the superclass instead of the
subclass.
t.timestamps
end
end
end
When you do Admin.create, this record will be saved in the users table with entity_type = "Admin"
Section 61.3: Rails model with type column and without STI
Having type column in a Rails model without invoking STI can be achieved by assigning :_type_disabled to
inheritance_column:
User.transaction do
account.save!
profile.save!
print "All saves success, returning 1"
return 1
end
rescue_from ActiveRecord::RecordInvalid do |exception|
print "Exception thrown, transaction rolledback"
render_error "failure", exception.record.errors.full_messages.to_sentence
end
Using save with a bang ensures that transaction will be automatically rolled back when the exception is thrown and
after the rollback, control goes to the rescue block for the exception. Make sure you rescue the exceptions
thrown from the save! in Transaction Block.
If you don't want to use save!, you can manually raise raise ActiveRecord::Rollback when the save fails. You
need not handle this exception. It will then rollback the transaction and take the control to the next statement after
transaction block.
User.transaction do
if account.save && profile.save
print "All saves success, returning 1"
return 1
else
raise ActiveRecord::Rollback
end
end
print "Transaction Rolled Back"
$(document).ready(function() {
// awesome code
});
won't work. While using turbolinks, the $(document).ready() event will only fire once: on the initial page load.
From that point on, whenever a user clicks a link on your website, turbolinks will intercept the link click event and
make an ajax request to replace the <body> tag and to merge the <head> tags. The whole process triggers the
notion of a "visit" in turbolinks land. Therefore, instead of using the traditional document.ready() syntax above,
you'll have to bind to turbolink's visit event like so:
// pure js
document.addEventListener("turbolinks:load", function() {
// awesome code
});
// jQuery
$(document).on('turbolinks:load', function() {
// your code
});
Turbolinks can be disabled on a per-link basis by annotating a link or any of its ancestors with data-
turbolinks="false".
Examples:
// disables turbolinks for this one link
<a href="/" data-turbolinks="false">Disabled</a>
// disables turbolinks for all links nested within the div tag
<div data-turbolinks="false">
<a href="/">I'm disabled</a>
<a href="/">I'm also disabled</a>
</div>
Turbolinks.visit(location)
By default, the visit function uses the 'advance' action. More understandably, the default behavior for the visit
function is to advance to the page indicated by the "location" parameter. Whenever a page is visited, turbolinks
pushes a new entry onto the browser's history using history.pushState. The history is important because
turbolinks will try to use the history to load pages from cache whenever possible. This allows for extremely fast
page rendering for frequently visited pages.
However, if you want to visit a location without pushing any history onto the stack, you can use the 'replace' action
on the visit function like so:
// using links
<a href="/edit" data-turbolinks-action="replace">Edit</a>
// programmatically
Turbolinks.visit("/edit", { action: "replace" })
This will replace the top of the history stack with the new page so that the total number of items on the stack
remains unchanged.
There is also a "restore" action that aids in restoration vists, the visits that occur as a result of the user clicking the
forward button or back button on their browser. Turbolinks handles these types of events internally and
recommends that users don't manually tamper with the default behavior.
// pure javascript
event.data.url
or
// jQuery
$event.originalEvent.data.url
to retrieve the location of the visit. The visit can then be cancelled by calling:
event.preventDefault()
NOTE:
This is a relatively common problem and one that turbolinks has provided a solution for. The reason the problem
occurs is because turbolinks automatically loads pages from the cache when a user clicks the back button. The
cached page won't always be updated with the database.
To solve this issue, imagine that you render the friend count inside a <div> tag with an id of "friend-count":
By adding the data-turbolinks-permanent attribute, you're telling turbolinks to persist certain elements across
page loads. The official docs say:
Designate permanent elements by giving them an HTML id and annotating them with data-turbolinks-
permanent. Before each render, Turbolinks matches all permanent elements by id and transfers them
from the original page to the new page, preserving their data and event listeners.
http://example.com/states/washington
Gemfile
gem 'friendly_id', '~> 5.1.0' # Note: You MUST use 5.0.0 or greater for Rails 4.0+
rails generate friendly_id
rails generate scaffold user name:string slug:string:uniq
rake db:migrate
edit app/models/user.rb
class User < ApplicationRecord
extend FriendlyId
friendly_id :name, use: :slugged
end
rails server
GET http://localhost:3000/users/joe-schmoe
Finders are no longer overridden by default. If you want to do friendly finds, you must do
Model.friendly.find rather than Model.find. You can however restore FriendlyId 4-style finders by
using the :finders addon
A new "candidates" functionality which makes it easy to set up a list of alternate slugs that can be used to uniquely
distinguish records, rather than appending a sequence. For example:
def normalize_friendly_id(string)
super[0..40]
end
SECRET_NAME: secret_value
where SECRET_NAME and secret_value are the name and value of your API key.
You also need to name these secrets in config/secrets.yml. You can have different secrets in each environment. The
file should look like this:
development:
secret_name: <%= ENV["SECRET_NAME"] %>
test:
secret_name: <%= ENV["SECRET_NAME"] %>
production:
secret_name: <%= ENV["SECRET_NAME"] %>
How you use these keys varies, but say for example some_component in the development environment needs access
to secret_name. In config/environments/development.rb, you'd put:
Rails.application.configure do
config.some_component.configuration_hash = {
:secret => Rails.application.secrets.secret_name
}
end
Finally, let's say you want to spin up a production environment on Heroku. This command will upload the values in
config/environments/production.rb to Heroku:
you can find a file named 'Gemfile' at the root of rails project
Now on console you can find few instructions just follow it.
Authentication Token
Authentication token is used to authenticate a user with a unique token, So Before we proceed with the logic first
we need to add auth_token field to a Devise model
Hence,
In app/controllers/application_controllers.rb
this will help rails application respond with both html and json
Then
So, by default Devise uses email as unique field we can also use custom fields, for this case we will be
authenticating using user_email and auth_token.
before_filter do
user_email = params[:user_email].presence
user = user_email && User.find_by_email(user_email)
Note: Above code is purely based on your logic i am just trying to explain the working example
On line 6 in the above code you can see that i have set store: false which will prevent from creating a session on
each requests hence we achieved stateless re
Other approaches not covered here are using the react-rails or react_on_rails gems.
rails s
The specific environment can be selected by using the flag -e for example:
rails s -e test
The default environment can be changed in terminal by editing the ~/.bashrc file, and adding the following line:
<VirtualHost *:80>
ServerName application_name.rails.local
DocumentRoot "/Users/rails/application_name/public"
RailsEnv production ## This is the default
</VirtualHost>
Engines can be considered miniature applications that provide functionality to their host applications. A Rails
application is actually just a "supercharged" engine, with the Rails::Application class inheriting a lot of its behavior
from Rails::Engine.
Engines are the reusable rails applications/plugins. It works like a Gem. Famous engines are Device, Spree gems
which can be integrated with rails applications easily.
Spree (Ecommerce)
Installing connectors
gem 'mysql2'
bundle install
production:
adapter: mysql2
encoding: utf8
database: <%= RDS_DB_NAME %> # Which you have entered you creating database
username: <%= RDS_USERNAME %> # db master username
password: <%= RDS_PASSWORD %> # db master password
host: <%= RDS_HOSTNAME %> # db instance entrypoint
port: <%= RDS_PORT %> # db post. For MYSQL 3306
In the example, we will cover Stripe and Braintree two very well-known payment platforms.
gem 'stripe'
Add initializers/stripe.rb file. This file contains the necessary keys for connecting with your stripe account.
require 'require_all'
Rails.configuration.stripe = {
:publishable_key => ENV['STRIPE_PUBLISHABLE_KEY'],
:secret_key => ENV['STRIPE_SECRET_KEY']
}
Stripe.api_key = Rails.configuration.stripe[:secret_key]
This code creates a new customer on Stripe with given email address and source.
payment_token is the token given from the client-side that contains a payment method like a credit card or bank
account. More info: Stripe.js client-side
When we have a customer and a plan we can create a new subscription on Stripe.
It will create a new subscription and will charge our User. It's important to know what really happens on Stripe
when we subscribe a user to a plan, you will find more info here: Stripe Subscription lifecycle.
Sometimes we want to charge our users just a single time, for do that we will do the next.
In that case, we are charging our user one time for given amount.
Common errors:
You cannot charge a user in two currencies. If the user was charged in EUR at any moment in the past you
cannot charge the user in USD.
This code contains the script that will be executed on our docker machine at the moment of start.For this reason,
we are installing all the required libraries and ends with the start of Puma (RoR dev server)
# Optionally set a maintainer name to let people know who made this image.
MAINTAINER Nick Janetakis <[email protected]>
# Install dependencies:
# - build-essential: To ensure certain gems can be compiled
# - nodejs: Compile assets
# - libpq-dev: Communicate with postgres through the postgres gem
RUN apt-get update && apt-get install -qq -y --no-install-recommends \
build-essential nodejs libpq-dev git
# This sets the context of where commands will be running in and is documented
# on Docker's website extensively.
WORKDIR $INSTALL_PATH
# Copy in the application code from your work station at the current directory
# over to the working directory.
COPY . .
# Ensure the static assets are exposed to a volume so that nginx can read
# in these values later.
VOLUME ["$INSTALL_PATH/public"]
# The default command that gets run will be to start the Puma server.
CMD bundle exec puma -C config/puma.rb
version: '2'
services:
backend:
links:
- #whatever you need to link like db
build: .
command: ./scripts/start.sh
ports:
- '3000:3000'
volumes:
- .:/backend
volumes_from:
- gembox
env_file:
- .dev-docker.env
stdin_open: true
tty: true
Just with these two files you will have enough to run docker-compose up and wake up your docker
created_at
created_on
updated_at
updated_on
deleted_at
(paranoia
gem)
lock_version
type
id
#{table_name}_count
position
parent_id
lft
rgt
quote_value
alias
and
BEGIN
begin
break
case
class
def
defined?
do
else
elsif
END
end
ensure
false
abhas Chapter 40
Abhinay Chapter 10
Adam Lassek Chapters 2, 5, 6, 9, 12, 13, 38, 40 and 42
Ahsan Mahmood Chapter 25
Aigars Cibuļskis Chapter 5
Ajay Barot Chapters 1 and 13
Akshay Borade Chapter 57
Ali MasudianPour Chapter 16
Andy Gauge Chapter 2
AnoE Chapter 3
Antarr Byrd Chapter 10
Arslan Ali Chapter 54
ArtOfCode Chapter 20
Ashish Bista Chapter 41
Aswathy Chapter 1
Atul Khanduri Chapters 7 and 14
Avdept Chapter 13
Awais Shafqat Chapter 35
B Liu Chapter 37
B8vrede Chapter 33
Bijal Gajjar Chapter 3
br3nt Chapters 7 and 13
Brian Chapter 58
buren Chapter 5
cl3m Chapter 2
Cuisine Hacker Chapter 20
Cyril Duchon Chapters 2 and 17
D Chapter 3
Dénes Papp Chapter 32
danirod Chapter 4
Darpan Chhatravala Chapters 1 and 48
Darshan Patel Chapter 1
DawnPaladin Chapter 65
Deep Chapters 21, 27 and 47
Deepak Kabbur Chapter 69
Deepak Mahakale Chapters 1, 2, 5 and 12
dgilperez Chapters 10, 12 and 25
Dharam Chapters 2, 15 and 32
dnsh Chapter 13
dodo121 Chapter 12
Don Giovanni Chapter 43
elasticman Chapter 4
Emre Kurt Chapter 73
esthervillars Chapter 2
Fabio Ros Chapters 2, 13 and 46
fiedl Chapter 18
Fire Chapters 2 and 21
Flambino Chapter 7
fool Chapter 56