Screencast: Schutz vor XSS in Rails 3

XSS (Cross-Site Scripting), eine Bezeichnung für das Ausnutzen von Sicherheitslücken innerhalb von Webanwendungen, sollte in allen WEB-Applikationen unterbunden werden. Ryan zeigt in dieser Woche welche Änderungen in Rails 3 den Entwickler dabei unterstützt, um von Anfang an mögliche Sicherheitslücken zu vermeiden.

 

Download:

Download (15.7 MB, 8:56)
alternative download for iPod & Apple TV (11.1 MB, 8:56)

 

Resourcen:

 

Quellcode:

[html]
<!– views/comments/_comment.html.erb –>
<div class="comment">
<%= strong link_to(comment.name, comment.url) %>
<p><%= comment.content %></p>
</div>
[/html]

[ruby]
# rails
"foo".html_safe?
safe = "safe".html_safe
safe.html_safe?

# application_helper.rb
def strong(content)
"<strong>#{h(content)}</strong>".html_safe
end
[/ruby]

Screencast: Routes in Rails 3

In Rails 3 wurde das Routing angepasst und in mancher Hinsicht vereinfacht. Ryan zeigt in dieser Woche wie bestehende Routen auf das neue Schema angepasst werden können, und was die neuen Features sind.

 

Download:

Download (30.2 MB, 13:31)
Alternativer Download für iPod & Apple TV (19 MB, 13:31)

 

Resourcen:

 

Quellcode:

[bash]
rails detour
mate detour
rails g controller info about
rails s
[/bash]

[ruby]
Detour::Application.routes.draw do |map|
# map.resources :products, :member => { :detailed => :get }
resources :products do
get :detailed, :on => :member
end

# map.resources :forums, :collection => { :sortable => :get, :sort => :put } do |forums|
# forums.resources :topics
# end
resources :forums do
collection do
get :sortable
put :sort
end
resources :topics
end

# map.root :controller => "home", :action => "index"
root :to => "home#index"

# map.about "/about", :controller => "info", :action => "about"
match "/about(.:format)" => "info#about", :as => :about

match "/:year(/:month(/:day))" => "info#about", :constraints => { :year => /d{4}/, :month => /d{2}/, :day => /d{2}/ }

match "/secret" => "info#about", :constraints => { :user_agent => /Firefox/ }

constraints :host => /localhost/ do
match "/secret" => "info#about"
end

match "/hello" => proc { |env| [200, {}, "Hello Rack!"] }
end
[/ruby]

[html]
<!– info/about.html.erb –>
<%= debug params %>
[/html]

Screencast: ActiveRecord Anfragen in Rails 3

Rails 3 führt ein paar Neuerungen in der Abfrage-Schnittstelle ein. Durch diese Neuerungen wird ActiveRecord schneller und einfacher zu benutzen sein. Ryan zeigt diese Woche wie die neuen Funktionen (incl. named scopes) genutzt werden können.

 

Download:

Download (17.8 MB, 10:43)
Alternativer Download für iPod & Apple TV (13.7 MB, 10:43)

 

Resourcen:

 

Quellcode:

[ruby]
# Article.find( :all, :order => "published_at desc", :limit => 10)
Article.order("published_at desc").limit(10)

# Article.find(:all, :conditions => ["published_at <= ?", Time.now], :include => :comments)
Article.where("published_at <= ?", Time.now).includes(:comments)

# Article.find(:first, :order => "published_at desc")
Article.order("published_at").last

# rails console
Article.all
articles = Article.order("name")
articles.all
articles.first
Article.recent.all
puts Article.recent.to_sql

# articles_controller.rb
@articles = Article.order("name")

if params[:hidden]
@articles = @articles.where(:hidden => (params[:hidden] == "1"))
end

# models/active_record.rb
scope :visible, where("hidden != ?", true)
scope :published, lambda { where("published_at <= ?", Time.zone.now) }
scope :recent, visible.published.order("published_at desc")
[/ruby]

Screencast: Bundler

Fast jede Rails/Ruby-Applikation hat Abhängigkeiten zu Bibliotheken und häufig auch zu einer bestimmten Version. Bundler kann solche Abhängigkeiten lösen und kann somit vieles vereinfachen. Ryan zeigt in dieser Woche wie Bundler eingesetzt werden kann.

 

Download:

Download (17 MB, 9:22)
Alternativer Download für iPod & Apple TV (11.7 MB, 9:22)

 

Resourcen:

 

Quellcode:

[bash]
gem install bundler
bundle install
bundle check
bundle help
bundle install –without=test
bundle lock
bundle install –relock
ls ~/.bundle
bundle pack
ls vendor/cache
[/bash]

[ruby]
gem "rails", "3.0.0.beta"
# gem "rails", :git => "git://github.com/rails/rails.git"

gem "sqlite3-ruby", :require => "sqlite3"

# gem "rspec", :group => :test
group :test do
gem "webrat"
end

gem "will_paginate", ">= 2.3.12"
[/ruby]

Screencast: Rails 3 Beta und RVM

Letzte Woche ist Rails 3.0 erschienen und Ryan hat dies zu dem Thema seines Screencasts für diese Woche gemacht. Neben Rails 3 zeigt er auch wie Ruby 1.9.1 mit RVM installiert und genutzt werden.

 

Download:

Download (32.1 MB, 8:43)
Alternativer Download für iPod & Apple TV (16 MB, 8:43)

 

Resourcen:

Quellcode:

[bash]
ruby -v
mkdir -p ~/.rvm/src/ && cd ~/.rvm/src && rm -rf ./rvm/ && git clone git://github.com/wayneeseguin/rvm.git && cd rvm && ./install
rvm install 1.9.1
rvm list
rvm 1.9.1
rvm 1.9.1 –default
rvm system
gem install tzinfo builder memcache-client rack rack-test rack-mount erubis mail text-format thor bundler i18n
gem install rails –pre
rails topscore
cd topscore
rails server
gem install sqlite3-ruby
rails generate scaffold game name:string
rake db:migrate
[/bash]

Screencast: Rails für mobile Geräte

Der mobile Markt wächst stetig weiter und hat andere Anforderungen an Webapplikationen auf dem mobilen Gerät als für Desktop-Geräte. Ryan zeigt in seinem Screencast wie Rails angepasst werden kann um mobile Geräte zu unterstützen. Dabei kommt mitunter jQTouch zum Einsatz.

 

Download:

Download (55.4 MB, 13:26)
alternative download for iPod & Apple TV (22.4 MB, 13:26)

 

Resourcen:

Quellcode:

[ruby]
# config/initializers/mime_types.rb
Mime::Type.register_alias "text/html", :mobile

# application_controller.rb
before_filter :prepare_for_mobile

private

def mobile_device?
if session[:mobile_param]
session[:mobile_param] == "1"
else
request.user_agent =~ /Mobile|webOS/
end
end
helper_method :mobile_device?

def prepare_for_mobile
session[:mobile_param] = params[:mobile] if params[:mobile]
request.format = :mobile if mobile_device?
end
[/ruby]

[html]
<!– views/layouts/application.html.erb –>
<%= stylesheet_link_tag ‚mobile‘ if mobile_device? %>

<p>
<% if mobile_device? %>
<%= link_to "Full Site", :mobile => 0 %>
<% else %>
<%= link_to "Mobile Site", :mobile => 1 %>
<% end %>
</p>

<!– views/layouts/application.mobile.erb –>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title><%= h(yield(:title) || "Untitled") %></title>
<%= stylesheet_link_tag "/jqtouch/jqtouch.min.css", "/jqtouch/themes/apple/theme.min.css" %>
<%= javascript_include_tag "/jqtouch/jquery.1.3.2.min.js", "/jqtouch/jqtouch.min.js", "mobile" %>
<%= yield(:head) %>
</head>
<body>
<div class="current">
<%- if show_title? -%>
<div class="toolbar">
<%= link_to "Back", nil, :class => "back" unless current_page? root_path %>
<h1><%=h yield(:title) %></h1>
<%= link_to "Full Site", root_url(:mobile => 0), :class => "button", :rel => "external" %>
<%= yield(:toolbar) %>
</div>
<%- end -%>

<% unless flash.empty? %>
<div class="info">
<%- flash.each do |name, msg| -%>
<%= content_tag :div, msg, :id => "flash_#{name}" %>
<%- end -%>
</div>
<% end %>

<%= yield %>
</div>
</body>
</html>

<!– views/projects/index.mobile.erb –>
<% title "Projects" %>

<ul>
<% for project in @projects %>
<li class="arrow">
<%= link_to h(project.name), project %>
<small class="counter"><%= project.tasks.size %></small>
</li>
<% end %>
</ul>

<ul><li class="arrow"><%= link_to "New Project", new_project_path %></li></ul>
[/html]

Screencast: Mehrere Daten gleichzeitig bearbeiten

Mehrere Einträge in Formular gleichtzeitig zu bearbeiten erfordert gewisse Anpassungen bzw. Vorkehrngen. Eine Möglichkeit wie dies gelöst werden kann zeigt Ryan diese Woche in seinem Screencast.

Download

Download (33.6 MB, 13:53)
Alternativer Download für iPod & Apple TV (19.8 MB, 13:53)

Ressourcen:

Quellcode:

[ruby]
# products_controller.rb
def edit_individual
@products = Product.find(params[:product_ids])
end

def update_individual
@products = Product.update(params[:products].keys, params[:products].values).reject { |p| p.errors.empty? }
if @products.empty?
flash[:notice] = "Products updated"
redirect_to products_url
else
render :action => "edit_individual"
end
end

# routes.rb
map.resources :products, :collection => { :edit_individual => :post, :update_individual => :put }
[/ruby]

[html]
<!– views/products/index.html.erb –>
<% form_tag edit_individual_products_path do %>
<table>
<tr>
<th></th>
<th>Name</th>
<th>Category</th>
<th>Price</th>
</tr>
<% for product in @products %>
<tr>
<td><%= check_box_tag "product_ids[]", product.id %></td>
<td><%=h product.name %></td>
<td><%=h product.category.name %></td>
<td><%= number_to_currency product.price %></td>
<td><%= link_to "Edit", edit_product_path(product) %></td>
<td><%= link_to "Destroy", product, :confirm => ‚Are you sure?‘, :method => :delete %></td>
</tr>
<% end %>
</table>
<p>
<%= select_tag :field, options_for_select([["All Fields", ""], ["Name", "name"], ["Price", "price"], ["Category", "category_id"], ["Discontinued", "discontinued"]]) %>
<%= submit_tag "Edit Checked" %>
</p>
<% end %>

<!– views/products/edit_individual.html.erb –>
<% form_tag update_individual_products_path, :method => :put do %>
<% for product in @products %>
<% fields_for "products[]", product do |f| %>
<h2><%=h product.name %></h2>
<%= render "fields", :f => f %>
<% end %>
<% end %>
<p><%= submit_tag "Submit" %></p>
<% end %>

<!– views/products/_fields.html.erb –>
<%= f.error_messages :object_name => "product" %>
<% if params[:field].blank? || params[:field] == "name" %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<% end %>
<% if params[:field].blank? || params[:field] == "price" %>
<p>
<%= f.label :price %><br />
<%= f.text_field :price %>
</p>
<% end %>
<% if params[:field].blank? || params[:field] == "category_id" %>
<p>
<%= f.label :category_id %><br />
<%= f.collection_select :category_id, Category.all, :id, :name %>
</p>
<% end %>
<% if params[:field].blank? || params[:field] == "discontinued" %>
<p>
<%= f.check_box :discontinued %>
<%= f.label :discontinued %>
</p>
<% end %>
[/html]

Screencast: Formulare mit verschachtelten Modellen Teil 2

In dieser Woche geht es weiter mit dem zweiten Teil von Ryans Screencast zu dem Thema „Formulare mit verschachtelten Modellen“. Er wie weitere Felder dynamisch mit JavaScript, über Prototype oder Query, hinzugefügt werden können.

Download:

Download (15.9 MB, 12:40)
alternative download for iPod & Apple TV (20.2 MB, 12:40)

 

Resourcen:

Quellcode:

[html]
<!– _form.html.erb –>
<p><%= link_to_add_fields "Add Question", f, :questions %></p>

<!– _question_fields.html.erb –>
<%= link_to_remove_fields "remove", f %>

<p><%= link_to_add_fields "Add Answer", f, :answers %></p>

<!– _answer_fields.html.erb –>
<%= link_to_remove_fields "remove", f %>
[/html]

[javascript]
// application.js
function remove_fields(link) {
$(link).previous("input[type=hidden]").value = "1";
$(link).up(".fields").hide();
}

function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g")
$(link).up().insert({
before: content.replace(regexp, new_id)
});
}

// application_jquery.js
function remove_fields(link) {
$(link).prev("input[type=hidden]").val("1");
$(link).closest(".fields").hide();
}

function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g")
$(link).parent().before(content.replace(regexp, new_id));
}
[/javascript]

Screencast: Formulare mit verschachtelten Modellen

Fomulare mit verschachtelten Modellen lassen sich viel einfacher mit der Methode accepts_nested_attributes erstellen. Wie diese Methode benutzt werden kann, zeigt Ryan in seinem dieswöchigen Screencast.

Download:

Download (22.4 MB, 11:09)
Alternativer Download für iPod & Apple TV (15.2 MB, 11:09)

 

Resourcen:

Quellcode:

[bash]
rails surveysays
script/generate nifty_layout
script/generate nifty_scaffold survey name:string
script/generate model question survey_id:integer content:text
script/generate model answer question_id:integer content:string
rake db:migrate
[/bash]

[ruby]
# models/survey.rb
class Survey < ActiveRecord::Base
has_many :questions, :dependent => :destroy
accepts_nested_attributes_for :questions, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end

# models/question.rb
class Question < ActiveRecord::Base
belongs_to :survey
has_many :answers, :dependent => :destroy
accepts_nested_attributes_for :answers, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end

# models/answer.rb
class Answer < ActiveRecord::Base
belongs_to :question
end

# surveys_controller.rb
def new
@survey = Survey.new
3.times do
question = @survey.questions.build
4.times { question.answers.build }
end
end
[/ruby]

[html]
<!– views/surveys/_form.html.erb –>
<% form_for @survey do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<% f.fields_for :questions do |builder| %>
<%= render "question_fields", :f => builder %>
<% end %>
<p><%= f.submit "Submit" %></p>
<% end %>

<!– views/surveys/_question_fields.html.erb –>
<p>
<%= f.label :content, "Question" %><br />
<%= f.text_area :content, :rows => 3 %><br />
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "Remove Question" %>
</p>
<% f.fields_for :answers do |builder| %>
<%= render ‚answer_fields‘, :f => builder %>
<% end %>

<!– views/surveys/_answer_fields.html.erb –>
<p>
<%= f.label :content, "Answer" %>
<%= f.text_field :content %>
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "Remove" %>
</p>
[/html]

Screencast: Ryans WebApp Favoriten 2009

Diese Woche zeigt Ryan in seinem Screencast seine Web-App-Favoriten für das Jahr 2009.

Download

Download (22.7 MB, 6:26)
Alternativer Download für iPod & Apple TV (9.3 MB, 6:26)

 

Ressourcen