Slide 1

Slide 1 text

Rails 4 Nando Vieira

Slide 2

Slide 2 text

Nando Vieira http://simplesideias.com.br @fnando

Slide 3

Slide 3 text

* * *

Slide 4

Slide 4 text

O Rails 4 foi lançado em 25 de junho de 2013. http://fnando.me/i1

Slide 5

Slide 5 text

Rails 3 Rails 4 Revolução Evolução

Slide 6

Slide 6 text

Ruby 1.9.3 Ruby 2.0.0 Versão mínima Recomendado

Slide 7

Slide 7 text

Stron Parameters

Slide 8

Slide 8 text

# app/models/user.rb class User < ActiveRecord::Base attr_accessible :email, :username end # app/controllers/users_controller.rb class UsersController < ApplicationController def create @user = User.create(params[:user]) respond_with(@user) end end Rails 3

Slide 9

Slide 9 text

# app/controllers/users_controller.rb class UsersController < ApplicationController def create @user = User.create(user_params) respond_with(@user) end private def user_params params .require(:user) .permit(:email, :username) end end Rails 4

Slide 10

Slide 10 text

Lança a exceção ActionController::ParameterMissin caso params[:user] não exista.

Slide 11

Slide 11 text

Turbolinks

Slide 12

Slide 12 text

Um plu in JavaScript semelhante ao PJAX (pushState + AJAX) e wiselinks.

Slide 13

Slide 13 text

Turbolinks faz requisições com AJAX e substitui as ta s e com o conteúdo retornado pelo servidor.

Slide 14

Slide 14 text

Firefox 4+ Chrome 5+ IE10+ Safari 6+

Slide 15

Slide 15 text

Você precisa executar manualmente scripts como Goo le Analytics.

Slide 16

Slide 16 text

$(document).on("page:change", function(){ if (window._gaq) { _gaq.push(["_trackPageview"]); } else if (window.pageTracker) { pageTracker._trackPageview(); } }); http://reed. ithub.io/turbolinks-compatibility/

Slide 17

Slide 17 text

Post reSQL ActiveRecord

Slide 18

Slide 18 text

O adapter do Post reSQL recebeu suporte para arrays, hstore e novos tipos de dados.

Slide 19

Slide 19 text

ActiveRecord::Schema.define(version: 0) do create_table :posts do |t| t.text :title t.text :tags, array: true end end

Slide 20

Slide 20 text

post = Post.new post.title = "Array support on ActiveRecord + PostgreSQL" post.tags = %w[rails ruby database] post.save p post.tags # ["rails", "ruby", "database"] p Post.where("? = ANY(tags)", "ruby").first # #

Slide 21

Slide 21 text

sudo apt-get install postgresql-contrib

Slide 22

Slide 22 text

ActiveRecord::Schema.define(version: 0) do execute "CREATE EXTENSION hstore" create_table :users do |t| t.string :username t.hstore :profile end end

Slide 23

Slide 23 text

class User < ActiveRecord::Base store_accessor :profile end

Slide 24

Slide 24 text

user = User.new user.username = "fnando" user.profile = { github: "fnando", twitter: "fnando", instagram: "nandovieira" } user.save p user.profile # {:github=>"fnando"...}

Slide 25

Slide 25 text

# Find users with github key User.where("profile ? :key", key: "github") # Find users without github key User.where("not profile ? :key", key: "github") # Find users with github profile as fnando User.where("profile @> (:key => :value)", key: "github", value: "fnando" ) # Find users with with instagram value like "nan" User.where("profile -> :key LIKE :value", key: "instagram", value: "%nan%" )

Slide 26

Slide 26 text

Lembre-se de adicionar índices ao seu campo hstore.

Slide 27

Slide 27 text

execute "CREATE INDEX users_profile ON users USING gin(profile)" execute "DROP INDEX users_profile"

Slide 28

Slide 28 text

Indices GIN Rápidos para buscar. Lentos para indexar. São melhores quando existem mais de 100 mil termos únicos. http://fnando.me/j

Slide 29

Slide 29 text

Indices GiST Mais lentos que GIN. Mais rápidos para indexar. São melhores quando o número de termos únicos for abaixo de 100 mil.

Slide 30

Slide 30 text

Novos tipos de campos.

Slide 31

Slide 31 text

uuid inet cidr macaddr json ran es Universally Unique Identifier Endereço IPv4 Endereço IPv6 MAC Address Serialização com JSON int4ran e, int8ran e, numran e, tsran e, tstzran e, dateran e

Slide 32

Slide 32 text

Mais ActiveRecord

Slide 33

Slide 33 text

Nova validação chamada absence.

Slide 34

Slide 34 text

class User < ActiveRecord::Base attr_accessor :honeypot validates_absence_of :honeypot validates :honeypot, absence: true end

Slide 35

Slide 35 text

user = User.create(honeypot: "SPAM") user.errors.full_messages => ["Honeypot must be blank"]

Slide 36

Slide 36 text

O ActiveRecord implementa o Null Object Pattern com ActiveRecord::Relation#none e ActiveRecord::NullRelation.

Slide 37

Slide 37 text

class Topic < ActiveRecord::Base def self.filter(filter) case filter when :all all when :published where(published: true) when :draft where(published: false) else where("1 = 0") end end end Rails 3

Slide 38

Slide 38 text

class Topic < ActiveRecord::Base def self.filter(filter) case filter when :all all when :published where(published: true) when :draft where(published: false) else none end end end Rails 4

Slide 39

Slide 39 text

O ActiveRecord implementa um método #not para o operador != nos finders.

Slide 40

Slide 40 text

User.where("role != ?", "admin") # Rails 3 User.where.not(role: "admin") # Rails 4

Slide 41

Slide 41 text

Novos métodos e semântica para a atualização de re istros.

Slide 42

Slide 42 text

user = User.find(params[:id]) user.update_attributes(user_params) # Rails 3 user.update(user_params) # Rails 4

Slide 43

Slide 43 text

user.update_attribute(:username, "fnando") user.update_attributes(username: "fnando") user.update(username: "fnando") user.update_column(:username, "fnando") user.update_columns(username: "fnando")

Slide 44

Slide 44 text

Método Validações Callbacks updated_at Dirty update_attributes update update_attribute update_columns update_column

Slide 45

Slide 45 text

Um novo método ActiveRecord::Base#destroy! lança uma exceção caso o re istro não possa ser removido.

Slide 46

Slide 46 text

class User < ActiveRecord::Base before_destroy :avoid_destruction private def avoid_destruction false end end user = User.create!(username: "fnando") user.destroy user.persisted? #=> true user.destroy! #=> exception ActiveRecord::RecordNotDestroyed

Slide 47

Slide 47 text

O ActiveRecord::Base.all a ora faz lazy loadin em vez de retornar um array.

Slide 48

Slide 48 text

User.all.class #=> ActiveRecord::Relation::ActiveRecord_Relation_User User.all.to_a #=> [] User.scoped DEPRECATION WARNING: Model.scoped is deprecated. Please use Model.all instead.

Slide 49

Slide 49 text

A API do ActiveRecord possui versão com ban para quase todos os métodos.

Slide 50

Slide 50 text

SELECT "users".* FROM "users" WHERE "users"."username" = 'fnando' ORDER BY "users"."created_at" DESC scope = User.all scope.where!(username: "fnando") scope.includes!(:articles) scope.order!(created_at: :desc) scope.to_sql SQL RUBY

Slide 51

Slide 51 text

Novos métodos de busca e inicialização.

Slide 52

Slide 52 text

User.find_by(username: "fnando") User.find_by!(username: "fnando") User.find_or_initialize_by(username: "fnando") User.find_or_create_by(username: "fnando") User.find_or_create_by!(username: "fnando")

Slide 53

Slide 53 text

Os escopos precisam ser callable objects.

Slide 54

Slide 54 text

class User < ActiveRecord::Base scope :recent, -> { order(created_at: :desc) } end

Slide 55

Slide 55 text

Encrypted Cookies

Slide 56

Slide 56 text

Até o Rails 3 todos os dados salvos na sessão podiam ser vistos pelo cliente.

Slide 57

Slide 57 text

$ curl -i http://localhost:3000/ HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 X-Ua-Compatible: IE=Edge Etag: "8b1a9953c4611296a827abf8c47804d7" Cache-Control: max-age=0, private, must-revalidate X-Request-Id: 25af60321d6e9c585c3f04ff8928d824 X-Runtime: 0.014431 Server: WEBrick/1.3.1 (Ruby/2.0.0/2013-06-27) Date: Sat, 13 Jul 2013 20:13:58 GMT Content-Length: 5 Connection: Keep-Alive Set-Cookie: _app_session=BAh7BzoMbWVzc2hh...; path=/; HttpOnly

Slide 58

Slide 58 text

require "rack" Rack::Session::Cookie::Base64::Marshal.new.decode( "BAh7BzoMbWVzc2FnZUkiDEhhY2tlZ..." ) => { message: "Shhh... Secret!", session_id: "e3bc1175000a3b257b4b68d983b9c3e2" } Rails 3

Slide 59

Slide 59 text

O Rails 4 usa cookies cripto rafados com o hash definido em Rails.application.confi .secret_key_base.

Slide 60

Slide 60 text

O mesmo exemplo anterior retornaria nil no Rails 4.

Slide 61

Slide 61 text

require "rack" Rack::Session::Cookie::Base64::Marshal.new.decode( "eVlGTkl1cEt1dHJUdVNzdUNkZWNmNDQxSm..." ) nil Rails 4

Slide 62

Slide 62 text

ActiveModel::Model

Slide 63

Slide 63 text

Para criar formulários com form_for você precisa implementar a API do ActiveModel.

Slide 64

Slide 64 text

class Contact include ActiveModel::Validations include ActiveModel::Conversion extend ActiveModel::Naming attr_accessor :name, :email, :message validates_presence_of :name, :message validates_format_of :email, with: /\A.+@.+\.[a-z]{2,4}\z/ def initialize(attributes = {}) attributes.each do |name, value| public_send("#{name}=", value) end end def persisted? false end end

Slide 65

Slide 65 text

contact = Contact.new(name: "John") contact.valid? #=> false contact.errors.full_messages #=> ["Message can't be blank", "Email is invalid"]

Slide 66

Slide 66 text

A ora você pode incluir o módulo ActiveModel::Model, que já faz tudo isso para você.

Slide 67

Slide 67 text

class Contact include ActiveModel::Model attr_accessor :name, :email, :message validates_presence_of :name, :message validates_format_of :name, with: /\A.+@.+\.[a-z]{2,4}\z/ end

Slide 68

Slide 68 text

Cachin

Slide 69

Slide 69 text

Definir ETa s ficou mais simples.

Slide 70

Slide 70 text

No Rails 3 você precisa definir todas as chaves que compõe o ETa , mesmo que elas sejam a mesma em todo o controller.

Slide 71

Slide 71 text

class ReposController < ApplicationController def show @repo = current_user.repos.find(params[:id]) fresh_when([current_user.id, @repo]) end end Rails 3

Slide 72

Slide 72 text

Você pode definir componentes lobais no controller, complementando com outros componentes na action.

Slide 73

Slide 73 text

class ReposController < ApplicationController etag { current_user.id } def show @repo = current_user.repos.find(params[:id]) fresh_when(@repo) end end

Slide 74

Slide 74 text

O cachin de fra mentos também ficou mais simples com a nova estraté ia de russian doll cachin .

Slide 75

Slide 75 text

No Rails 3 você precisava definir uma versão do fra mento e atualizar seu valor caso o markup mudasse.

Slide 76

Slide 76 text

posts/_post.html.erb posts/index.html.erb posts/_post.html.erb posts/_post.html.erb

Slide 77

Slide 77 text

<%= render @posts %> <% cache ["v1", post] do %> <%= link_to post.title, post_path(post) %> <% end %>

Slide 78

Slide 78 text

posts/show.html.erb the posts details comments/_comment.html.erb comments/_comment.html.erb

Slide 79

Slide 79 text

<% cache ["v1", @post, "details"] do %>

<%= @post.title %>

<%= simple_format @post.content %> <%= render @post.comments %> <% end %> <% cache ["v1", comment] do %> <%= simple_format comment.content %> <% end %>

Slide 80

Slide 80 text

Esse esquema de cachin iria erar chaves considerando a versão.

Slide 81

Slide 81 text

views/v1/posts/1-20130714050931 views/v1/posts/2-20130714052742 views/v1/posts/3-20130714052756 views/v1/posts/1-20130714050931/details views/v1/comments/1-20130714050931

Slide 82

Slide 82 text

Se a partial _comment.html.erb fosse alterada, você precisaria mudar a versão de toda a hierarquia.

Slide 83

Slide 83 text

No Rails 4 você não precisa mais adicionar a versão do cache, pois isso é calculado automaticamente.

Slide 84

Slide 84 text

<% cache post do %> <%= link_to post.title, post_path(post) %> <% end %> <% cache [@post, "details"] do %>

<%= @post.title %>

<%= simple_format @post.content %> <%= render @post.comments %> <% end %> <% cache comment do %> <%= simple_format comment.content %> <% end %>

Slide 85

Slide 85 text

Um hash MD5 é calculado à partir do conteúdo do bloco do método cache.

Slide 86

Slide 86 text

views/posts/1-20130714050931154460000/7c2217e636 8… views/posts/2-20130714052742379289000/7c2217e636 8… views/posts/3-20130714052756198046000/7c2217e636 8… views/posts/1-20130714050931154460000/details/369c5d… views/comments/1-20130714050931144537000/7069559c…

Slide 87

Slide 87 text

O cache di est só é calculado uma vez, mesmo em modo de desenvolvimento. Reinicie o memcached ou o app server para recalculá-lo.

Slide 88

Slide 88 text

Outras mudanças

Slide 89

Slide 89 text

Foi removido o suporte para plu ins dentro de vendor/plu ins.

Slide 90

Slide 90 text

ActiveRecord session store foi extraída para uma em chamada activerecord-session_store.

Slide 91

Slide 91 text

Observers e cache sweepers foram extraídos para a em rails-observers.

Slide 92

Slide 92 text

As funcionalidades de cachin foram extraídas para as ems actionpack-pa e_cachin e actionpack-action_cachin .

Slide 93

Slide 93 text

ActiveResource não é mais incluído nas dependências do Rails por padrão.

Slide 94

Slide 94 text

Al uns finders do ActiveRecord deixaram de existir ou tiveram uma nova API.

Slide 95

Slide 95 text

User.find_all_by_role("admin") # Rails 3 User.where(role: "admin") # Rails 4 User.find_last_by_role("admin") # Rails 3 User.where(role: "admin").last # Rails 4 User.find_or_create_by_role("admin") # Rails 3 User.find_or_create_by(role: "admin") # Rails 4 User.find_or_initialize_by_role("admin") # Rails 3 User.find_or_initialize_by(role: "admin") # Rails 4 User.scoped_by_role("admin") # Rails 3 User.where(role: "admin") # Rails 4 User.all(role: "admin") # Rails 3 User.where(role: "admin") # Rails 3

Slide 96

Slide 96 text

User.find(:first) # Rails 3 User.first # Rails 4 User.find(:last) # Rails 3 User.last # Rails 4 User.find(:all) # Rails 3 User.all # Rails 4

Slide 97

Slide 97 text

Instale a em activerecord-deprecated_finders para trazer a API anti a de volta.

Slide 98

Slide 98 text

O verbo HTTP de atualização de resources foi alterado de PUT para PATCH. https:// ithub.com/rails/rails/pull/505

Slide 99

Slide 99 text

Os filtros de fluxo de requisição foram renomeados de *_filter para *_action.

Slide 100

Slide 100 text

before_filter after_filter around_filter before_action after_action around_action

Slide 101

Slide 101 text

class TopicsController before_action :require_logged_user, only: %i[ new create ] end

Slide 102

Slide 102 text

Os diretórios de teste a ora tem nomes mais coerentes.

Slide 103

Slide 103 text

test user_test.rb repo_test.rb models application_helper_test.rb html_helper_test.rb helpers mailer_test.rb mailers # antes era test/units # antes era test/units/helpers # antes era test/functional application_controller_test.rb repos_controller_test.rb controllers # antes era test/functional

Slide 104

Slide 104 text

Você pode definir headers que serão enviados em todos as requisições.

Slide 105

Slide 105 text

config.action_dispatch.default_headers = { "X-Frame-Options" => "SAMEORIGIN", "X-XSS-Protection" => "1; mode=block", "X-Content-Type-Options" => "nosniff" } http://fnando.me/jh

Slide 106

Slide 106 text

Foram adicionados novos helpers de formulário.

Slide 107

Slide 107 text

week_field month_field datetime_field datetime_local_field time_field date_field color_field collection_check_boxes collection_radio_buttons

Slide 108

Slide 108 text

A pá ina de boas-vindas a ora é dinâmica e exibida apenas em modo de desenvolvimento quando a rota root não tiver sido definida.

Slide 109

Slide 109 text

Thread-safe por padrão.

Slide 110

Slide 110 text

* * *

Slide 111

Slide 111 text

Existem muito mais novidades. Al umas nem aparecem nos chan elo s.

Slide 112

Slide 112 text

Experimente as novas funcionalidades para saber se vale a pena ou não usá-las.

Slide 113

Slide 113 text

Obri ado!

Slide 114

Slide 114 text

* * *

Slide 115

Slide 115 text

http://howtocode.com.br