Screencast: Eigene Rails 3 Generatoren erstellen

In Rails 3 wurde die Erstellung von eigenen Generatoren überarbeitet. Ryan zeigt diese Woche wie man eigene Generatoren erstellen kann und was sich an der bisherigen Syntax geändert hat.

 

Download:

Download(14 MB, 10:07)
Alternativer Downloadfür iPod & Apple TV(13.8 MB, 10:07)

 

Resourcen:

 

Quellcode:

[bash]
rails g generator –help
rails g generator layout
rails g layout –help
rails g layout admin
rails g layout foo –skip-stylesheet
[/bash]

[ruby]
# lib/generators/layout/layout_generator.rb
class LayoutGenerator < Rails::Generators::Base
source_root File.expand_path(‚../templates‘, __FILE__)
argument :layout_name, :type => :string, :default => "application"
class_option :stylesheet, :type => :boolean, :default => true, :desc => "Include stylesheet file."

def generate_layout
copy_file "stylesheet.css", "public/stylesheets/#{file_name}.css" if options.stylesheet?
template "layout.html.erb", "app/views/layouts/#{file_name}.html.erb"
end

private

def file_name
layout_name.underscore
end
end
[/ruby]

[html]
# lib/generators/layout/templates/layout.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Untitled</title>
<%- if options.stylesheet? -%>
<%%= stylesheet_link_tag "<%= file_name %>" %>
<%- end -%>
<%%= javascript_include_tag :defaults %>
<%%= csrf_meta_tag %>
<%%= yield(:head) %>
</head>
<body>
<div id="container">
<%% flash.each do |name, msg| %>
<%%= content_tag :div, msg, :id => "flash_#{name}" %>
<%% end %>
<%%= yield %>
</div>
</body>
</html>
[/html]

Screencast: Mehrstufige Formulare

Je nach nach Umfang und Komplexität ist es notwendig ein Formular in mehrere Schritte aufzuteilen. Diese Woche zeigt Ryan in seinem Screencast, wie dies mit Rails gelöst werden kann.

 

Download:

Download(21.8 MB, 15:14)
Alternativer Downloadfür iPod & Apple TV(20.9 MB, 15:14)

 

Resourcen:

 

Quellcode:

[bash]
script/generate nifty_scaffold order shipping_name:string billing_name:string index show new
[/bash]

[ruby]
# models/order.rb
attr_writer :current_step

validates_presence_of :shipping_name, :if => lambda { |o| o.current_step == "shipping" }
validates_presence_of :billing_name, :if => lambda { |o| o.current_step == "billing" }

def current_step
@current_step || steps.first
end

def steps
%w[shipping billing confirmation]
end

def next_step
self.current_step = steps[steps.index(current_step)+1]
end

def previous_step
self.current_step = steps[steps.index(current_step)-1]
end

def first_step?
current_step == steps.first
end

def last_step?
current_step == steps.last
end

def all_valid?
steps.all? do |step|
self.current_step = step
valid?
end
end

# orders_controller.rb
def new
session[:order_params] ||= {}
@order = Order.new(session[:order_params])
@order.current_step = session[:order_step]
end

def create
session[:order_params].deep_merge!(params[:order]) if params[:order]
@order = Order.new(session[:order_params])
@order.current_step = session[:order_step]
if @order.valid?
if params[:back_button]
@order.previous_step
elsif @order.last_step?
@order.save if @order.all_valid?
else
@order.next_step
end
session[:order_step] = @order.current_step
end
if @order.new_record?
render "new"
else
session[:order_step] = session[:order_params] = nil
flash[:notice] = "Order saved!"
redirect_to @order
end
end
[/ruby]

[html]
<!– orders/new.html.erb –>
<% form_for @order do |f| %>
<%= f.error_messages %>
<%= render "#{@order.current_step}_step", :f => f %>
<p><%= f.submit "Continue" %></p>
<p><%= f.submit "Back", :name => "back_button" unless @order.first_step? %></p>
<% end %>
[/html]

Screencast: Generatoren in Rails 3

In Rails 3 wurden die Generatoren komplett überarbeitet und modularisiert. Auf diese Weise lassen sie sich an die eigenen Anforderngen anpassen. Ryan zeigt in dieser Woche wie man dies machen kann.

 

Download:

Download(43.3 MB, 11:24)
Alternativer Downloadfür iPod & Apple TV(33.7 MB, 11:24)

 

Resourcen:

 

Quellcode:

[bash]
rails g
rails g scaffold –help
rails g scaffold project name:string –no-stylesheets
bundle install
rails g scaffold task project_id:integer
rails g scaffold category name:string
[/bash]

[ruby]
# Gemfile
group :test do
gem "shoulda"
gem "factory_girl"
end

gem "rails3-generators", :group => :development

# config/application.rb
config.generators do |g|
g.stylesheets false
g.test_framework :shoulda
g.fixture_replacement :factory_girl
end
# …
require ‚rails/generators‘
Rails::Generators.fallbacks[:shoulda] = :test_unit
[/ruby]

Screencast: Refactoring und Dynamic Delegator

Code Refactoring ist der Prozess bei dem ein Programm modifiziert (optimiert, verbessert) wird ohne sein Verhalten nach aussen zu verändern. Diese Woche zeigt Ryan wie Refactoring eingesetzt werden kann und wie man Dynamic Delegator in Active Recors nutzt.

 

Download:

Download (11.2 MB, 7:58)
Alternativer Download für iPod & Apple TV (10.9 MB, 7:58)

 

Resourcen:

 

Quellcode:

[ruby]
# rails console
Product.search({}).class
Object.instance_methods
BasicObject.instance_methods

# products_controller.rb
@products = Product.search(params)

# models/product.rb
def self.search(params)
products = scope_builder
products.where("name like ?", "%" + params[:name] + "%") if params[:name]
products.where("price >= ?", params[:price_gt]) if params[:price_gt]
products.where("price <= ?", params[:price_lt]) if params[:price_lt]
products
end

def self.scope_builder
DynamicDelegator.new(scoped)
end

# lib/dynamic_delegator.rb
class DynamicDelegator < BasicObject
def initialize(target)
@target = target
end

def method_missing(*args, &block)
result = @target.send(*args, &block)
@target = result if result.kind_of? @target.class
result
end
end
[/ruby]

Screencast: Validieren mit Rails 3

Rails 3 bietet viel Neues bzgl. Validierungen. Ryan zeigt diese Woche wie die Neuerungen benutzt und komplexe Validierungen aufgeräumt werden können.

 

Download:

Download (14.4 MB, 9:53)
Alternativer Download für iPod & Apple TV (14.3 MB, 9:53)

 

Resourcen:

 

Quellcode:

[bash]
gem install rails –pre
gem cleanup
rails store
cd store
rails g scaffold user name:string email:string
rake db:migrate
[/bash]

[html]
<!– users/_form.html.erb –>
<%= form_for(@user) do |f| %>
<%= render "shared/error_messages", :target => @user %>

<div class="field">
<%= f.label :name %><%= mark_required(@user, :name) %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %><%= mark_required(@user, :email) %><br />
<%= f.text_field :email %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>

<!– shared/_error_messages.html.erb –>
<% if target.errors.any? %>
<div id="errorExplanation">
<h2><%= pluralize(target.errors.count, "error") %> prohibited this record from being saved:</h2>
<ul>
<% target.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
[/html]

[ruby]
# application_helper.rb
def mark_required(object, attribute)
"*" if object.class.validators_on(attribute).map(&:class).include? ActiveModel::Validations::PresenceValidator
end

# models/user.rb
validates :email, :presence => true, :uniqueness => true, :email_format => true

# lib/email_format_validator.rb
class EmailFormatValidator < ActiveModel::EachValidator
def validate_each(object, attribute, value)
unless value =~ /^([^@s]+)@((?:[-a-z0-9]+.)+[a-z]{2,})$/i
object.errors[attribute] << (options[:message] || "is not formatted properly")
end
end
end
[/ruby]

Screencast: Einführung Devise

Devise ist ein Authentifizierungslösung welche jegliche Controller-Logik als auch Views abdeckt. Im dieswöchigen Screencast könnt ihr sehen wie es eingesetzt werden kann.

 

Download:

Download (32.2 MB, 10:36)
Alternative Download fÜr iPod & Apple TV (26.8 MB, 10:36)

 

Resourcen:

 

Quellcode:

[bash]
bundle install
rails generate devise_install
rails generate devise User
rake db:migrate
rake routes
[/bash]

[ruby]
# Gemfile
gem ‚devise‘, ‚1.1.rc0‘

# config/environments/development.rb
config.action_mailer.default_url_options = { :host => ‚localhost:3000‘ }

# models/user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :lockable, :timeoutable, :confirmable and :activatable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable

# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation
end

# migration
class DeviseCreateUsers < ActiveRecord::Migration
def self.up
create_table(:users) do |t|
t.database_authenticatable :null => false
# t.confirmable
t.recoverable
t.rememberable
t.trackable
# t.lockable :lock_strategy => :failed_attempts, :unlock_strategy => :both

t.timestamps
end

add_index :users, :email, :unique => true
# add_index :users, :confirmation_token, :unique => true
add_index :users, :reset_password_token, :unique => true
# add_index :users, :unlock_token, :unique => true
end

def self.down
drop_table :users
end
end

# migration
create_table(:users) do |t|
t.database_authenticatable :null => false
# t.confirmable
t.recoverable
t.rememberable
t.trackable
# t.lockable :lock_strategy => :failed_attempts, :unlock_strategy => :both

t.timestamps
end

add_index :users, :email, :unique => true
# add_index :users, :confirmation_token, :unique => true
add_index :users, :reset_password_token, :unique => true
# add_index :users, :unlock_token, :unique => true
[/ruby]

[html]
<!– layouts/application.html.erb –>
<div id="user_nav">
<% if user_signed_in? %>
Signed in as <%= current_user.email %>. Not you?
<%= link_to "Sign out", destroy_user_session_path %>
<% else %>
<%= link_to "Sign up", new_user_registration_path %> or <%= link_to "sign in", new_user_session_path %>
<% end %>
</div>
[/html]

Screencast: ERB Blöcke in Rails 3

In Rails 3 Beta 2 hat sich die Verwendung von Blöcken in ERB Templates geändert. Ryan zeigt in dieser Woche wie sie benutzt werden können.

 

Download:

Download (21.2 MB, 9:41)
Alternativer Download für iPod & Apple TV (18 MB, 9:41)

 

Resourcen:

 

Quellcode:

[bash]
rvm install ruby-head
rvm ruby-head
gem install rails –pre
bundle install
[/bash]

[ruby]
# Gemfile
gem "rails", "3.0.0.beta2"

# application_helper.rb
def admin_area(&block)
content = with_output_buffer(&block)
content_tag(:div, content, :class => "admin")
end
# or
def admin_area(&block)
content_tag(:div, :class => "admin", &block) if admin?
end
[/ruby]

[html]
<%= form_for @product do |f| %>
<% end %>

<%= div_for @product do %>
<% end %>

<% @comments.each do |c| %>
<% end %>

<% content_for :side do %>
<% end %>

<% cache do %>
<% end %>

<!– products/show.html.erb –>
<%= admin_area do %>
<%= link_to "Edit", edit_product_path(@product) %> |
<%= link_to "Destroy", @product, :confirm => "Are you sure?", :method => :delete %> |
<%= link_to "View All", products_path %>
<% end %>
[/html]

Screencast: Syntax Highlighting

Syntax Highlighting wird die visuelle Aufbereitung von Source-Code genant. Die meisten Texteditoren unterstützen Syntax Highlighting, aber auch Web wird gerne darauf zurückgegriffen um Quellcode lesbarer zu machen. Ryan zeigt diese Woche wie man in Ruby/Rails-Applikationen um Syntax Highlighting bereichern kann.

 

Download:

Download (30.9 MB, 9:09)
Alternativer Download für iPod & Apple TV (24.4 MB, 9:09)

 

Resourcen:

 

Quellcode:

[html]
<%= textilize(coderay(@article.content)) %>
[/html]

[ruby]
# config/environment.rb
config.gem "coderay"
config.gem "RedCloth"

# application_helper.rb
def coderay(text)
text.gsub(/<code( lang="(.+?)")?>(.+?)</code>/m) do
content_tag("notextile", CodeRay.scan($3, $2).div(:css => :class))
end
end

# syntax_benchmark.rb
require "rubygems"
require "benchmark"
require "coderay"
require "uv"

path = __FILE__
content = File.read(__FILE__)

# run it once to initialize
CodeRay.scan("print ‚hello’", "ruby").div(:css => :class)
Uv.parse("print ‚test’", "xhtml", "ruby", true, "amy")

Benchmark.bm(11) do |b|
b.report("coderay") do
50.times { CodeRay.scan(content, "ruby").div(:css => :class) }
end

b.report("ultraviolet") do
50.times { Uv.parse(content, "xhtml", "ruby", true, "amy") }
end

b.report("pygments") do
50.times { `pygmentize -f html "#{path}"` }
end
end
[/ruby]

[css]
.CodeRay {
background-color: #232323;
border: 1px solid black;
font-family: ‚Courier New‘, ‚Terminal‘, monospace;
color: #E6E0DB;
padding: 3px 5px;
overflow: auto;
font-size: 12px;
margin: 12px 0;
}
.CodeRay pre {
margin: 0px;
padding: 0px;
}

.CodeRay .an { color:#E7BE69 } /* html attribute */
.CodeRay .c { color:#BC9358; font-style: italic; } /* comment */
.CodeRay .ch { color:#509E4F } /* escaped character */
.CodeRay .cl { color:#FFF } /* class */
.CodeRay .co { color:#FFF } /* constant */
.CodeRay .fl { color:#A4C260 } /* float */
.CodeRay .fu { color:#FFC56D } /* function */
.CodeRay .gv { color:#D0CFFE } /* global variable */
.CodeRay .i { color:#A4C260 } /* integer */
.CodeRay .il { background:#151515 } /* inline code */
.CodeRay .iv { color:#D0CFFE } /* instance variable */
.CodeRay .pp { color:#E7BE69 } /* doctype */
.CodeRay .r { color:#CB7832 } /* keyword */
.CodeRay .rx { color:#A4C260 } /* regex */
.CodeRay .s { color:#A4C260 } /* string */
.CodeRay .sy { color:#6C9CBD } /* symbol */
.CodeRay .ta { color:#E7BE69 } /* html tag */
.CodeRay .pc { color:#6C9CBD } /* boolean */
[/css]

Screencast: ActionMailer in Rails 3

Auch ActionMailer wurde in Rails 3 neu geschrieben und bietet nun eine einfache Möglicheit es zu benutzen. In der neuen Version baut ActionMail auf dem gem Mail auf. Ryan zeigt diese Woche wie es benutzt werden kann.

 

Download:

Download (27.5 MB, 12:20)
Alternative Download für iPod & Apple TV (16.3 MB, 12:20)

 

Resourcen:

 

Quellcode:

[bash]
rails mailit
cd mailit
rails g scaffold user name:string email:string
rake db:migrate
rails g mailer user_mailer
bundle install
[/bash]

[ruby]
# config/initializers/setup_mail.rb
ActionMailer::Base.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => "railscasts.com",
:user_name => "railscasts",
:password => "secret",
:authentication => "plain",
:enable_starttls_auto => true
}

ActionMailer::Base.default_url_options[:host] = "localhost:3000"
Mail.register_interceptor(DevelopmentMailInterceptor) if Rails.env.development?

# app/mailers/user_mailer.rb
class UserMailer < ActionMailer::Base
default :from => "ryan@railscasts.com"

def registration_confirmation(user)
@user = user
attachments["rails.png"] = File.read("#{Rails.root}/public/images/rails.png")
mail(:to => "#{user.name} <#{user.email}>", :subject => "Registered")
end
end

# users_controller.rb
UserMailer.registration_confirmation(@user).deliver

# Gemfile
gem "mail", "2.1.3"

# lib/development_mail_interceptor.rb
class DevelopmentMailInterceptor
def self.delivering_email(message)
message.subject = "#{message.to} #{message.subject}"
message.to = "ryan@railscasts.com"
end
end
[/ruby]

[html]
<!– views/user_mailer/registration_confirmation.text.erb –>
<%= @user.name %>,

Thank you for registering!

Edit profile: <%= edit_user_url(@user) %>

<!– views/user_mailer/registration_confirmation.html.erb –>
<p><%= @user.name %>,</p>

<p>Thank you for registering!</p>

<p><%= link_to "Edit profile", edit_user_url(@user) %></p>
[/html]

Screencast: Unobtrusive Javascript in Rails 3

Wie in den Vorgängerversionen unterstützt auch Rails 3 bei der Integration von JavaScript. Ryan zeigt diese Woche welche Möglichkeiten Rails 3 bietet.

 

Download:

Download (27.4 MB, 13:18)
Alternativer Download für iPod & Apple TV (17.7 MB, 13:18)

 

Resourcen:

 

Quellcode:

[html]
<!– ujs_example.html –>
<!DOCTYPE html>
<html>
<head>
<title>UJS Example</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
$(function() {
$("#alert").click(function() {
alert(this.getAttribute("data-message"));
return false;
})
})
</script>
</head>
<body>
<h1><a href="#" id="alert" data-message="Hello UJS!">Click Here</a></h1>
</body>
</html>

<!– layouts/application.html.erb –>
<%= javascript_include_tag :defaults %>
<!– or –>
<%= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js", "jquery.rails.js" %>
<%= csrf_meta_tag %>

<!– products/index.html.erb –>
<% form_tag products_path, :method => :get, :remote => true do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>

<div id="products">
<%= render @products %>
</div>
[/html]

[html]
// products/index.js.erb
$("products").update("<%= escape_javascript(render(@products)) %>");
// or
$("#products").html("<%= escape_javascript(render(@products)) %>");
[/html]