[srijan wednesday webinar] rails 5: what's in it for me?
TRANSCRIPT
Rails 5What’s in it for me?
@_cha1tanya@BigBinary
@Srijan
Overview of Rails 5
Rails.5.started_on?
Nov, 2014
9359+ Commits
Beta 3
RC 1 coming soon
Lots of new features
Bug fixes
Improvements
DHH Features
Major features
Ruby 2.2.2+Rails 5 will require that your apps runs on Ruby 2.2.2 or latest.
Symbol GC
Incremental GC
Chance to cleanupRails internals
Keyword argumentsRails code can use keyword arguments internally as now it only supports Ruby 2.2.2 +
Module#prepend
Action CableDHH talking about Action Cable https://www.youtube.com/watch?v=n0WUjGkDFS0
Full StackIt has both Ruby side as well as JavaScript side.
Pub/Sub
Seamless integration with
other parts
module ApplicationCable class Connection < ActionCable::Connection::Base identified_by :current_user
def connect self.current_user = find_verified_user end
protected def find_verified_user id = cookies.signed[:user_id] if current_user = User.find_by(id: id) current_user else reject_unauthorized_connection end end endend
Ruby sideInitially it was started with hard dependency on event machine.It was later dropped in https://github.com/rails/rails/commit/74497eabd52f2f9f8c383808b11286283046c2b2.
Now Action Cable does not have hard dependency on Event machine
These are the 3 dependencies of Action Cable on Ruby side:
websocket-drivernio4rconcurrent-ruby
Adapters
InlineAsync
Good for development and test mode.
Evented RedisNon-Evented Redis
PostgresqlFor production mode.
Rendering a template
outside of controller
ActionController::Renderer.render
Basecamp 3
API only apps
What is an API only app
Twitter APIGithub API
Supplementary APIs where apps are still traditional web apps
Proliferation of client side
frameworks
Rails as a Back EndWhich results into using Rails only as
back end app.
No HTML, only JSON!
Slim version of Rails
No view layer
Limited set of middlewares
JBuilderActiveModel::SerializerThese can be used with API only apps to generate JSON
Still Rails!(But for API)
Create new Rails API only appwith
rails new api_app --api
Convert existing app to API only app
config.api_only = true
development
PumaPuma is default web server now
config/puma.rb
Newly created Rails 5 apps will come with a config/puma.rb by default.
New Welcome page
`rails` CLI
rake db:migrate
rails server
Why some rake and some rails?
In Rails 5, just use `rails`
rails db:migrate
rails server
rails assets:precompile
One `rails` command to bind
them all!
Rake Proxy
rake db:migrate #works
rails restartAbility to restart Rails app in
development.https://github.com/rails/rails/issues/188
76
tmp/restart.txt
Similar to how passenger restarts app by touching tmp/restart.txt
Works with Pow,Puma
rails dev:cache
Caching in development modeIn previous Rails versions, caching does not work automatically in development.
Now it will work in Rails 5.
Toggles caching in development
Also restarts app
Filtering routeshttps://github.com/rails/rails/issues/189
02Ability to filter routes.
Have thousands of routes?
Filtering is easier now
rails routes -c users
rails routes -c admin/users
rails routes -c PostsController
rails routes -g PATCH
rails routes -g admin
Evented File system monitor
Reloading in development
Rails reloads all code in development when something changes. For that it has to do a
complete walkthrough of all files.
Check something has changed or not
config.file_watcher
gem ‘listen’
test
Test RunnerRails 5 has added Rspec like test runner
http://blog.bigbinary.com/2016/01/03/test-runner-in-rails-5.html
bin/rails test
Running a single test by line number$ bin/rails test test/models/user_test.rb:27
$ bin/rails test test/models test/jobs
Improved failure message
$ bin/rails tRun options: --seed 51858
# Running:
.F
Failure:PostsControllerTest#test_should_get_new:Expected response to be a <success>, but was a <302> redirect to <http://test.host/posts>
bin/rails test test/controllers/posts_controller_test.rb:15
Failing fast
$ bin/rails t -fRun options: -f --seed 59599
# Running:
..F
Failure:PostsControllerTest#test_should_get_new:Expected response to be a <success>, but was a <302> redirect to <http://test.host/posts>
bin/rails test test/controllers/posts_controller_test.rb:15
Interrupted. Exiting...
Finished in 0.179125s, 16.7481 runs/s, 22.3308 assertions/s.
3 runs, 4 assertions, 1 failures, 0 errors, 0 skips
Backtrace
See complete backtrace with -b switch$ bin/rails t -b
Error:PostsControllerTest#test_should_create_post:NameError: undefined local variable or method `boom' for #<PostsController:0x007fc53c4eb868> /rails-5-test-runner-app/app/controllers/posts_controller.rb:29:in `create' /sources/rails/actionpack/lib/action_controller/metal/basic_implicit_render.rb:4:in `send_action' /sources/rails/actionpack/lib/abstract_controller/base.rb:183:in `process_action' /sources/rails/actionpack/lib/action_controller/metal/rendering.rb:30:in `process_action' /sources/rails/actionpack/lib/abstract_controller/callbacks.rb:20:in `block in process_action' /sources/rails/activesupport/lib/active_support/callbacks.rb:126:in `call'..... /sources/rails/activesupport/lib/active_support/testing/assertions.rb:71:in `assert_difference' /rails-5-test-runner-app/test/controllers/posts_controller_test.rb:19:in `block in <class:PostsControllerTest>'
Colored output
Controller tests
assignsassert_template
assignsassert_template
Why?
gem ‘action-controller_testing’
Controller tests are integration tests
def test_index get :index assert_response :successend
Example of changed controller test.
def test_index get posts_url
assert_response :successend
https://github.com/rails/rails/issues/22076
ActionController::TestCase
In Rails 4.x this was the superclass for all controller tests.
ActionDispatch::IntegrationTest
Now it is this one. Also a lot of effort has gone into making these tests faster.
More focus onintegration testing
caching
http_cache_forever
def index http_cache_forever do render ‘index’ endend
Use it with caution!It will literally set the cache control headers for ‘forever’. Make sure that you are using it with static content only.
Collection Caching
@users = User.where(city: 'Pune')
No record is deleted. No record is added.
Caching of collections
ActiveRecord::Relation#cache_key
@users.cache_key=> "users/query-67ed32b36805123"
cache(@users) do ………end
LimitationsDoesn’t work well with limits and groups.
Partials caching
# index.html.erb<%= render partial: 'todo', collection: @todos %>
# _todo.html.erb<% cache todo do %> <%= todo.name %><% end %>
multi_fetch_fragments gem
Folded in Rails 5
Just pass `cached: true` and Rails will fetch all caches at once.
# index.html.erb<%= render partial: 'todo', collection: @todos, cached: true %>
# _todo.html.erb<% cache todo do %> <%= todo.name %><% end %>
Caching Action Mailer views
Active Record
ApplicationRecordApplicationRecord is a new superclass for all app models, analogous to app controllers subclassing ApplicationController instead of ActionController::Base. This gives apps a single spot to configure app-wide model behavior
class Post < ActiveRecord::Baseend
class Post < ApplicationRecordend
#orAdded the #or method on ActiveRecord::Relation, allowing use of the OR operator to combine WHERE or HAVING clauses
Post.where('id = 1').or(Post.where('id = 2'))
# => SELECT * FROM posts WHERE (id = 1) OR (id = 2)
has_secure_token Added ActiveRecord::SecureToken in order to encapsulate generation of unique tokens for attributes in a model using SecureRandomhttps://github.com/rails/rails/pull/18217
class User < ApplicationRecord has_secure_tokenend
>> user = User.new>> user.save=> true
>> user.token=> 'qjCbex522DfVEVd5ysUWppWQ'
URL safe
Fixed length strings
Base 58 encoding
Regenerating also possible
>> user = User.first=> <User id: 11, name: 'John', email: '[email protected]', token: "jRMcN645BQyDr67yHR3qjsJF", token: "qjCbex522DfVEVd5ysUWppWQ">
>> user.token=> "qjCbex522DfVEVd5ysUWppWQ"
>> user.regenerate_token=> true
>> user.token=> "tYYVjnCEd1LAXvmLCyyQFzbm"
Versioned migrations
Backward compatibility
But API must change
For eg. in Rails 4.x
t.timestamps null: false
But in Rails 5, there is no `null: false` still it adds `NULL` constraint when the migration is run in
Rails 5.
t.timestamps # Rails 5
Compatibility Layer
ActiveRecord::Migration[5.0]
Superclass of migrations in Rails 5. Tells Rails for which version this migration was generated.
Active Support
Improvements to Date/Time
next_day/prev_day
Time.current=> Fri, 12 Feb 2016 08:53:31 UTC +00:00
Time.current.next_day=> Sat, 13 Feb 2016 08:53:31 UTC +00:00
Time.current.prev_day=> Thu, 11 Feb 2016 08:53:31 UTC +00:00
next week with same time
Time.current=> Fri, 12 Feb 2016 09:15:10 UTC +00:00
Time.current.next_week=> Mon, 15 Feb 2016 00:00:00 UTC +00:00
Time.current.next_week(same_time: true)=> Mon, 15 Feb 2016 09:15:20 UTC +00:00
on_weekend?
Time.current=> Fri, 12 Feb 2016 09:47:40 UTC +00:00
Time.current.on_weekend?=> false
Time.current.tomorrow=> Sat, 13 Feb 2016 09:48:47 UTC +00:00
Time.current.tomorrow.on_weekend?=> tru
on_weekday?
Time.current=> Fri, 12 Feb 2016 09:47:40 UTC +00:00
Time.current.on_weekday?=> true
Time.current.tomorrow=> Sat, 13 Feb 2016 09:48:47 UTC +00:00
Time.current.tomorrow.on_weekday?=> false
Time.current=> Fri, 12 Feb 2016 09:47:40 UTC +00:00
Time.current.next_weekday=> Mon, 15 Feb 2016 09:55:14 UTC +00:00
Time.current.prev_weekday=> Thu, 11 Feb 2016 09:55:33 UTC +00:00
Enumerable#pluck
users = [{id: 1, name: 'Max'},
{id: 2, name: 'Mark'}, {id: 3, name: 'Jen'}]
users.pluck(:name)=> ["Max", "Mark", "Jen"]
users = [{id: 1, name: 'Max'},
{id: 2, name: 'Mark'}, {id: 3, name: 'Jen'}]
users.pluck(:id, :name)=> [[1, "Max"], [2, "Mark"], [3, "Jen"]]
Improvement to Active Record’s pluck
# In Rails 4.xusers = User.allSELECT `users`.* FROM `users`
users.pluck(:id, :name)# SELECT "users"."id", "users"."name" FROM “users"=> [[1, "Max"], [2, "Mark"], [3, "George"]]
# In Rails 5users = User.allSELECT `users`.* FROM `users`
users.pluck(:id, :name)=> [[1, "Max"], [2, "Mark"], [3, "George"]]
Enumerable#without
vehicles = ['Car', 'Bike', 'Truck', 'Bus']
vehicles.without("Car", "Bike")=> ["Truck", "Bus"]
vehicles = {car: 'Hyundai', bike: 'Honda', bus: 'Mercedes', truck: 'Tata'}
vehicles.without(:bike, :bus)=> {:car=>"Hyundai", :truck=>"Tata"}
Halting callback chainChanged the way in which callback chains can be halted. The preferred method to halt a callback chain from now on is to explicitly throw(:abort).https://github.com/rails/rails/pull/17227
return false from one of the `before` callbacks
Stop entire callback chain
Rails 5 no longer has this side effect!
throw(:abort)
Explicitly throw(:abort) to stop it.
While upgrading, it will still haltFor older apps getting upgraded to Rails 5, the callback will still halt with returning false, as this is a breaking change.
ActiveSupport.halt_callback_chains_on_return_false
Once you are ready, toggle this flag and it will use new behaviour of throw.
Performance
https://github.com/rails/rails/pull/21057https://github.com/rails/rails/pull/18643https://github.com/rails/rails/pull/21411https://github.com/rails/rails/pull/21155https://github.com/rails/rails/pull/20946
And more…
Attributes API
Sprockets 3/4
Turbolinks 5
What’s next?
If you are new to Rails, check out the Rails Doctrine to understand the philosophy behind Rails.
rubyonrails.org/doctrine/
5.0.0.RC1
weblog.rubyonrails.org
@rails
github.com/rails/rails
This week in Rails
rails-weekly.goodbits.io
blog.bigbinary.com/categories/Rails%205
Try RC
Report bugs
Fix bugs!
Let’s make Rails better
Thank you!@_cha1tanya@BigBinary
@Srijan