Screencast: JSON Dokumente mit Jbuilder erstellen

Jbuilder (nicht zu verwechseln mit der Java IDE der Firma CodeGear, früher Borland) ist ein Gem zum Erstellen von JSON Dokumenten. Hierzu stellt Jbuilder eine DSL und Template Engines zur Verfügung, mit der auch komplexe Rückgabe-Dokumente erstellt werden können. Ryan zeigt in dieser Woche wie es installiert, integriert und verwendet wird.

 

Downloads in verschiedenen Formaten:

mp4
mp4
webm
ogg

 

Resourcen:

Gemfile

[ruby]
gem ‚jbuilder‘
[/ruby]

views/articles/show.json.builder

[ruby]
json.(@article, :id, :name, :published_at)
json.edit_url edit_article_url(@article) if current_user.admin?

json.author @article.author, :id, :name
# or
json.author do |json|
json.(@article.author, :id, :name)
json.url author_url(@article.author)
end

json.comments @article.comments, :id, :name, :content
# or
json.comments @article.comments do |json, comment|
json.partial! comment
end
[/ruby]

views/comments/_comment.json.jbuilder

[ruby]
json.(comment, :id, :name, :content)
[/ruby]

Screencast: Private Pub für Realtime-Events

Privat Pub ist ein Gem mit dem Echtzeit-Events auf sehr einfach Weise erstellt und genutzt werden können. In diesem Screencast erfahrt ihr wie es in Kombination mit Rails verwendet werden kann.

 

Downloads in verschiedenen Formaten:

mp4
mp4
webm
ogg

 

Resourcen:

Gemfile

[ruby]
gem ‚private_pub‘
[/ruby]

terminal

[bash]
bundle
rails g private_pub:install
rackup private_pub.ru -s thin -E production
[/bash]

messages/index.html.erb

[html]
<%= subscribe_to "/messages/new" %>
[/html]

messages/create.js.erb

[javascript]
<% publish_to "/messages/new" do %>
$("#chat").append("<%= j render(@message) %>");
<% end %>
[/javascript]

messages_controller.rb

[ruby]
PrivatePub.publish_to("/messages/new", message: @message)
[/ruby]

app/assets/javascripts/messages.js.coffee

[javascript]
PrivatePub.subscribe "/messages/new", (data, channel) ->
alert data.message.content
[/javascript]

Screencast: Pretty URLs mit FriendlyId

Benutzerfreundliche URLs erleichtert z.B. Besuchern sprechende Bookmarks zu erstellen oder Optimierungen bzgl. SEO durchzuführen. Das Plugin friendly_id erfüllt die Erstellung von Pretty URLs und bringt zusätzlich noch weitere Features mit. Ryan zeigt wie es installiert und eingesetzt werden kann.

 

Downloads in verschiedenen Formaten:

mp4
m4v
webm
ogg

 

Resourcen:

terminal

[bash]
rails g migration add_slug_to_articles slug:string
rake db:migrate
rails c
rails g friendly_id
[/bash]

rails console

[ruby]
Article.find_each(&:save)
[/ruby]

db/migrate/add_slug_to_articles.rb

[ruby]
add_column :articles, :slug, :string
add_index :articles, :slug
[/ruby]

models/article.rb

[ruby]
class Article < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :slugged

def should_generate_new_friendly_id?
new_record?
end
end

# Or…

class Article < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: :history
end
[/ruby]

Screencast: ElasticSearch Teil 1

ElasticSearch ist eine auf Lucene basierende Suchmaschine. ElasticSearch bietet eine RESTfull Schnittstelle um Suchanfragen zu stellen. Ryan zeigt in diesem ersten Teil wie es in bestehende Applikationen integriert werden kann.

 

Downloads in verschiedenen Formaten:

mp4
m4v
webm
ogg

 

Resourcen:

bash

[bash]
brew install elasticsearch
elasticsearch -f -D es.config=/usr/local/Cellar/elasticsearch/0.18.5/config/elasticsearch.yml
rake db:setup
[/bash]

Gemfile

[ruby]
gem ‚tire‘
[/ruby]

articles_controller.rb

[ruby]
def index
@articles = Article.search(params)
end
[/ruby]

models/article.rb

[ruby]
include Tire::Model::Search
include Tire::Model::Callbacks

def self.search(params)
tire.search(load: true) do
query { string params[:query], default_operator: "AND" } if params[:query].present?
filter :range, published_at: {lte: Time.zone.now}
end
end
[/ruby]

articles/index.html.erb

[html]
<%= form_tag articles_path, method: :get do %>
<p>
<%= text_field_tag :query, params[:query] %>
<%= submit_tag "Search", name: nil %>
</p>
<% end %>
[/html]

Screencast: OmniAuth

OmniAuth ist ein Ruby-Authetifierungs-Framework welches eine standardisierte Schnittstelle zu verschiedenen Authentifizierungs-Providern bietet (z.B. Facebook, OpenID). Mit dem aktuellen OmniAuth-Release 1.0 ist nun auch möglich klassisch über Benutzernamen und Passwort die Authentifizierung durchzuführen, wenn kein externer Anbieter gewünscht oder vorhanden ist. In diesem Screencast zeigt Ryan wie es installiert und verwendet werden kann.

 

Resourcen:

bash

[bash]
rails g model identity name:string email:string password_digest:string
rake db:migrate
rails g controller identities
[/bash]

Gemfile

[ruby]
gem ‚omniauth-identity‘
[/ruby]

config/initializers/omniauth.rb

[ruby]
Rails.application.config.middleware.use OmniAuth::Builder do
# …
provider :identity, on_failed_registration: lambda { |env|
IdentitiesController.action(:new).call(env)
}
end
[/ruby]

models/identity.rb

[ruby]
class Identity < OmniAuth::Identity::Models::ActiveRecord
validates_presence_of :name
validates_uniqueness_of :email
validates_format_of :email, :with => /^[-a-z0-9_+.]+@([-a-z0-9]+.)+[a-z0-9]{2,4}$/i
end
[/ruby]

sessions/new.html.erb

[html]
<p>
<strong>Don’t use these services?</strong>
<%= link_to "Create an account", new_identity_path %> or login below.
</p>

<%= form_tag "/auth/identity/callback" do %>
<div class="field">
<%= label_tag :auth_key, "Email" %><br>
<%= text_field_tag :auth_key %>
</div>
<div class="field">
<%= label_tag :password %><br>
<%= password_field_tag :password %>
</div>
<div class="actions"><%= submit_tag "Login" %></div>
<% end %>
[/html]

routes.rb

[ruby]
resources :identities
[/ruby]

identities_controller.rb

[ruby]
def new
@identity = env[‚omniauth.identity‘]
end
[/ruby]

identities/new.html.erb

[html]
<%= form_tag "/auth/identity/register" do %>
<% if @identity && @identity.errors.any? %>
<div class="error_messages">
<h2><%= pluralize(@identity.errors.count, "error") %> prohibited this account from being saved:</h2>
<ul>
<% @identity.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= label_tag :name %><br>
<%= text_field_tag :name, @identity.try(:name) %>
</div>
<div class="field">
<%= label_tag :email %><br>
<%= text_field_tag :email, @identity.try(:email) %>
</div>
<div class="field">
<%= label_tag :password %><br>
<%= password_field_tag :password %>
</div>
<div class="field">
<%= label_tag :password_confirmation %><br>
<%= password_field_tag :password_confirmation %>
</div>
<div class="actions"><%= submit_tag "Register" %></div>
<% end %>
[/html]

Screencast: Spree – Einstieg in Ecommerce mit Rails

Spree ist eine open-source e-Commerce-Lösung auf Basis von Rails und wurde von Sean Schofield entwickelt. Inzwischen wird es von einer Community gepflegt ist aktuell die meistgenutzte Shop-Lösung im Rails-Umfeld. Ryan bietet diese Woche einen Einstieg in das Framework.

 

Downloads in verschiedenen Formaten:

mp4
m4v
webm
ogg

 

Resourcen:

bash

[bash]
brew install imagemagick
rails new store
bundle
rails g spree:site
rake db:bootstrap
[/bash]

Gemfile

[ruby]
gem ’spree‘, ‚0.70.1‘
gem ’spree_blue_theme‘, :git => ‚git://github.com/spree/spree_blue_theme.git‘
[/ruby]

config/initializers/spree_config.rb

[ruby]
Spree::Config.set(logo: "store/rails.png")
[/ruby]

overrides/logo.rb

[ruby]
Deface::Override.new(:virtual_path => "layouts/spree_application",
:name => "logo",
:replace_contents => "#logo",
:text => "Store")
[/ruby]

app/assets/stylesheets/store/all.css

[css]
/*
*= require store/screen
* …
*/
[/css]

app/assets/stylesheets/store/layout.css.scss

[css]
#logo {
font-size: 32px;
color: #FFF;
}
[/css]

Screencast: Mercury Online Editor

Mercury ist ein auf HTML5 basierender Web-Editor mit dem Inhalte direkt im Browser bearbeitet werden können. In dem folgenden Screencast zeigt Ryan wie es in eigenen Applikationen eingebunden und benutzt werden kann.

 

Downloads in verschiedenen Formaten:

mp4
m4v
webm
ogg

 

Resourcen:

Gemfile

[ruby]
gem ‚mercury-rails‘, git: ‚https://github.com/jejacks0n/mercury.git‘, ref: ‚a2b16bcdc9‘
[/ruby]

bash

[bash]
bundle
rails g mercury:install
rake mercury_engine:install:migrations
rake db:migrate
[/bash]

pages/show.html.erb

[html]
<h1><span id="page_name" class="mercury-region" data-type="editable"><%= raw @page.name %></span></h1>

<div id="page_content" class="mercury-region" data-type="editable">
<%= raw @page.content %>
</div>
<p><%= link_to "Edit Page", "/editor" + request.path, id: "edit_link", data: {save_url: mercury_update_page_path(@page)} %></p>
[/html]

config/routes.rb

[ruby]
resources :pages do
member { post :mercury_update }
end
[/ruby]

pages_controller.rb

[ruby]
def mercury_update
page = Page.find(params[:id])
page.name = params[:content][:page_name][:value]
page.content = params[:content][:page_content][:value]
page.save!
render text: ""
end
[/ruby]

app/assets/javascripts/mercury.js

[javascript]
$(window).bind(‚mercury:ready‘, function() {
var link = $(‚#mercury_iframe‘).contents().find(‚#edit_link‘);
Mercury.saveURL = link.data(’save-url‘);
link.hide();
});

$(window).bind(‚mercury:saved‘, function() {
window.location = window.location.href.replace(//editor//i, ‚/‘);
});
[/javascript]

views/layouts/mercury.html.erb

[html]

saveStyle: ‚form‘,

[/html]

Screencast: Mit PJAX Bereiche aktualisieren

Häfig wird bei kleinsten Änderungen in Teilbereichen einer Seite die gesamte Seite erneut gerendert. Die führt zu „unnötigen“ Seiten-Generierungen die gespart werden können. PJAX kann neue oder aktualisierte Bereiche über AJAX holen und somit die Seite stets aktuell halten. Ryan zeigt diese Woche wie es eingesetzt werden kann.

 

Downloads in verschiedenen Formaten:

mp4
m4v
webm
ogg

 

Resourcen:

Gemfile

[ruby]
gem ‚pjax_rails‘
[/ruby]

app/assets/javascripts/application.js

[javascript]
//= require jquery.pjax
[/javascript]

layouts/application.html.erb

[html]
<div data-pjax-container>
<%= yield %>
</div>
[/html]

index.html.erb

[html]
<title><%= yield(:title) %></div>
[/html]

Gemfile

[ruby]
gem ‚rack-pjax‘
[/ruby]

config/application.rb

[ruby]
config.middleware.use Rack::Pjax
[/ruby]

bash

[bash]
mkdir -p vendor/assets/javascripts
curl https://raw.github.com/defunkt/jquery-pjax/master/jquery.pjax.js > vendor/assets/javascripts/jquery.pjax.js
[/bash]

app/assets/javascripts/application.js

[javascript]
//= require jquery.pjax
[/javascript]

products.js.coffee

[javascript]
jQuery ->
$(‚.product a‘).pjax(‚[data-pjax-container]‘)
[/javascript]

index.html.erb

[html]
<div data-pjax-container>

</div>
[/html]

Screencast: SOAP Webservices mit Savon

Obwohl REST inzwischen für viele die erste Wahl bei Webservices ist, gibt es noch einige Dienste, die aus SOAP aufbauen. Im Gegensatz zu REST ist bei SOAP ein wenig mehr Aufwand nötig, um diese APIs konsumieren zu können. Savon ist ein Plugin um dem Entwicker bei dieser Arbeit zu unterstützen und die Verwendung der Dienste zu vereinfachen. Ryan zeigt in diesem Screencast wie es eingesetzt werden kann.

 

Downloads in verschiedenen Formaten:

mp4
m4v
webm
ogg

 

Resourcen:

Gemfile

[ruby]
gem ’savon‘
[/ruby]

rails console

[ruby]
client = Savon::Client.new("http://www.webservicex.net/uszip.asmx?WSDL")
client.wsdl.soap_actions
client.request :web, :get_info_by_zip, body: { "USZip" => "90210" }
[/ruby]

models/zip_code.rb

[ruby]
class ZipCode
attr_reader :state, :city, :area_code, :time_zone
def initialize(zip)
# Gyoku.convert_symbols_to :camelcase
client = Savon::Client.new("http://www.webservicex.net/uszip.asmx?WSDL")
response = client.request :web, :get_info_by_zip, body: { "USZip" => zip }
if response.success?
data = response.to_array(:get_info_by_zip_response, :get_info_by_zip_result, :new_data_set, :table).first
if data
@state = data[:state]
@city = data[:city]
@area_code = data[:area_code]
@time_zone = data[:time_zone]
end
end
end
end
[/ruby]

Screencast: Abrechnungen in Rails mit Stripe

Abrechnungen werden von verschiedenen Bezahlsystemen angeboten. Je nach Umfang der Anforderungen kann dies ein komplexe Integrationsarbeit erfordern. Stripe versucht an dieser Stelle zu helfen und den gesammten Prozess zu vereinfachen und ist zusätzlich relativ günstig. Ryan zeigt in seinem Screencast wie es installiert und eingesetzt werden kann.

 

Downloads in verschiedenen Formaten:

mp4
m4v
webm
ogg

 

Resourcen:

Gemfile

[ruby]
gem ’stripe‘
[/ruby]

config/initializers/stripe.rb

[ruby]
Stripe.api_key = "tGaNWsIG3Qy6zvXB8wv4rEcizJpSXjF4"
STRIPE_PUBLIC_KEY = "pk_KcSyS2qPWdT5SdrwkQg0vNSyhZgqP"
[/ruby]

layouts/application.html.erb

[html]
<%= javascript_include_tag "https://js.stripe.com/v1/", "application" %>
<%= tag :meta, :name => "stripe-key", :content => STRIPE_PUBLIC_KEY %>
[/html]

subscriptions/new.html.erb

[html]
<%= f.hidden_field :stripe_card_token %>

<div class="field">
<%= f.label :email %>
<%= f.text_field :email %>
</div>
<% if @subscription.stripe_card_token.present? %>
Credit card has been provided.
<% else %>
<div class="field">
<%= label_tag :card_number, "Credit Card Number" %>
<%= text_field_tag :card_number, nil, name: nil %>
</div>
<div class="field">
<%= label_tag :card_code, "Security Code on Card (CVV)" %>
<%= text_field_tag :card_code, nil, name: nil %>
</div>
<div class="field">
<%= label_tag :card_month, "Card Expiration" %>
<%= select_month nil, {add_month_numbers: true}, {name: nil, id: "card_month"} %>
<%= select_year nil, {start_year: Date.today.year, end_year: Date.today.year+15}, {name: nil, id: "card_year"} %>
</div>
<% end %>
<div id="stripe_error">
<noscript>JavaScript is not enabled and is required for this form. First enable it in your web browser settings.</noscript>
</div>
[/html]

app/assets/javascripts/subscriptions.js.coffee

[javascript]

jQuery ->
Stripe.setPublishableKey($(‚meta[name="stripe-key"]‘).attr(‚content‘))
subscription.setupForm()

subscription =
setupForm: ->
$(‚#new_subscription‘).submit ->
$(‚input[type=submit]‘).attr(‚disabled‘, true)
if $(‚#card_number‘).length
subscription.processCard()
false
else
true

processCard: ->
card =
number: $(‚#card_number‘).val()
cvc: $(‚#card_code‘).val()
expMonth: $(‚#card_month‘).val()
expYear: $(‚#card_year‘).val()
Stripe.createToken(card, subscription.handleStripeResponse)

handleStripeResponse: (status, response) ->
if status == 200
$(‚#subscription_stripe_card_token‘).val(response.id)
$(‚#new_subscription‘)[0].submit()
else
$(‚#stripe_error‘).text(response.error.message)
$(‚input[type=submit]‘).attr(‚disabled‘, false)
[/javascript]

controllers/subscriptions_controller.rb

[ruby]
def create
@subscription = Subscription.new(params[:subscription])
if @subscription.save_with_payment
redirect_to @subscription, :notice => "Thank you for subscribing!"
else
render :new
end
end
[/ruby]

models/subscription.rb

[ruby]
attr_accessor :stripe_card_token

def save_with_payment
if valid?
customer = Stripe::Customer.create(description: email, plan: plan_id, card: stripe_card_token)
self.stripe_customer_token = customer.id
save!
end
rescue Stripe::InvalidRequestError => e
logger.error "Stripe error while creating customer: #{e.message}"
errors.add :base, "There was a problem with your credit card."
false
end
[/ruby]

bash

[bash]
rails g migration add_stripe_to_subscriptions stripe_customer_token:string
rake db:migrate
[/bash]