Screencast: MetaSearch und MetaWhere

MetaSearch und MetaWhere hilft bei Entwicklung komplexe Abfragen ohne SQL in ActiveRecord zu erstellen. In diesem Screencast wird gezeigt wie es eingesetzt werden kann.

 

Download:

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

 

Resourcen:

 

Quellcode:

[ruby]
# Gemfile
gem "meta_where"
gem "meta_search"

# rails console
Product.where(:price.lt => 5)
Product.where({:price.lt => 5} | {:name.matches => "%video%"})
Product.order(:released_at.desc)
MetaWhere.operator_overload!
Product.where(:price < 5)

# products_controller.rb
def index
@search = Product.search(params[:search])
@products = @search.all
end
[/ruby]

[html]
<!– products/index.html.erb –>
<%= form_for @search do |f| %>
<p>
<%= f.label :name_contains %>
<%= f.text_field :name_contains %>
</p>
<p>
<%= f.label :price_gte, "Price ranges from" %>
<%= f.text_field :price_gte, :size => 8 %>
<%= f.label :price_lte, "to" %>
<%= f.text_field :price_lte, :size => 8 %>
</p>
<p class="button"><%= f.submit "Search" %></p>
<% end %>

<p>
Sort by:
<%= sort_link @search, :name %> |
<%= sort_link @search, :price %> |
<%= sort_link @search, :released_at %>
</p>
[/html]

Screencast: Offline Applikationen Teil 2

In dieser Woche zeigt Ryan in seinem zweiten Teil zu Offline-Applikationen wie z.B. HTML5 Storage, zum speichern von Offline-Daten genutzt werden kann.

 

Download:

Download(27.2 MB, 14:51)
Alternativer Download für iPod & Apple TV(25.1 MB, 14:51)

 

Resourcen:

 

Quellcode:

[bash]
curl https://github.com/jquery/jquery-tmpl/raw/master/jquery.tmpl.js > public/javascripts/jquery.tmpl.js
curl https://github.com/wycats/jquery-offline/raw/master/lib/jquery.offline.js > public/javascripts/jquery.offline.js
curl https://github.com/wycats/jquery-offline/raw/master/lib/json.js > public/javascripts/json.js
[/bash]

[ruby]
# items_controller.rb
respond_to :html, :json

def index
@items = Item.all
respond_with(@items)
end
[/ruby]

[html]
<!– layouts/application.html.erb –>
<%= javascript_include_tag :defaults, "jquery.tmpl", "json", "jquery.offline" %>

<!– items/index.html.erb –>
<script type="text/html" id="item_template">
<li>${item.name}</li>
</script>
<ol id="items">
<li><em>Loading items…</em></li>
</ol>
[/html]

[javascript]
// application.js
$(function() {
if ($.support.localStorage) {
$(window.applicationCache).bind("error", function() {
console.log("There was an error when loading the cache manifest.");
});
if (!localStorage["pendingItems"]) {
localStorage["pendingItems"] = JSON.stringify([]);
}
$.retrieveJSON("/items.json", function(data) {
var pendingItems = $.parseJSON(localStorage["pendingItems"]);
$("#items").html($("#item_template").tmpl(data.concat(pendingItems)));
});
$("#new_item").submit(function(e) {
var pendingItems = $.parseJSON(localStorage["pendingItems"]);
var item = {"data":$(this).serialize(), "item":{"name":$("#item_name").val()}};
$("#item_template").tmpl(item).appendTo("#items");
pendingItems.push(item);
localStorage["pendingItems"] = JSON.stringify(pendingItems)
$("#item_name").val("");
sendPending();
e.preventDefault();
});
function sendPending() {
if (window.navigator.onLine) {
var pendingItems = $.parseJSON(localStorage["pendingItems"]);
if (pendingItems.length > 0) {
var item = pendingItems[0];
$.post("/items", item.data, function(data) {
var pendingItems = $.parseJSON(localStorage["pendingItems"]);
pendingItems.shift();
localStorage["pendingItems"] = JSON.stringify(pendingItems)
setTimeout(sendPending, 100);
});
}
}
}
sendPending();
$(window).bind("online", sendPending);
} else {
alert("Try a different browser.");
}
});
[/javascript]

Screencast: Gravatar

Gravatar ist ein Service, der Benutzern die Möglichkeit gibt öffentlich benutzbare Avartare zum Beispiel in ihren Social Networks zu verwenden. Ryan zeigt diese Woche wie einfach Gravatar in einer Rails-Applikation genutzt werden kann.

 

Download:

Download(13.2 MB, 5:36)
Alternativer Download für iPod & Apple TV(11.2 MB, 5:36)

 

Resourcen:

 

Quellcode:

[ruby]
# application_helper.rb
def avatar_url(user)
if user.avatar_url.present?
user.avatar_url
else
default_url = "#{root_url}images/guest.png"
gravatar_id = Digest::MD5.hexdigest(user.email.downcase)
"http://gravatar.com/avatar/#{gravatar_id}.png?s=48&d=#{CGI.escape(default_url)}"
end
end
[/ruby]

[html]
<!– users/index.html.erb –>
<%= image_tag avatar_url(user) %>
[/html]

Screencast: OmniAuth Teil 1

Die traditionelle Authentifizierung mit einem eigenem System wird immer mehr zur einer Ausnahme. Moderne Webapplikationen bieten daher die Anmeldung über bestehende Dienste wie OpenID, Twitter, Facebook und/oder OAuth an. OmniAuth ist ein Plugin das in Rails-App für diesen Zweck eingesetzt werden kann. Ryan zeigt in im ersten Teil wie es in Devise integriert werden kann.

 

Download:

Download(25.6 MB, 10:52)
Alternativer Download für iPod & Apple TV(22.3 MB, 10:52)

 

Resourcen:

 

Quellcode:

[bash]
bundle install
rails g nifty:scaffold authentication user_id:integer provider:string uid:string index create destroy
rake db:migrate
[/bash]

[ruby]
# Gemfile
gem ‚omniauth‘

# models/user.rb
has_many :authentications

# models/authentication.rb
belongs_to :user

# authentications_controller.rb
def index
@authentications = current_user.authentications if current_user
end

def create
auth = request.env["rack.auth"]
current_user.authentications.find_or_create_by_provider_and_uid(auth[‚provider‘], auth[‚uid‘])
flash[:notice] = "Authentication successful."
redirect_to authentications_url
end

def destroy
@authentication = current_user.authentications.find(params[:id])
@authentication.destroy
flash[:notice] = "Successfully destroyed authentication."
redirect_to authentications_url
end
[/ruby]

[html]
<!– authentications/index.html.erb –>
<% title "Sign In" %>

<% if @authentications %>
<% unless @authentications.empty? %>
<p><strong>You can sign in to this account using:</strong></p>
<div class="authentications">
<% for authentication in @authentications %>
<div class="authentication">
<%= image_tag "#{authentication.provider}_32.png", :size => "32×32" %>
<div class="provider"><%= authentication.provider.titleize %></div>
<div class="uid"><%= authentication.uid %></div>
<%= link_to "X", authentication, :confirm => ‚Are you sure you want to remove this authentication option?‘, :method => :delete, :class => "remove" %>
</div>
<% end %>
<div class="clear"></div>
</div>
<% end %>
<p><strong>Add another service to sign in with:</strong></p>
<% else %>
<p><strong>Sign in through one of these services:</strong></p>
<% end %>

<a href="/auth/twitter" class="auth_provider">
<%= image_tag "twitter_64.png", :size => "64×64", :alt => "Twitter" %>
Twitter
</a>
<a href="/auth/facebook" class="auth_provider">
<%= image_tag "facebook_64.png", :size => "64×64", :alt => "Facebook" %>
Facebook
</a>
<a href="/auth/google_apps" class="auth_provider">
<%= image_tag "google_64.png", :size => "64×64", :alt => "Google" %>
Google
</a>
<a href="/auth/open_id" class="auth_provider">
<%= image_tag "openid_64.png", :size => "64×64", :alt => "OpenID" %>
OpenID
</a>
<div class="clear"></div>
[/html]

[css]
// application.css
.authentications {
margin-bottom: 30px;
}

.authentication {
width: 130px;
float: left;
background-color: #EEE;
border: solid 1px #999;
padding: 5px 10px;
-moz-border-radius: 8px;
-webkit-border-radius: 8px;
position: relative;
margin-right: 10px;
}

.authentication .remove {
text-decoration: none;
position: absolute;
top: 3px;
right: 3px;
color: #333;
padding: 2px 4px;
font-size: 10px;
}

.authentication .remove:hover {
color: #CCC;
background-color: #777;
-moz-border-radius: 6px;
-webkit-border-radius: 6px;
}

.authentication img {
float: left;
margin-right: 10px;
}

.authentication .provider {
font-weight: bold;
}

.authentication .uid {
color: #666;
font-size: 11px;
}

.auth_provider img {
display: block;
}

.auth_provider {
float: left;
text-decoration: none;
margin-right: 20px;
text-align: center;
margin-bottom: 10px;
}
[/css]

Screencast: Simple Form

Simple Form ist ein gem zur Unterstützung bei der Entwicklung von Formularen. In diesem Screencast gibt Ryan einen Überblick wie es eingesetzt werden kann.

 

Download:

Download(14.7 MB, 7:50)
Alternativer Download für iPod & Apple TV(13.7 MB, 7:50)

 

Resourcen:

 

Quellcode:

[bash]
bundle_install
rails g simple_form:install
[/bash]

[html]
<%= simple_form_for @product do |f| %>
<%= f.error_messages %>
<%= f.input :name %>
<%= f.input :price, :hint => "prices should be in USD" %>
<%= f.input :released_on %>
<%= f.association :category, :include_blank => false %>
<%= f.input :rating, :collection => 1..5, :as => :radio %>
<%= f.input :discontinued %>
<%= f.button :submit %>
<% end %>
[/html]

[css]
/* stylesheets/application.css */
.simple_form label {
float: left;
width: 100px;
text-align: right;
margin: 2px 10px;
}

.simple_form div.input {
margin-bottom: 10px;
}

.simple_form div.boolean, .simple_form input[type=’submit‘] {
margin-left: 120px;
}

.simple_form div.boolean label, .simple_form label.collection_radio {
float: none;
margin: 0;
}

.simple_form label.collection_radio {
margin-right: 10px;
margin-left: 2px;
}

.simple_form .error {
clear: left;
margin-left: 120px;
font-size: 12px;
color: #D00;
display: block;
}

.simple_form .hint {
clear: left;
margin-left: 120px;
font-size: 12px;
color: #555;
display: block;
font-style: italic;
}
[/css]

Screencast: Routing in Rails 3

Diese Woche zeigt Ryan wie Routen in Rails 3 funktionieren und wie sie aufgebaut sind.

 

Download:

Download(39.7 MB, 13:22)
Alternativer Download für iPod & Apple TV(32.9 MB, 13:22)

 

Resourcen:

 

Quellcode:

[bash]
git clone git://github.com/rails/rails.git
git checkout v3.0.0
[/bash]

[ruby]
match ‚products‘, :to => ‚products#index‘
# same as
match ‚products‘, :to => ProductsController.action("index")

match ‚products/recent‘
# same as
match ‚products/recent‘, :to =>’products#recent‘, :as => ‚products_recent‘
[/ruby]

Screencast: Resourcen vererben

Vererbte Resourcen können RESTful Controller erheblich vereinfachen, indem Standard-Actions eingesetzt werden. Ryan zeigt diese Woche wie das funktioniert.

 

Download:

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

 

Resourcen:

 

Quellcode:

[ruby]
# Gemfile
gem ‚inherited_resources‘
gem ‚has_scope‘

# products_controller.rb
class ProductsController < InheritedResources::Base
respond_to :html, :xml
has_scope :limit, :default => 8

def create
create! { products_path }
end
end

# reviews_controller.rb
class ReviewsController < InheritedResources::Base
belongs_to :product
actions :index, :new, :create
has_scope :rating

def create
create! { collection_url }
end
end

# models/review.rb
scope :rating, proc { |rating| where(:rating => rating) }
[/ruby]

[text]
# config/locales/en.yml
en:
flash:
actions:
create:
notice: "Your {{resource_name}} has been created!"
[/text]

Screencast: Polling nach Aktualisierungen

Bei häufig aktualisierten Daten auf der Serverseite, ist es hilfreich diese dem Benutzer automatisch anzuzeigen. In diesem Screencast zeigt Ryan wie dies mit JQuery gelöst werden kann.

 

Download:

Download(23.2 MB, 16:07)
Alternativer Download für iPod & Apple TV(22.3 MB, 16:07)

 

Resourcen:

 

Quellcode:

[bash]
bundle install
rails g jquery:install
[/bash]

[ruby]
# Gemfile
gem ‚jquery-rails‘

# comments_controller.rb
def index
@comments = Comment.where("article_id = ? and created_at > ?", params[:article_id], Time.at(params[:after].to_i + 1))
end
[/ruby]

[html]
<!– layouts/application.html.erb –>
<%= javascript_include_tag :defaults %>
<%= csrf_meta_tag %>

<!– articles/show.html.erb –>
<div id="article" data-id="<%= @article.id %>">

<div class="comment" data-time="<%= comment.created_at.to_i %>">

<!– comments/index.js.erb –>
<% unless @comments.empty? %>
$("#comments").append("<%=raw escape_javascript(render(@comments)) %>");
$("#article h2").text($(".comment").length + " comments");
<% end %>
[/html]

Screencast: Sortierbare Tabellen

Ryan zeigt in diesem Screencast wie Tabellen auf- und absteigend sortiert werden können.

 

Download:

Download(16.2 MB, 10:52)
Alternativer Download für iPod & Apple TV(15.4 MB, 10:52)

 

Resourcen:

 

Quellcode:

[ruby]
class ProductsController < ApplicationController
helper_method :sort_column, :sort_direction

def index
@products = Product.order(sort_column + " " + sort_direction)
end

# …

private

def sort_column
Product.column_names.include?(params[:sort]) ? params[:sort] : "name"
end

def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
end
end

# application_helper.rb
def sortable(column, title = nil)
title ||= column.titleize
css_class = column == sort_column ? "current #{sort_direction}" : nil
direction = column == sort_column && sort_direction == "asc" ? "desc" : "asc"
link_to title, {:sort => column, :direction => direction}, {:class => css_class}
end
[/ruby]

[html]
<!– products/index.html.erb –>
<tr>
<th><%= sortable "name" %></th>
<th><%= sortable "price" %></th>
<th><%= sortable "released_at", "Released" %></th>
</tr>
[/html]

[css]
/* application.css */
.pretty th .current {
padding-right: 12px;
background-repeat: no-repeat;
background-position: right center;
}

.pretty th .asc {
background-image: url(/images/up_arrow.gif);
}

.pretty th .desc {
background-image: url(/images/down_arrow.gif);
}
[/css]

Screencast: Subdomains in Rails 3

Seit Rails 3 ist es nun möglich Subdomains ohne zusätzliche Plugins zu benutzen bzw. einzusetzen. Ryan zeigt diese Woche wie.

 

Download:

Download(18.8 MB, 13:55)
Alternativer Download für iPod & Apple TV(18.5 MB, 13:55)

 

Resourcen:

 

Quellcode:

[ruby]
# routes.rb
constraints(Subdomain) do
match ‚/‘ => ‚blogs#show‘
end

# lib/subdomain.rb
class Subdomain
def self.matches?(request)
request.subdomain.present? && request.subdomain != "www"
end
end

# app/helpers/url_helper.rb
module UrlHelper
def with_subdomain(subdomain)
subdomain = (subdomain || "")
subdomain += "." unless subdomain.empty?
[subdomain, request.domain, request.port_string].join
end

def url_for(options = nil)
if options.kind_of?(Hash) && options.has_key?(:subdomain)
options[:host] = with_subdomain(options.delete(:subdomain))
end
super
end
end

# application_controller.rb
include UrlHelper

# config/initializers/session_store.rb
# requires Rails 3.0 RC or head
Rails.application.config.session_store :cookie_store, :key => ‚_blogs_session‘, :domain => :all

# change top level domain size
request.domain(2)
request.subdomain(2)
Rails.application.config.session_store :cookie_store, :key => ‚_blogs_session‘, :domain => "example.co.uk"
[/ruby]

[html]
<!– blogs/index.html.erb –>
<%= link_to blog.name, root_url(:subdomain => blog.subdomain) %>

<!– blogs/show.html.erb –>
<%= link_to "All Blogs", root_url(:subdomain => false) %>
[/html]