Last active
December 25, 2015 20:49
-
-
Save jlucasps/7037824 to your computer and use it in GitHub Desktop.
Rails roadmap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
rails-0.10.0: Routing, Web Services, Components, Oracle | |
active support: | |
class e module attribute accessors: | |
Extends the class object with class and instance accessors for class attributes | |
Extends the module object with module and instance accessors for class attributes | |
inflectors: | |
The Inflector transforms words from singular to plural, class names to table names, modularized class names | |
to ones without, and class names to foreign key. | |
breakpoints: | |
The Breakpoint library provides the convenience of being able to inspect and modify state, diagnose | |
bugs all via IRB by simply setting breakpoints in your applications by the call of a method. | |
core_ext: | |
Adiciona comportamentos convenientes a diversas classes Ruby | |
time: | |
calculations: | |
Mudar campos específicos em uma data. Por exemplo, mudar do ano 2005 para 2006 | |
assert_equal Time.local(2006,2,22,15,15,10), Time.local(2005,2,22,15,15,10).change(:year => 2006) | |
Retornar uma nova data sendo um número de segundos antes ou depois de uma certa data. Por ex, | |
assert_equal Time.local(2005,2,22,10,10,9), Time.local(2005,2,22,10,10,10).ago(1) | |
assert_equal Time.local(2005,2,20,10,10,10), Time.local(2005,2,22,10,10,10).ago(86400*2) | |
Retornar uma nova data sendo o início do dia, semana ou mês | |
assert_equal Time.local(2005,1,31), Time.local(2005,2,4,10,10,10).beginning_of_week | |
assert_equal Time.local(2005,2,4,0,0,0), Time.local(2005,2,4,10,10,10).beginning_of_day | |
conversions: | |
Getting times in different convenient string representations and other objects | |
assert_equal "February 21, 2005 17:44", Time.local(2005, 2, 21, 17, 44, 30).to_s(:long) | |
assert_equal Date.new(2005, 2, 21), Time.local(2005, 2, 21, 17, 44, 30).to_date | |
string: | |
inflections: | |
Makes it possible to do "posts".singularize that returns "post" and "MegaCoolClass".underscore that returns "mega_cool_class". | |
"ApplicationController" => "application_controller" | |
"UsersSection::CommissionDepartment" => "users_section/commission_department" | |
"Person" => "person_id" | |
"NodeChild" => "node_children" | |
numeric: | |
byte: | |
Enables the use of byte calculations and declarations, like 45.bytes + 2.6.megabytes | |
1024.kilobytes => 1.megabyte | |
1.kilobyte ** 4 => 1.terabyte | |
time: | |
Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years | |
1.minute => 60 | |
1.hour + 15.minutes => 4500 | |
2.days + 4.hours + 30.minutes => 189000 | |
hash: | |
stringify_keys, symbolize_keys e indifferent_access | |
strings = { 'a' => 1, 'b' => 2 } | |
symbols = { :a => 1, :b => 2 } | |
mixed = { :a => 1, 'b' => 2 } | |
date: | |
conversions: | |
Getting dates in different convenient string representations and other objects | |
assert_equal "February 21, 2005", Date.new(2005, 2, 21).to_s(:long) | |
assert_equal Time.local(2005, 2, 21), Date.new(2005, 2, 21).to_time | |
active record: | |
connections: | |
db2, mysql, oracle, postgresql, sqlite, sqlite3, sqlserver | |
mapping: | |
class Product < ActiveRecord::Base; end | |
is automatically mapped to the table named "products", | |
associations: | |
class Firm < ActiveRecord::Base | |
has_many :clients | |
has_one :account | |
belongs_to :conglomorate | |
has_and_belongs_to_many :investors | |
end | |
natural assignments: | |
apple.account = citibank | |
assert_equal apple.id, citibank.firm_id | |
validations: | |
Validation rules that can differ for new or existing objects | |
class Account < ActiveRecord::Base | |
validates_presence_of :subdomain, :name, :email_address, :password | |
validates_uniqueness_of :subdomain | |
validates_acceptance_of :terms_of_service, :on => :create | |
validates_confirmation_of :password, :email_address, :on => :create | |
end | |
callbacks: | |
Callbacks as methods or queues on the entire lifecycle (instantiation, saving, destroying, validating, etc). | |
:after_find, :after_initialize, :before_validation, :before_validation_on_update, :after_validation, :after_validation_on_update, :before_save, :before_update, :after_update, :after_save, :before_destroy, :after_destroy | |
finds and dynamic methods: | |
Firm.find(1, 2) | |
Company.find_first "name = 'Next Angle'" | |
Firm.find_by_sql("SELECT * FROM companies WHERE id = 1").first | |
Topic.find(1, :conditions => "approved = 1") | |
Topic.find_by_title("The First Topic") | |
Topic.find_by_title_and_author_name("The First Topic", "David") | |
Topic.find_all_by_content("Have a nice day") | |
next_angle.clients.find(2) | |
next_angle.clients.empty? | |
next_angle.clients.size | |
action pack: | |
Action Pack splits the response to a web request into a controller part (performing the logic) and a view | |
part (rendering a template). This two-step approach is known as an action, which will normally create, read, update, | |
or delete (CRUD for short) some sort of model part (often backed by a database) before choosing either to render a | |
template or redirecting to another action | |
action controller: | |
Action Controllers are then responsible for handling all the actions relating to a certain part of an application. | |
This grouping usually consists of actions for lists and for CRUDs revolving around a single (or a few) model objects | |
Actions grouped in controller as methods instead of separate command objects: | |
BlogController < ActionController::Base | |
def display | |
@customer = find_customer | |
end | |
private | |
def find_customer() Customer.find(@params["id"]) end | |
end | |
Filters for pre and post processing of the response: | |
lass WeblogController < ActionController::Base | |
before_filter :authenticate, :cache, :audit | |
after_filter { |c| c.response.body = GZip::compress(c.response.body) } | |
Layout sharing for template reuse: | |
class WeblogController < ActionController::Base | |
layout "weblog_layout" | |
def hello_world | |
end | |
end | |
Scaffolding for Action Record model objects: | |
require 'account' # must be an Active Record class | |
class AccountController < ActionController::Base | |
scaffold :account | |
end | |
# templates: list, show, destroy, new, create, edit, update | |
Advanced redirection that makes pretty urls easy: | |
RewriteRule ^/library/books/([A-Z]+)([0-9]+)/([-_a-zA-Z0-9]+)$ \ | |
/books_controller.cgi?action=$3&type=$1&code=$2 [QSA] [L] | |
Accessing /library/books/ISBN/0743536703/show calls BooksController#show | |
action view: | |
Action View templates are written using embedded Ruby in tags mingled in with the HTML. To avoid cluttering the | |
templates with code, a bunch of helper classes provide common behavior for forms, dates, and strings. | |
Embedded Ruby for templates: | |
<% for post in @posts %> | |
Title: <%= post.title %> | |
<% end %> | |
Helpers for forms, dates, action links, and text: | |
<%= text_field "post", "title", "size" => 30 %> | |
<%= html_date_select(Date.today) %> | |
<%= link_to "New post", :controller => "post", :action => "new" %> | |
<%= truncate(post.title, 25) %> | |
Form building for Active Record model objects: | |
<%= form "post" %> | |
This form generates a @params["post"] array that can be used directly in a save action | |
Rendering shared partials: | |
<%= render_partial "advertisement/ad", ad %> | |
action mailer: | |
Action Mailer is framework for designing email-service layers. | |
The framework works by setting up all the email details, except the body: | |
def signed_up(recipient) | |
@recipients = recipient | |
@subject = "[Signed up] Welcome #{recipient}" | |
@from = "[email protected]" | |
@sent_on = Time.local(2004, 12, 12) | |
@body["recipient"] = recipient | |
end | |
The body of the email is created by using an Action View template (regular ERb) | |
ApplicationMailer.deliver_signed_up("[email protected]") # sends the email | |
rails-0.11.0: Ajax, Pagination, Non-vhost, Incoming mail | |
active support: | |
string to date and time: | |
assert_equal Time.utc(2005, 2, 27, 23, 50), "2005-02-27 23:50".to_time | |
assert_equal Date.new(2005, 2, 27), "2005-02-27".to_date | |
active record: | |
Oracle native to OCI Oracle | |
action pack: | |
ajax | |
action mailer: | |
incoming mails | |
rails-0.12.0: Eager associations, new Base.find API, assertions revisited, more Ajax! | |
# Turning N+1 queries into 1 | |
for post in Post.find(:all, :include => [ :author, :comments ]) | |
puts "Post: " + post.title | |
puts "Written by: " + post.author.name | |
puts "Last comment on: " + post.comments.first.created_on | |
end | |
Person.find(1, :conditions =>"administrator = 1", :order =>"created_on DESC") | |
Person.find(1, 5, 6, :conditions =>"administrator = 1", :order =>"created_on DESC") | |
Person.find(:first, :order =>"created_on DESC", :offset => 5) | |
Person.find(:all, :conditions => [ "category IN (?)", categories], :limit => 50) | |
Person.find(:all, :offset => 10, :limit => 10) | |
rails-0.13: | |
Using script.aculo.us to visual effects, drag’n’drop, sortable lists, auto-completing text fields | |
remote link: | |
link_to_remote( | |
"test", | |
:url => { :action =>"faulty" }, | |
:update => { :success =>"good", :failure =>"bad" }, | |
403 =>"alert('Forbidden- got ya!')", | |
404 =>"alert('Nothing there...?')", | |
:failure =>"alert('Unkown error ' + request.status)" | |
) | |
Migrations for PostgreSQL and MySQL: | |
With migrations, you can describe the transformations in self-contained classes that can be checked | |
into version control systems and executed against another database that might be one, two, or five versions behind. | |
Rendering: One method to bind them all | |
Routes: Giving them a name and calling them by it | |
map.home '', :controller => 'main', :action => 'start' | |
edirect_to :controller => 'main', :action => 'start' ... is now redirect_to :home_url | |
Mail attachments | |
Conditional validations: | |
validates_numericality_of :income, :if => :employed? | |
validates_presence_of :username, :if => Proc.new { |user| user.signup_step > 1 } | |
rails-1.0 : | |
script/plugin: | |
Helps you install, manage, and discover new plugins | |
Active Record: | |
find_or_create_by_X, association collection extensions, migrations for all databases | |
rails-1.1.0 | |
gzip compression for JavaScript, CSS, and HTML to default lighttpd.conf | |
Avoid passing escapeHTML non-string in Rails' info controller | |
RJS: JavaScript written in Ruby | |
Polymorphic associations: | |
class Address < ActiveRecord::Base | |
belongs_to :addressable, :polymorphic => true | |
end | |
class Person < ActiveRecord::Base | |
has_one :address, :as => :addressable | |
end | |
class Company < ActiveRecord::Base | |
has_one :address, :as => :addressable | |
end | |
Calculations: | |
sum, average, count, max | |
Eager loading: | |
# Single database query: | |
companies = Company.find(:all, :include => { :groups => { :members=> { :favorites } } }) | |
# Just 1 database query for all of this: | |
authors = Author.find(:all, :include => [ { :posts => :comments }, :categorizations ]) | |
authors[0].posts[0].comments[0].body # => "Rock on Rails!" | |
authors[0].categorizations[0].name # => "Less software" | |
respond_to: Launch your application with both Ajax, non-Ajax, and API access through the same actions | |
def create | |
@post = Post.create(params[:post]) | |
respond_to do |type| | |
type.js { render } # renders create.rjs | |
type.html { redirect_to :action => "index" } | |
type.xml do | |
headers["Location"] = post_url(:id => @post) | |
render(:nothing, :status => "201 Created") | |
end | |
end | |
end | |
Integration tests: | |
They allow you to faithfully simulate users accessing multiple controllers and even gives | |
you the power to simulate multiple concurrent users. | |
rails-1.2 | |
REST, formats and respond_to: | |
class WeblogController < ActionController::Base | |
def index | |
@posts = Post.find :all | |
respond_to do |format| | |
format.html | |
format.xml { render :xml => @posts.to_xml } | |
format.rss { render :action => “feed.rxml” } | |
end | |
end | |
end | |
GET /weblog # returns HTML from browser Accept header | |
GET /weblog.xml # returns the XML | |
GET /weblog.rss # returns the RSS | |
Auto-loading: | |
Module loading, which means that a reference for Accounting::Subscription will look | |
for app/models/accounting/subscription.rb. | |
Referencing Subscription will not look for subscription.rb in any subdir of app/models. | |
Only app/models/subscription.rb will be tried. | |
rails-1.2.2: | |
single resource: | |
map.resource :account | |
rails-2 preview: | |
Action Pack: Resources: | |
namespaces e collection resources | |
Action Pack: Multiview: | |
So show.rhtml now becomes show.html.erb, which is the template that’ll be rendered by default | |
for a show action that has declared format.html in its respond_to. | |
Action Pack: Record identification: | |
# person is a Person object, which by convention will | |
# be mapped to person_url for lookup | |
redirect_to(person) | |
link_to(person.name, person) | |
form_for(person) | |
Action Pack: Security: | |
Most importantly, we now ship we a built-in mechanism for dealing with CRSF attacks. | |
By including a special token in all forms and Ajax requests, you can guard from having requests made | |
from outside of your application. | |
ActionWebService out, ActiveResource in: | |
It’ll probably come as no surprise that Rails has picked a side in the SOAP vs REST debate. | |
Unless you absolutely have to use SOAP for integration purposes, we strongly discourage you from doing so. | |
Action Pack: Exception handling: | |
class PostsController < ApplicationController | |
rescue_from User::NotAuthorized, :with => :deny_access | |
protected | |
def deny_access | |
... | |
end | |
end | |
rails-2.1: Time zones, dirty, caching, gem dependencies, caching, etc | |
change tracking methods: | |
p.changed? | |
p.changes | |
p.name_changed? | |
gem dependencies: | |
gem verions at config/environments/test.rb | |
named scopes: | |
class Product < ActiveRecord::Base | |
belongs_to :category | |
named_scope :cheap, :conditions => { :price => 0..5 } | |
named_scope :recent, lambda { |*args| {:conditions => ["released_at > ?", (args.first || 2.weeks.ago)]} } | |
named_scope :visible, :include => :category, :conditions => { 'categories.hidden' => false } | |
end | |
rails-2.2 | |
i18n internacionalization | |
Ruby 1.9 and JRuby compatible | |
rails-2.3: | |
nested attributes: | |
class Book < ActiveRecord::Base | |
has_one :author | |
has_many :pages | |
accepts_nested_attributes_for :author, :pages | |
end | |
default scopes | |
adopted Rack | |
Multiple Conditions for Callbacks: | |
before_save :update_credit_rating, :if => :active, :unless => [:admin, :cash_only] | |
Find with having: | |
developers = Developer.find(:all, :group => "salary", :having => "sum(salary) > 10000", :select => "salary") | |
Unified Rendering: | |
render '/tmp/random_file.erb' | |
render 'other_controller/action' | |
render 'show' | |
render :show | |
Smart Rendering of Partials: | |
# Equivalent of render :partial => 'articles/_article', | |
# :object => @article | |
render @article | |
rails-2.3.6: | |
flash keys to alert and notice | |
I18n to internacionalize label_helper | |
rails-3: | |
New ActiveRecord query engine: | |
users = User.where(:name => "david").limit(20) | |
users.order(:name).each { |user| puts user.name } | |
Manage dependencies with Bundler: | |
All Rails 3 applications are born with a Gemfile | |
Active Model: Validations, callbacks, etc for all models: | |
Agnosticism with jQuery, rSpec, and Data Mapper: | |
DataMapper -> Active Record | |
Query -> Prototype | |
Spec -> test/unit | |
rails-3.1: | |
AssetPipeline: | |
Sprockets, SCSS, CoffeeScript | |
JQuery default | |
Reversible migrations | |
asset paths when pipeline is on | |
rails-3.2: | |
Faster dev mode & routing: | |
Only reload classes from files you’ve actually changed. The difference is dramatic on a larger application. | |
Extract your vendor/plugins to their own gems and bundle them in your Gemfile. | |
Explain queries | |
rails-3.2.X: | |
critical security fixies: | |
CVE-2012-5664, CVE-2013-0155, CVE-2013-0156, CVE-2013-0333 | |
rails-4: | |
Turbolinks | |
Live streaming | |
Scopes as callable objects | |
Mass assignment protection from models to Controllers | |
ActiveModel::Model: | |
update its attributes through a form, but not persist it to the database | |
we can create attr_accessors for any method we want | |
add validations just like we would with ActiveRecord | |
Remove resources duplication using concerns: | |
concern :commentable do | |
resources :comments | |
end | |
resources :articles, concerns: :commentable | |
resources :photos, concerns: :commentable | |
Deprecating match and using get, post, patch |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment