Share
Embed
New Stuff in Rails 4
Sandbox Rails 4 demo project I've used for this presentation is here:
https://github.com/gregmalcolm/rails4demo
Greg Malcolm
October 21, 2013
Transcript
30 slides
-
Moved to Gem-space • Mass assignment • ActiveRecord::SessionStore • Action
Caching, Page Caching, Cashew Cashing • Observers • ActiveResource • Sprockets -
Moved to Gem-space • Mass assignment • ActiveRecord::SessionStore • Action
Caching, Page Caching, Cashew Cashing • Observers • ActiveResource • Sprockets -
ActiveModel class Tardis! include ActiveModel::Validations! include ActiveModel::Conversion! extend ActiveModel::Naming! !
attr_accessor :doctor, ! :companion, ! :theme! ! def initialize(attributes = {})! attributes.each do |k, v|! send(“#{k}=”, v)! end! end! end Rails 3: -
ActiveModel::Model class Tardis! include ActiveModel::Model! ! attr_accessor :doctor, ! :companion,
! :theme! ! validates :doctor, presence: true! validates :companion, length: { maximum: 20 }! end -
Finders ‘all’ is scopey now 2.0.0p0 :037 > Wizard.all.last! Wizard
Load (0.8ms) SELECT "wizards".* FROM "wizards" ORDER BY "wizards"."id" DESC LIMIT 1! => #<Wizard id: 7, name: "Bellatrix", alignment: "evil", spells: ["Avada Kedavra", "Accio"], bag_of_holding: nil, created_at: "2013-07-25 04:10:36", updated_at: "2013-07-25 04:10:36"> -
Finders • find_all_by_name(‘Gandalf’) • find_last_by_name(‘Rincewind’) • find_or_create_by_name(‘Hermione’) • find_or_create_by_name!(‘Merlin’) •
find_or_initialize_by_name(‘Harry Dresden’) • scoped_by_name(‘Allanon’) Deprecated magic finders: -
Form Helpers • number_field • date_field • week_field • month_field
• color_field • highlight HTML5: -
class WizardsController < ApplicationController! before_action :set_wizard, only: [:show, :edit, :update,
:destroy]! ! ...! ! # PATCH/PUT /wizards/1! # PATCH/PUT /wizards/1.json! def update! respond_to do |format|! if @wizard.update(wizard_params)! format.html { redirect_to @wizard, notice: 'Wizard was successfully updated.' }! format.json { head :no_content }! else! format.html { render action: 'edit' }! format.json { render json: @wizard.errors, status: :unprocessable_entity }! end! end! end! ! ...! ! private! # Use callbacks to share common setup or constraints between actions.! def set_wizard! @wizard = Wizard.find(params[:id])! end! ! # Never trust parameters from the scary internet, only allow the white list through.! def wizard_params! params.require(:wizard).permit(:name, :alignment, :spells, :bag_of_holding)! end! end -
class WizardsController < ApplicationController! before_action :set_wizard, only: [:show, :edit, :update,
:destroy]! ! ...! ! # PATCH/PUT /wizards/1! # PATCH/PUT /wizards/1.json! def update! respond_to do |format|! if @wizard.update(wizard_params)! format.html { redirect_to @wizard, notice: 'Wizard was successfully updated.' }! format.json { head :no_content }! else! format.html { render action: 'edit' }! format.json { render json: @wizard.errors, status: :unprocessable_entity }! end! end! end! ! ...! ! private! # Use callbacks to share common setup or constraints between actions.! def set_wizard! @wizard = Wizard.find(params[:id])! end! ! # Never trust parameters from the scary internet, only allow the white list through.! def wizard_params! params.require(:wizard).permit(:name, :alignment, :spells, :bag_of_holding)! end! end -
class WizardsController < ApplicationController! before_action :set_wizard, only: [:show, :edit, :update,
:destroy]! ! ...! ! # PATCH/PUT /wizards/1! # PATCH/PUT /wizards/1.json! def update! respond_to do |format|! if @wizard.update(wizard_params)! format.html { redirect_to @wizard, notice: 'Wizard was successfully updated.' }! format.json { head :no_content }! else! format.html { render action: 'edit' }! format.json { render json: @wizard.errors, status: :unprocessable_entity }! end! end! end! ! ...! ! private! # Use callbacks to share common setup or constraints between actions.! def set_wizard! @wizard = Wizard.find(params[:id])! end! ! # Never trust parameters from the scary internet, only allow the white list through.! def wizard_params! params.require(:wizard).permit(:name, :alignment, :spells, :bag_of_holding)! end! end -
class WizardsController < ApplicationController! before_action :set_wizard, only: [:show, :edit, :update,
:destroy]! ! ...! ! # PATCH/PUT /wizards/1! # PATCH/PUT /wizards/1.json! def update! respond_to do |format|! if @wizard.update(wizard_params)! format.html { redirect_to @wizard, notice: 'Wizard was successfully updated.' }! format.json { head :no_content }! else! format.html { render action: 'edit' }! format.json { render json: @wizard.errors, status: :unprocessable_entity }! end! end! end! ! ...! ! private! # Use callbacks to share common setup or constraints between actions.! def set_wizard! @wizard = Wizard.find(params[:id])! end! ! # Never trust parameters from the scary internet, only allow the white list through.! def wizard_params! params.require(:wizard).permit(:name, :alignment, :spells, :bag_of_holding)! end! end -
class WizardsController < ApplicationController! before_action :set_wizard, only: [:show, :edit, :update,
:destroy]! ! ...! ! # PATCH/PUT /wizards/1! # PATCH/PUT /wizards/1.json! def update! respond_to do |format|! if @wizard.update(wizard_params)! format.html { redirect_to @wizard, notice: 'Wizard was successfully updated.' }! format.json { head :no_content }! else! format.html { render action: 'edit' }! format.json { render json: @wizard.errors, status: :unprocessable_entity }! end! end! end! ! ...! ! private! # Use callbacks to share common setup or constraints between actions.! def set_wizard! @wizard = Wizard.find(params[:id])! end! ! # Never trust parameters from the scary internet, only allow the white list through.! def wizard_params! params.require(:wizard).permit(:name, :alignment, :spells, :bag_of_holding)! end! end -
Postgres Native Support • UUID • Network Address Types (IP4/IP6,
MAC) • JSON • String Arrays • HStore -
Postgres class SetupHstore < ActiveRecord::Migration def self.up execute "create extension
hstore" end ! def self.down execute "drop extension hstore" end end -
Postgres class SetupHstore < ActiveRecord::Migration def self.up #execute "create extension
hstore" system("psql template1 -c 'create extension hstore;'") end ! def self.down #execute "drop extension hstore" system("psql template1 -c 'drop extension hstore;'") end end -
Postgres class CreateWizards < ActiveRecord::Migration def change create_table :wizards do
|t| t.string :name t.string :alignment t.string :spells, array:true t.hstore :bag_of_holding ! t.timestamps end end end -
Postgres Wizard.create name: 'Bellatrix', alignment: 'evil', spells: ['Avada Kedavra', 'Accio'],
bag_of_holding: { wand: 'goose bone' } ! Wizard.create name: 'Evil Willow', alignment: 'evil', spells: ['Sphere of Infinite Agonies', 'Living Flame', 'Vine Bondage'], bag_of_holding: { wand: 'unicorn tears', toothbrush: 'evil' } -
Postgres class Wizard < ActiveRecord::Base store_accessor :bag_of_holding, :wand store_accessor :bag_of_holding,
:toothbrush store_accessor :bag_of_holding, :cupboard end -
Postgres HStore Queries Who has a wand? Wizard.where("bag_of_holding ? 'wand'")
Who has a specific wand? Wizard.where("bag_of_holding -> 'wand' like 't%'")