Linksammlung KW 06+07 2011
Und schon wieder Freitag… keine Zeit… gespeicherte Links der letzten 2 Wochen raussuchen, Blogeintrag schreiben und schnell weiter an sovido arbeiten.
Ruby + Rails
- CSS3, HTML5 and how to degrade gracefully.
- ComfortableMexicanSofa - a powerful micro CMS for Ruby on Rails 3 applications
- Travis – a distributed build server tool for the Ruby community
Webdev
- Is IE9 a modern browser?
- How To Create a Cool Animated Menu with jQuery
- Mockingbird - a fast and friendly rapid wireframing tool
Sonstiges
Code Schnipsel
%table#videos
%thead
%tr
%th Heading 1
%th Heading 2
%tbody
- @videos.each do |video|
%tr.video{:id => "video-#{video.id}"}
%td Info 1
%td Info 2
%tr.video-details{:id => "video-details-#{video.id}"}
%td{:colspan => 2}
%p= video.to_yaml
:css
.video-details { display:none; }
.video-details td { padding: 0 1em; }
.hover { background: #ddd; }
:javascript
$(document).ready(function(){
$(".video").hover(function () {
$(this).css("cursor", "pointer");
$(this).addClass("hover");
}, function () {
$(this).removeClass("hover");
});
$(".video").click(function(event){
$(this).next("tr").toggle();
});
});
Awesome Feature Suggest 1
Ich habe mich am Sonntag mit einem Artikel von der Seite Tutorialzine befasstet. Das Tutorial beschreibt den Aufbau einer simplen Feature Request App mit PHP, MySQL und jQuery.
Da ich noch nicht direkt ein Projekt mit Rails 3 entwickeln konnte, habe ich mich entschlossen den Ansatz von Tutorialzine aufzunehmen und eine kleine Rails 3 app zu schreiben, nur BESSER!
Du brauchst für mein Tutorial RVM!
rails new suggest
echo "rvm ruby-1.9.2@suggest --create" > suggest/.rvmrc
cd suggest
================================================================
= Trusting an .rvmrc file means that whenever you cd into the =
= directory RVM will excecute this .rvmrc script in your shell =
= =
= Now that you have examined the contents of the file, do you =
= wish to trust this .rvmrc from now on? =
================================================================
(yes or no) > yes
Wir werden aufgefordert die angelegte .rvmrc zu vertrauen, was natürlich der Fall ist, denn wir wollen ein seperates gemset für unsere neue app anlegen.
Für unser SCM nutzen wir natürlich git. Ich persönlich verfolge den Ansatz von git-flow und initialisiere somit meinen branches mit:
git flow init
No branches exist yet. Base branches must be created now.
Branch name for production releases: [master]
Branch name for "next release" development: [develop]
How to name your supporting branch prefixes?
Feature branches? [feature/]
Release branches? [release/]
Hotfix branches? [hotfix/]
Support branches? [support/]
Version tag prefix? []
Sofern nicht anders benötigt, einfach ENTER drücken ;) Jetzt checken in welchen branch wir uns befinden:
git branch
* develop
master
Wir sehen, dass wir uns jetzt im develop branch befinden.
git add .
git commit -a -m "initial commit"
bundle
Zunächst den initial commit ausführen und als nächstes bundeler laufen lassen, damit wir in unserem frischen gemset auch alle benötigten gems haben.
Okay, das Projekt ist soweit um Modelle anzulegen. Fangen wir mit den suggestions an.
rails generate model suggestion suggestion:string votes_up:integer votes_down:integer rating:integer
rake db:migrate
git add .
git commit -a -m "adding suggestion model"
Füllen wir das model app/models/suggestion.rb mit Leben:
class Suggestion < ActiveRecord::Base
before_create :set_rating
validates :suggestion, :presence => true
validates :suggestion, :uniqueness => true
def vote_up
self.update_attributes({
:votes_up => self.votes_up.to_i+1,
:rating => self.rating.to_i+1
})
end
def vote_down
self.update_attributes({
:votes_down => self.votes_down.to_i+1,
:rating => self.rating.to_i-1
})
end
private
def set_rating
self.rating, self.votes_up, self.votes_down = 0, 0, 0
end
end
Die beiden Methoden vote_up und vote_down erleichtern später die Auswertung. Mit der Methode set_rating initialisiere ich explizit vor dem Erstellen des Models die Wertungsattribute. Zusätzlich spendiere ich dem model die Validierung auf Vorhandensein und Einmaligkeit des Attributs suggestion.
Das sind schon viele Kleinigkeiten, die wir dem Model auftragen zu beherzigen, aber passt das auch? Um z.B. die Validierungen zu testen, könnten wir folgenden Unit Test schreiben:
require 'test_helper'
class SuggestionTest < ActiveSupport::TestCase
fixtures :suggestions
test "suggestion attributes must not be empty" do
suggestion = Suggestion.new
assert suggestion.invalid?
assert suggestion.errors[:suggestion].any?
end
test "suggestion is not valid without a unique suggestion" do
suggestion = Suggestion.new(:suggestion => suggestions(:rails).suggestion)
assert !suggestion.save
assert_equal "has already been taken", suggestion.errors[:suggestion].join('; ')
end
end
rails:
suggestion: Create a Ruby on Rails Tutorial
votes_up: 0
votes_down: 0
rating: 0
blog:
suggestion: Add new blog entry
votes_up: 0
votes_down: 0
rating: 0
Und was sagt unser Unit Test dazu?
rake test:units
Started
..
Finished in 0.194499 seconds.
2 tests, 4 assertions, 0 failures, 0 errors, 0 skips
Sauber, 2 tests, 4 assertions und keine Fehler. So kann das weitergehen. Also, Quellcode commiten und einen Controller für unser Model mit einer index action anlegen. Außerdem arbeite ich gerne mit haml und jquery, daher packe ich sie in das gemfile und starte bundler. Danach hole ich mir jQuery in das Projekt (rails.js muss überschrieben werden) und “verschiebe” das application .erb layout nach .haml.
git commit -a -m "validating unique not empty suggestion"
rails g controller suggestions index
echo "gem 'haml'" >> Gemfile
echo "gem 'jquery-rails', '>= 0.2.6'" >> Gemfile
bundle
rails generate jquery:install --ui
mv app/views/layouts/application.html.erb app/views/layouts/application.html.haml
Hier nun der Inhalt für das application haml layout:
!!! 5
%html
%head
%meta{'http-equiv' => 'Content-Type', :content => 'text/html; charset=utf-8'}/
%title Suggest
= stylesheet_link_tag :all
= javascript_include_tag :defaults
= csrf_meta_tag
%body
#page
#heading.rounded
%h1
Feature Suggest
%i for Tutorialzine.com
= yield
Der Inhalt vom Controller app/controllers/suggestions_controller.rb :
class SuggestionsController < ApplicationController
before_filter :load_suggestions
def index
@suggestion = Suggestion.new
end
def create
@suggestion = Suggestion.new(params[:suggestion])
respond_to do |wants|
if @suggestion.save
wants.html { redirect_to root_path }
else
wants.html { render :action => "index" }
end
end
end
private
def load_suggestions
@suggestions = Suggestion.order("rating DESC")
end
end
rm public/index.html
mv app/views/suggestions/index.html.erb app/views/suggestions/index.html.haml
touch public/stylesheets/styles.css
Das CSS und die Bilder habe ich mir bei dem Artikel von tutorialzine.com ausgeliehen. Das Css kommt in die public/stylesheets/styles.css, die Bilder in den Ordner public/images/
Der Inhalt der routes.rb :
Suggest::Application.routes.draw do
resources :suggestions
root :to => "suggestions#index"
end
Der Inhalt vom index View app/views/suggestions/index.haml :
%ul.suggestions
- @suggestions.each do |suggestion|
= render :partial => 'suggestion', :locals => {:suggestion => suggestion}
= form_for @suggestion, :as => :suggestion, :url => suggestions_path, :html => { :id => "suggest" } do |f|
%p
= f.text_field :suggestion, :id => "suggestionText", :class => "rounded"
= f.submit "Submit", :disable_with => 'Submiting...', :id => "submitSuggestion"
Die Aktivität/Inaktivität der suggestion definiere ich vorerst aus Der Inhalt vom Partial suggestion app/views/suggestions/_suggestion.haml :
%li{:id => "s_#{suggestion.id}"}
%div{:class => "vote #{inactive ? 'inactive' : 'active'}"}
%span.up
%span.down
.text= suggestion.suggestion
.rating= suggestion.rating
Als nächstes können wir funktionalen Test erstellen um den Controller zu überprüfen:
require 'test_helper'
class SuggestionsControllerTest < ActionController::TestCase
test "should get index" do
get :index
assert_response :success
assert_select "#page ul.suggestions li", 2
assert_tag "form", :attributes => {:action => "/suggestions", :method => "post" }
end
test "should create suggestion" do
assert_difference('Suggestion.count', 1) do
post :create, :suggestion => {:suggestion => "Create functional tests"}
end
assert_redirected_to root_path
end
test "should not create suggestion" do
assert_difference('Suggestion.count', 0) do
post :create, :suggestion => {:suggestion => "Create a Ruby on Rails Tutorial"}
end
assert_template :index
end
end
rake test:functionals
Started
...
Finished in 0.316923 seconds.
3 tests, 7 assertions, 0 failures, 0 errors, 0 skips
Okay, wir können sicher sein, dass unser Controller macht, was er tun soll.
Bevor ich hier die 300 LOC Grenze für einen Blogeintrag überschreite, werde ich den suggestion_votes und der meiner awsome Variante des Feature Requests jeweils einen eigenen Blogeintrag widmen.
Linksammlung KW05 2011
Rails
Seit einigen Wochen habe ich mich nicht getraut den folder “rubyonrails” in meinem google reader abzuarbeiten. Das hat dazu geführt, dass sich dort so
Einges angesammelt hat. Nun der Versuch dem Haufen Herr zu werden. Dies sind die Ergebnisse meiner Aufräumaktion:
- easy_translate: Google (bulk) Translate in Ruby
Einfaches gem für die die neue Google Translate V2 API - Delivering email with Amazon SES in a Rails 3 app
Amazon hat seinen Simple Email Service (SES) gestartet. Hier die Infos um SES in seine Rails app zu integrieren. - Lee Edwards - Visit to Olin College
Eine nette Linksammlung über Agile Development, TDD, Git, Ruby, Rails & popular gems - Getting Started with Rails 3: Part 1
- Getting Started with Rails 3: Part 2
2 Posts über die Erstellung einer Rails app zu Thema “URL shortener” - A git-flow screencast
Ich persönlich nutze für mein Projekt auch git-flow und kann es nur empfehlen. Besonders hotfixes lassen sich einfach umsetzen, wenn man gerade an einem feature arbeitet. Hier ein passender Screencast zum Thema git-flow. - Setting Up And Testing Devise – Delicious Clone
Ein weiterer Screencast, diesmal zu Thema Einrichtung und Testen von Devise - RVM and Passenger setup for Rails 2 and Rails 3 apps
Howto um den Passenger mit RVM zu nutzen. Hilfreich, wenn man sein Projekt von Rails 2 auf Rails 3 uppen will. - Front-end Maintainability with Sass and Style Guides
Tips und Tricks für die Einbindung von HAML und SASS in dem eigenen Projekt. - Rails 3 Remote Links and Forms: A Definitive Guide
- Rails 3 Remote Links and Forms Part 2: Data-type (with jQuery)
2 Rails 3 AJAX Guides - Introducing RailsInstaller
Engine Yard hat einen RailsInstaller für Windows rausgebracht. Klingt interessant. - Beginning Rails testing
Für alle, die ihre Rails apps immer noch nicht testen… - DIY @font-face web service
Kurze Einführung von font-face und die Einrichtung eines eigenen Services.
jQuery/JavaScript
- jQuery Mobile Alpha 3 Released
Ich finde, dass das jQuery mobile framework relativ simpel einsetzbar ist und einen echten Mehrwert für die mobile Version‚ einer Website/app bietet. - Converting jQuery Code to a Plugin
Es ist relativ simpel ein jQuery Plugin zu erstellen, daher sollte man sich überlegen seinen häufiger genutzen jQuery Code einfach in ein Plugin umzuwandeln. - treesaver: HTML5, JavaScript library for creating magazine style layouts for iPad and web
Habe ich noch nicht benutzen können, fand das aber eine tolle Idee.
Linux
- PirateBox
Das Prinzip der PirateBox ist es überall und jederzeit einen freien und offenen Dateiaustausch zu ermöglichen. Würde mich nicht wundern, wenn auf den nächsten Camps solche Piratenboxen rumstehen ;) - ROCKIGER OS 10.04
Ich finde die Idee gut und werde demnächst meinen alten Laptop mit Rockiger OS ausstatten, mal gucken, ob es hält, was es verspricht…
Mac
- AppCleaner
Kennt bestimmt schon jeder. War mir neu und ist eine ganz klar Empfehlung für jeden Mac User. - LiveView for iPhone & iPad
Wie sieht eigentlich mein Design auf dem iPad oder iPhone aus? Mit dieser Kombination aus iPhone/iPad App und OSX Programm kann der aktuelle Bildschirmausschnitt auf das iDevice angeschaut werden. - Syncing Socialite across multiple Macs (using Dropbox)
Cooles Tutorial von Dennis um seine Programme zwischen mehreren Rechnern zu syncen, wenn die Apps dieses von Haus aus nicht können/wollen.
Freelancer Tips
Hier einige Tipps wie man sein Leben führen sollte ;) Einige coole Ideen kann man schon mitnehmen und für sich anwenden.
- Startups, Think Again: Writing Code Is Not Your Biggest Challenge
- Excellent Ideas to Having a Positive Outcome to Your Website
- How to Hack Your Brain
- 6 Time-Tested Applications for Freelance Web Designers
Sonstiges
Diese beiden Sachen haben keine Kategorie gefunden, sollten aber erwähnt werden
Linksammlung KW03 2011
- 8 useful sites for web developers
- Head JS script loader
- Prologue - Generate a Rails 3 app with the application templates
- Setup script to get Ruby and Rails running on Ubuntu with one command
- A Colorful Clock With CSS & jQuery
- How to Make Auto-Advancing Slideshows
- An HTML5 Slideshow w/ Canvas & jQuery
- Drink Rails - Ruby on Rails Blog Links
- Create JavaScript Apps with Backbone.js
Linksammlung KW02 2011
Rails
Hier einige Projekte die interessant sein könnten.
- StillAlive
- Enrichments - Enrichments for a front-end CMS and i18n
- Shortener application that uses MongoDB, cucumber and rspec
- 8 Free Open Source Ruby on Rails Content Management System
RoR E - rails for ecommerce
Leider hab ich das Projekt noch nicht testen können. Klingt aber Vielversprechend, hat das schon jemand Erfahrung mit?
Gmail
Einige Tipps zu Gmail sofern noch nicht bekannt.
Sonstiges
- Set Up and Get to Know Your New Camera
- Internationaler Eventkalender 2011 für Shopbetreiber
- Most Popular iPhone Posts and Free Apps of 2010
WikiLeaks – Rebellen im Netz from netzpolitik on Vimeo.
Magento Ubuntu Nginx Sample Installation
PHP und nginx
PHP5 und nginx installieren:
sudo aptitude install php5-cgi nginx
Erestelle ein PHP5 FastCGI start-up script mit
sudo nano /etc/init.d/php-fastcgi
Folgenden Inhalt einfügen:
#!/bin/bash
BIND=127.0.0.1:9000
USER=www-data
PHP_FCGI_CHILDREN=15
PHP_FCGI_MAX_REQUESTS=1000
PHP_CGI=/usr/bin/php-cgi
PHP_CGI_NAME=`basename $PHP_CGI`
PHP_CGI_ARGS="- USER=$USER PATH=/usr/bin PHP_FCGI_CHILDREN=$PHP_FCGI_CHILDREN PHP_FCGI_MAX_REQUESTS=$PHP_FCGI_MAX_REQUESTS $PHP_CGI -b $BIND"
RETVAL=0
start() {
echo -n "Starting PHP FastCGI: "
start-stop-daemon --quiet --start --background --chuid "$USER" --exec /usr/bin/env -- $PHP_CGI_ARGS
RETVAL=$?
echo "$PHP_CGI_NAME."
}
stop() {
echo -n "Stopping PHP FastCGI: "
killall -q -w -u $USER $PHP_CGI
RETVAL=$?
echo "$PHP_CGI_NAME."
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
*)
echo "Usage: php-fastcgi {start|stop|restart}"
exit 1
;;
esac
exit $RETVAL
Das Startscript ausführbar machen:
sudo chmod +x /etc/init.d/php-fastcgi
PHP starten:
sudo /etc/init.d/php-fastcgi start
(Optional) Beim Booten ausführen:
sudo update-rc.d php-fastcgi defaults
Testen
Trage in der nginx server config folgendes ein:
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/nginx-default$fastcgi_script_name;
include fastcgi_params;
}
nginx neu starten:
sudo /etc/init.d/nginx restart
Erstelle eine Datei in deinem Web-Verzeichnis:
<?php
phpinfo();
?>
Die erstellte Seite im Browser aufrufen. Nun sollte die PHP Info Seite erscheinen.
Magento installieren:
PHP Pakete für Magento installieren:
sudo apt-get install php5-mcrypt php5-curl php5-gd
Limitierung von Ressourcen. Maximalwert des Speichers erhöhen.
sudo nano /etc/php5/cgi/php.ini
memory_limit = 64M;
Magento aus dem SVN importieren:
sudo apt-get install subversion
cd /var/www
svn checkout http://svn.magentocommerce.com/source/branches/1.4
sudo mv 1.4 magento
sudo chown -R www-data magento
Magento Datenbank anlegen und Beispieldaten importieren:
wget http://www.magentocommerce.com/downloads/assets/1.2.0/magento-sample-data-1.2.0.tar.gz
tar xvfz magento-sample-data-1.2.0.tar.gz
cd magento-sample-data-1.2.0
mysqladmin -u root -p create magento
mysql -u root -p magento < magento_sample_data_for_1.2.0.sql
mv media/* /var/www/magento/media/
Server Config anpassen:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request "'
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
autoindex off;
map $scheme $fastcgi_https { ## Detect when HTTPS is used
default off;
https on;
}
keepalive_timeout 10;
gzip on;
gzip_comp_level 2;
gzip_proxied any;
gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# Load config files from the /etc/nginx/conf.d directory
include /etc/nginx/conf.d/*.conf;
}
Magento für nginx einrichten:
server {
listen 80 default;
server_name www.DOMAIN.com *.DOMAIN.com; ## Domain is here twice so server_name_in_redirect will favour the www
root /var/www/vhosts/DOMAIN.com;
location / {
index index.html index.php; ## Allow a static html file to be shown first
try_files $uri $uri/ @handler; ## If missing pass the URI to Magento's front handler
expires 30d; ## Assume all files are cachable
}
location /minify/ { ## Needed for Fooman Speedster
rewrite ^/minify/([0-9]+)(/.*\.(js|css))$ /lib/minify/m.php?f=$2&d;=$1 last;
}
## These locations would be hidden by .htaccess normally
location /app/ { deny all; }
location /includes/ { deny all; }
location /lib/ { deny all; }
location /lib/minify/ { allow all; } ## Deny is applied after rewrites so must specifically allow minify
location /media/downloadable/ { deny all; }
location /pkginfo/ { deny all; }
location /report/config.xml { deny all; }
location /var/ { deny all; }
location /var/export/ { ## Allow admins only to view export folder
auth_basic "Restricted"; ## Message shown in login window
auth_basic_user_file htpasswd; ## See /etc/nginx/htpassword
autoindex on;
}
location /. { ## Disable .htaccess and other hidden files
return 404;
}
location @handler { ## Magento uses a common front handler
rewrite / /index.php;
}
location ~ \.php/ { ## Forward paths like /js/index.php/x.js to relevant handler
rewrite ^(.*\.php)/ $1 last;
}
location ~ \.php$ { ## Execute PHP scripts
expires off; ## Do not cache dynamic content
fastcgi_pass 127.0.0.1:9000;
fastcgi_param HTTPS $fastcgi_https;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params; ## See /etc/nginx/fastcgi_params
}
}
Quellen:
Linksammlung KW50 2010
Die letzen 2 Wochen musste meine Linksammlung ausfallen, da ich mich an türkisblaue Lagunen mit weißen Sand entspannt habe, siehe letze Posts. Ich werde meine Tagestouren in Bangkok und die Erlebnisse auf Phuket und Ko Phi Phi in den demnächst nachholen, aber nun die Linksammlung dieser Woche mit kleinen Einschränkungen, da viel zutun war.
Turnkey administration interface for your Rails apps RailsAdmin bietet ein funktionales Admin-Backend für deine Rails 3 Applikation. Der Blog-Post beschreibt die Nutzung von RailsAdmin mit CanCan von Ryan Bates und einem simplen Rollensystem (is_admin im User-Model). Ich werde RailsAdmin mal in einem kleinen Projekt testen und meine Erfahrungen hier posten.
Another one nginx optimal configuration to use with passenger 3.0 Das gist beschreibt die Installation und Einrichtung von Nginx mit Passanger + SSL Redirect + http headers + passenger settings. Wer mal Nginx mit SSL eingerichtet hat und sich durch die z.T. russische Doku gekämpft hat, findet hier recht übersichtliche Konfigurationsdateien. Das ein oder andere kann man sicherlich übernehmen. Wer dem Russischen mächtig ist, darf mir gerne die Details erklären. Google geht aber auch schon recht gut…
RubyDrop Nachdem DropBox nun endlich 1.0 geworden ist, finde ich diese Projekt auch spannend. RubyDrop ist ein Dropbox Clone mit git als Backend zum Tracken und Synchronisieren. Nachdem ein Remote Git Repository eingerichtet ist, wird in einem definierten Abstand der ausgewählte Ordner mit dem Remote Repository synchronisiert. Weitere Infos entnehmt ihr bitte aus diesem Blog-Post
Ruby on Rails and jQuery: multiselect with checkbox Dieser Post beschreibt die Nutzung von jQuery für eine has_many Relation mit Multi-Select Checkboxen. Kann man immer mal gebrauchen…
Titan kann genutzt werden um Hintergrundprozesse zu erzeugen und zu verwalten.
Virtualize This – Instant Rails in a Virtual Box Wie ich bereites in Linksammlung KW46 2010 erwähnt habe, wird das Vagrant Projekt von EngineYard supported. In dem Post wird die Installation und Nutzung von Vagrant vorgestellt. Ziel ist es dem Nutzer einen Ubuntu Server mit komplette RoR Stack zu liefern.
Phuket
- Patong
- Kamala Beach
- Ko Phi Phi
Bangkok Tag 7
- Fische füttern für Charma
- TukTuk fahren
- Dusit-Palast
- Chatuchak Markt
- MBK/Siam Central
- Chatuchak Markt Feuerwerk
Bangkok Tag 6
- Ko Kret
- Chatuchak Markt
- Cabadges & Condoms