Waiting for ie, at least 7, but ideally all of them, to die
Tech stuff around computer programming, basically for web development, especially opensource. Topics will go round Ruby on Rails (git gems etc.), Ubuntu (admin and basic shell) and work organization (agile philosophy)
Tuesday, 25 September 2012
Monday, 6 August 2012
The easiest, fastest and safest way to get your ip address
Tuesday, 31 July 2012
Change the db with migrations on the fly
ActiveRecord::Migration.new.add_column :payments, :card_verification, :string, limit: 8 ActiveRecord::Migration.new.execute "full sql here"
Saturday, 14 July 2012
Coffescript rendering
The correct way to render html inside your XHR response in Rails.
app.showFlashMessages('<%=j flash_messages %>')
$('.booking').replaceWith( '<%=j render @booking %>' )
app.myFunction( <%=raw array.map(&:to_json) %> ) # TODO: double check
Monday, 4 June 2012
backtrace_silencers to clean the development log from missing assets
# /config/initializers/backtrace_silencers.rb
Rails.backtrace_cleaner.add_silencer { |line| line =~ /lib\/action_dispatch\/middleware\/static.rb/ } if Rails.env.development?
This simple line will clean up your development log to something like this:
[FTL] ActionController::RoutingError (No route matches [GET] "/assets/ecoologic/rooms/room_tb.png"): actionpack (3.2.5) lib/action_dispatch/middleware/static.rb:62:in `call'
This is only in development (or test?) as you usually don't use the static middleware in staging or production.
Thursday, 17 May 2012
mysql cheatsheet
# Print the query result into a file mysql> select * into outfile '/tmp/new.txt' from users; # show the current database mysql> select database();
Tuesday, 15 May 2012
Thursday, 3 May 2012
get out of the filter bubble
&pws=0to the end of your search URL in the search bar. Useful for SEO.
Disclaimer: You can't get out of all of the filters bubble.
Wednesday, 2 May 2012
define class methods in ruby (private too)
class Item
def self.find(name)
# ...
end
class << self
alias :search :find
end
private_class_method :find # writing it below private is not enough
end
Saturday, 28 April 2012
Friday, 27 April 2012
import a gem list
#!/usr/bin/ruby
gem_list = <<GEM_LIST
actionmailer (2.3.8)
actionpack (2.3.8)
activerecord (2.3.8)
activeresource (2.3.8)
activesupport (2.3.8)
aws-s3 (0.6.3)
barista (1.3.0)
bistro_car (0.2.2)
soap4r (1.5.8)
therubyracer (0.10.2)
will_paginate (2.3.16)
xml-simple (1.1.2)
GEM_LIST
gem_list.split("\n").each do |line|
gem = line.match(/^.+? /).to_s # with a space at the end
versions = line.match(/\(.+\)/) # surrounded by parenthesis
highest_version = line.match(/([\d\.]+)/).to_s
puts `gem install #{gem} -v #{highest_version}`
end
null_store cache for Rails 2
def initialize
super # options parameter has been removed
extend Strategy::LocalCache
end
and this is the call
# config/environments/development.rb require 'vendor/gems/activesupport/cache/null_store.rb' # could also go in environment.rb # [...] config.cache_store = :null_store # In Rails 3 it's simply :null
Update for rails 2.3.18:
Have your file in lib, rather than vendor/gems and have it referenced with full path, something like this:
require "#{Rails.root}/lib/activesupport/cache/null_store.rb"
If every other attempt fail, how about redirecting the cache to dev/null?
config.cache_store = :file_store, "/dev/null"
Thursday, 19 April 2012
Ruby 1.9.2 Goodies
[1,2,3].each_with_object(1).map(&:+)
# => [2, 3, 4]
# Same outcome, even shorter
[1, 2, 3].map(&1.method(:+))
# => [2, 3, 4]
# Thanks to rubyquicktips.com
######## even in 1.8
a = [[1,2,3],[2,3,4],[3,4,5]]
# get the union:
a.inject(a.first) { |f,x| f = f | x } # => [1, 2, 3, 4, 5]
# get the intersection:
a.inject(a.first) { |f,x| f = f & x } => [3]
Wednesday, 4 April 2012
Ruby Koan #183 about scoring project: The Greed Game
Here it goes!
class Greed
def initialize(dice_faces)
@dice_count = count_occurrences_in(dice_faces)
@score = calculate_score!
end
attr_reader :score
def calculate_score!
@score = 0
@score += score_of_triple_1(1000)
@score += score_of_other_triples(100)
@score += score_of_5s(50)
@score += score_of_1s(100)
end
private
def score_of_5s(score)
face_score(5, score)
end
def score_of_1s(score)
face_score(1, score)
end
def score_of_other_triples(score_each)
score_triples score_each, (2..6).to_a
end
# >>>>> here starts the meat
def score_of_triple_1(score)
score if @dice_count[1] >= 3
end
def score_triples(score, faces)
partial_score = 0
@dice_count.each_with_index do |times, face|
next unless faces.include? face
partial_score += score * face if times >= 3
end
partial_score
end
# faces counted in triples are escluded
def face_score(face, score = 0)
times = @dice_count[face]
score * (times % 3)
end
# <<<<< here ends the meat
def count_occurrences_in(dice_faces)
# nil for 0 which is not a face, then the 6 faces
[nil,0,0,0,0,0,0].tap do |occurrences|
dice_faces.each { |face| occurrences[face] += 1 }
end
end
end
def score(dice)
# You need to write this method
Greed.new(dice).score
end
Even considering only "the meat" of my class, the solution on github is still a few lines shorter... Hei, wait, I could implement the sandwitch in score_triple and count_times! I feel like Randy Marshall watching cooking programs!
Monday, 2 April 2012
restrict dates in datepicker with html data attribute
class DateDisabler
constructor: (@only) ->
beforeShowDay: (date) =>
if @only == date.getDate()
[true, 'available', 'This date is a good date']
else
[false, 'unavailable', 'This date is NOT good']
jQuery ->
$('.datepicker').each (i, e) ->
dates = $(e).data('only')
disabler = new DateDisabler dates
$(e).datepicker({beforeShowDay: disabler.beforeShowDay})
and the haml that calls it:
.datepicker{data: {only: 5}}
Please note the fat arrow in the beforeShowDay, I'll have a look at it soon.
Of corse you want it to make it accept an array but that's quite easy and I'm going into it right now.
For more complex solutions I recommend gazay/gon, which I know thanks to this railscast
Sunday, 1 April 2012
Realex RealVault ActiveMerchant implementation
# see: RealVault - Recurring Payments.pdf
module ActiveMerchant::Billing
class RealVault < RealexGateway
# 7. on page 24
URL = 'https://check-doc.cgi'
# 7.1 (Setup a new Payer)
# Create a Profile for a payer using payer‐new
# If the payer exists another one will be stored
# payer is a hash (see self.test)
def send_payer(payer, options = {})
requires! options, :order_id
request = build_payer_new_request payer, options
commit request, URL
end
# 7.2 (Payment method setup)
# Store the Card details using Card‐New
# If the card exists another one will be stored
# card is a ActiveMerchant::Billing::CreditCard
# options is a hash
def send_card(card, options)
requires! options, :order_id
request = build_card_new_request card, options
commit request, URL
end
# see self.test or send_x methods
def store!(payer, card, options)
send_payer_response = send_payer(payer, options)
send_card_response = send_card(card, options) if send_payer_response.success?
{ :success? => (send_payer_response.success? && send_card_response.success?),
:send_payer_response => send_payer_response,
:send_card_response => send_card_response }
end
# ActiveMerchant::Billing::RealVault.test
# will store the payer and the card in the test account
# makes a purchase before as suggested by the doc. to make sure auth is ok
# works out of the box
def self.test
timestamp = Time.new.to_s :number
currency = 'EUR'
firstname = 'John'
surname = 'Smith'
payerref = timestamp
orderid = timestamp
rv = ActiveMerchant::Billing::RealVault.new({:password => "pwd",
:currency => currency,
:rebate => "rebate",
:account => "internettest",
:login => "merchant_id",
:gateway => "Realex"})
card = ActiveMerchant::Billing::CreditCard.new(
:number => 'test_cc_number',
:month => '12',
:year => '2012',
:type => 'visa',
:first_name => firstname,
:last_name => surname,
:verification_value => '123')
payer = { :type => 'Business',
:ref => payerref, # 'smithj01'
:title => 'Mr',
:firstname => firstname,
:surname => surname,
:email => 'jsmith@acme.com',
:company => 'Acme Inc',
:address => {
:line1 => '123 Fake St.',
# :line2
# :line3
:postcode => '3',
:city => 'Hytown',
:county => 'Dunham',
:country => 'Ireland',
:country_code => 'IE'
},
:phonenumbers => {
:home => '55555555',
:work => '+35317433923',
:fax => '+35317893248',
:mobile => '+353873748392',
}
}
options = {:order_id => orderid,
:currency => currency,
:payerref => payer[:ref]}
rv.purchase 777, card, options
rv.store! payer, card, options
# rv.send_payer payer, options
# rv.send_card card, options
end
private
def build_card_new_request(card, options)
action = 'card-new'
timestamp = Time.now.strftime '%Y%m%d%H%M%S' # same as to_s(:number), but not subjected to override
orderid = sanitize_order_id options[:order_id]
chname = "#{card.first_name}#{card.last_name}"
expdate = card.year.to_s[2..3] + card.month.to_s
sha1 = sha1from "#{timestamp}.#{@options[:login]}.#{orderid}...#{options[:payerref]}.#{chname}.#{card.number}"
xml = Builder::XmlMarkup.new :indent => 2
xml.tag! :request, :timestamp => timestamp, :type => action do
xml.tag! :merchantid, @options[:login]
xml.tag! :orderid , orderid
xml.tag! :card do
xml.tag! :ref , card.type + timestamp[3..14]
xml.tag! :payerref, options[:payerref]
xml.tag! :number , card.number
xml.tag! :expdate , expdate
xml.tag! :chname , chname
xml.tag! :type , CARD_MAPPING[card_brand(card).to_s]
xml.tag! :issueno
end
xml.tag! :sha1hash, sha1
end
end
def build_payer_new_request(payer, options)
action = 'payer-new'
timestamp = Time.now.strftime '%Y%m%d%H%M%S' # same as to_s(:number), but not subjected to override
orderid = sanitize_order_id options[:order_id]
sha1 = sha1from "#{timestamp}.#{@options[:login]}.#{orderid}...#{payer[:ref]}"
xml = Builder::XmlMarkup.new :indent => 2
xml.tag! :request, :timestamp => timestamp, :type => action do
xml.tag! :merchantid, @options[:login]
xml.tag! :account , @options[:account]
xml.tag! :orderid , orderid
xml.tag! :payer, :type => payer[:type], :ref => payer[:ref] do
[:title, :firstname, :surname, :company].each do |tag|
xml.tag! tag, payer.send('[]', tag)
end
xml.tag! :address do
address = payer[:address]
[:line1, :line2, :line3, :city, :county, :postcode].each do |tag|
xml.tag! tag, address.send('[]', tag)
end
xml.tag! :country, address[:country], :code => address[:country_code]
end
xml.tag! :phonenumbers do
phonenumbers = payer[:phonenumbers]
[:home, :work, :fax, :mobile].each do |tag|
xml.tag! tag, phonenumbers[tag]
end
end
xml.tag! :email, payer[:email]
xml.tag! :comments do
xml.tag! :comment, nil, :id => 1
xml.tag! :comment, nil, :id => 2
end
end
xml.tag! :sha1hash, sha1
xml.tag! :comments do
xml.tag! :comment, nil, :id => 1
xml.tag! :comment, nil, :id => 2
end
end
xml.target!
end
end
end
Unfortunately even the gem itself needed a slight change, due to constant priority order in Ruby (this wouldn't be necessary in java for example):
# Realex.rb in ActiveMerchant 1.9.4 # commit method in private section - def commit(request) + def commit(request, url = URL)
Saturday, 24 March 2012
Keeping the environment updated
rvm get latest --auto rvm install 1.9.3 gem update --system # 1.3.7 # that's it for downgrading
gem update bundler # which I actually keep in my Gemfile bundle update
Saturday, 17 March 2012
Useful Shell commands in Linux (terminal)
find . -name file_name # path first option without equal grep -rn string . --context=5 # path last # count the lines of ruby ( find ./ -name '*.rb' -print0 | xargs -0 cat ) | wc -l rails -e production rake x:y x:z RAILS_ENV=test # chain tasks and env is loaded only once rails c production --sandbox rails dbconsole -p'whatever' tailf log/development.log | grep -v ECONNREFUSED -E 'Processing|Render|Parameters' # show actions and templates only ssh user@host 'ls -l' scp -C user@host /tmp/db.sql /tmp/db.sql # -C will compress the data over the wire curl -Lk --user user:pwd --data "param1=value1¶m2=value2" http://url service --status-all netstat -an | grep "LISTEN " # check the open ports free -m # check the ram df -H # check the disk curl --user usr:pwd -Lkv --data "param1=value1¶m2=value2" www.url.com/post_here scp -C urs@url:/origin/ destination/
ncdu / # disk usage
Friday, 16 March 2012
Git cheatsheet
# Search for a word in log diff
git log -S"def email_required"
# display branches in activity order
git for-each-ref --sort=-committerdate --format='%(committerdate:short) %(refname)' refs/heads refs/remotes
# checkout previous branch
git checkout -
git checkout @{-1}
# get rid of the latest changes and restore to the sha
git checkout sha1
# undo latest pull
git reset HEAD@{1}
git checkout .
# discard conflicting changes in a dir (after merge)
git co --theirs dir/ # discard their changes
git co --ours dir/ # discard our changes
# stash
git stash save "name of the stash"
git stash apply
git stash help
# checkout a new branch from origin
git checkout -b new origin/new
# tags
git tag "tag-name"
git push --tags
# bisect for debugging
git bisect start
git bisect bad
git co 32c4bf6 # (known good sha)
git bisect good
# create a patch
git format-patch -1 sha1
# and to apply it
git am 0001-commit-name.patch
# ignore a committed file
# add the file to .gitignore
git rm --cache your_file
# ignore the repo
git update-index --assume-unchanged .ruby-version
# delete a remote branch
git push origin --delete branch_name
# rename a branch
git branch -m old_name new_name
# all your commits on any branch in the last x months
git log --pretty=format:"%ad:%h:%B" --date=short --reverse --all --author=erik --since=1.day.ago
# count the lines of code of your app
git ls-files app/ | xargs wc -l
# undo a merge that was already pushed:
git revert -m 1 merge_hash
#
#
Here great post on git tips
.gitignore_global (add .rbenv-gemsets)Here's my git config
Git style guide
Best practices
Monday, 12 March 2012
A Ruby on Rails developer environment
Then you'll need postgres
echo "-d=postgresql --skip-bundle -T" > ~/.railsrc # $ rvm gemset create opera_wbe # $ gem install bundler --no-rdoc --no-riNOTE: the `-T` option will change the `config/application.rb` as this following top group instead of loading `rails/all` (very nice!):
# Pick the frameworks you want:
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie"
require "sprockets/railtie"
# require "rails/test_unit/railtie"
module OperaWbe
class Application < Rails::Application
# migration with numbers (001, 002, ...) in stead of timestamp
config.active_record.timestamped_migrations = false
# in production actually
# prepend assets path
# config.action_controller.asset_host = ASSETS_PATH
# in development actually
# Remove assets logging
config.assets.logger = false # ~only~ one line each asset request
# [...]
Also I find the following files very useful
~/.irbrc # with global functions to call in the console ~/workspace/.rvmrc # which loads my @new gemset ~/workspace/every_app/.rvmrc # with the following...
rvm ruby-1.9.2-p290@new # with bundler and rails only rvm gemdir # show the gemdir everytime you change project
# .irbrc puts 'Using irb console helper functions from ~/.irbrc' # returns the list of methods not inherited from Object # it will not show methods overwritten from `Object.new` # eg: `y ml String.new` def ml(object) (String.public_methods - object.methods).sort endThen my prompt looks like this:
21:43:02-6950 - ~/workspace> cat ~/.bashrc
[...]
# some more ls aliases
alias ll='ls -l'
alias la='ls -A'
alias lo='ls -o'
# colorful, with time, history id and path (also in window title)
# export PS1="\[\e]0;\w\a\]\e[1;36m\t-\! - \w>\e[m "
export PS1="\[\e]0;\w\a\e[1;36m\]\t-\! - \w>\[\e[m\] "
# TODO: git branch in prompt
# ror workspace available everywhere
export CDPATH=$CDPATH':/home/erik/workspace/'
## big bash history
export HISTSIZE=20000
# append all commands to the history file, don't overwrite it at the start of every new session
shopt -s histappend
[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm" # This loads RVM into a shell session.
cd .
And yes, I know, at the moment without without the git branch, it's messing with the color.
echo 'gem: --no-ri --no-rdoc' >~/.gemrc # never install gem docA couple of config for git, get the book here
[color] diff = true status = true branch = true [alias] co = checkoutSetup Sublime Text and customize it as such
Wednesday, 22 February 2012
Scrum, Agile according with @hamids
@hamids has the best introduction video on Scrum I've ever seen.
Sunday, 5 February 2012
blogger sucks
brush list
Configuring redis 2.4.7 on Ubuntu 10.04
TODO: this post is still a draft, if you're a visitor, please move on
* install *
not enough, then:
AAA! maybe I'd avoid adding it to the auto-execution list, which happens with the following command:
sudo update-rc.d redis-server defaults
run it with: sudo /etc/init.d/redis-server start
* customization *
/etc/sysctl.conf
sysctl vm.overcommit_memory=1 # to avoid reboot