Showing posts with label ruby. Show all posts
Showing posts with label ruby. Show all posts

Wednesday, 8 May 2013

regex to update from rspec 1 to rspec 2

Rspec 2 removes assign_to and replace it with assigns, here are the regex I'm using in sublime text 2 for the update:


should assign_to\((.*)\).with\(nil\)
assigns($1).should be_nil

should assign_to\(:(.+)\).with\((.+)\)
assigns(:$1).should == $2

should_not assign_to\(:(.*)\)
assigns(:$1).should be_nil

should assign_to\(:(.*)\)
assigns(:$1).should_not be_nil


Links to some doc here

Sunday, 14 April 2013

quick upload to amazon S3 with Fog and Carrierwave

require 'rubygems'
require 'fog' # version 1.10.1


fog_credentials = {
  provider: "AWS",
  aws_access_key_id: "QWERTTYQWERTTYQWERTT",
  aws_secret_access_key: "q1w2e3r4t5yQWERTYUq1w2e3r4t5yQWERTYasdf1",
  region: "ap-southeast-2" # Sydney ;)
}


CONNECTION = Fog::Storage.new fog_credentials

S3 = CONNECTION.directories.get 'bucket-name'
S3.files.create(key: 'test_me/test1', body: 'xxxxxxxxx')

The following works with Carrierwave
require 'carrierwave'
require 'fog'

CarrierWave.configure do |config|
  config.fog_credentials = {
    provider:              'AWS',
    aws_access_key_id:     'QWERTYQWERTYQWERTYTY',
    aws_secret_access_key: 'qewr1234qewr1234qwer1234qwer1234qwer1234',
    region:                'ap-southeast-2' # Sydney :)
  }
  config.fog_public    = false
  config.fog_directory = 'bucket-name'
end

class MyUploader < CarrierWave::Uploader::Base
  storage :fog
end

file = File.open('/tmp/tmp.txt')
uploader = MyUploader.new
uploader.store!(file)

Monday, 18 March 2013

ruby operator precedence explained with an example

OR has lower precence than ||, in particular assignments (=) are in the middle, therefor:
a = false || true # => true
a                 # => **true**  => a = (false || true)
# BUT
a = false or true # => true
a                 # => **false** => (a = false) or true

# another BIG difference
:a || :b && :c  # => :a          => (:a || :b) && :c
# BUT 
:a or :b and :c # => **c**       => :a or (:b and :c)


Got it?
Where does it make sense to use the English operators?
a = value or raise "a cannot be nil"

def tail_color(args)
  animal = args[:animal] and
  tail = animal.tail and
  tail.color
end


Conclusion: only use English operators for flow control, not in if statements
also see this table

Sunday, 24 February 2013

validates exclusion of controller names when catching all routes

Of course catching all routes is bad, but if you have to:
class Account < ActiveRecord::Base
  INVALID_PAGE_NAMES = Dir[Rails.root.join('app/controllers/*_controller.rb')].map { |path| path.match(/(\w+)_controller.rb/); $1 }
  validates :page_name, :exclusion => { :in => INVALID_PAGE_NAMES,
    :message => "Page %{value} is reserved." }
end

Saturday, 23 February 2013

rials and ruby postcasts and screencasts



Also worth checking

rspec, capybara and factorygirl hints

# spec_helper.rb

# this line will make rpsec end at the first failing test
RSpec.configure do |c|
  c.fail_fast = true
end
# in integration specs

# xpath can be copied from chrome, rx-click on the element (in the dev-tool)
page.should have_xpath("//a[contains(@href,'users')]"), count: num)

rails sandbox tasks

desc 'do not permanently write on the db (good for testing rake tasks)'
task :sandbox => :environment do
  puts "** << USING SANDBOX!! >> **"

  # beginning
  ActiveRecord::Base.connection.increment_open_transactions
  ActiveRecord::Base.connection.begin_db_transaction

  # end
  at_exit do
     ActiveRecord::Base.connection.rollback_db_transaction
     ActiveRecord::Base.connection.decrement_open_transactions
  end    
end

yaml defaults example (postgres on ruby on rails)

postgres:   &postgres
  adapter:  postgresql
  encoding: unicode
  host:     localhost
  username: netengine
  password:

development:
  <<: *postgres
  database: propertyconnect_development

test:
  <<: *postgres
  database: propertyconnect_test

Saturday, 12 January 2013

first post at netengine!

Not the best I've ever done, but I had to write something... A ruby implementation of the OAuth2 protocol for third party roles, enjoy!

http://goo.gl/UbHxI

Saturday, 5 January 2013

extend vs include

I always make confusion, although I'm getting better, this should help:


module MainMod
  module SubMod
    def self.included(cls)
      puts "#{self} included in #{cls}"
      cls.extend ClassMethods
    end

    module ClassMethods
      
      def ext
        puts 'extended'
      end
  
    end
  
    def inc
      puts 'included'
    end

  end
end

class A
  include MainMod::SubMod # => MainMod::SubMod included in A
end

A.new.inc
A.ext

module Mod1
  inc MainMod::SubMod
end

class B
  inc Mod1 # => MainMod::SubMod included in Mod1 !!!(Mod1)
end

B.new.inc
# B.ext # does not exists, `ext` was extended on Mod1

Tuesday, 31 July 2012

Change the db with migrations on the fly

What if you want to add a column though the console with one line of code? (and you exactly know what this implies)
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.

Friday, 27 April 2012

import a gem list

If your project doesn't use Gemfile, paste the wanted gemlist in the GEM_LIST string, run this script and that's it. I know, it could be improved, but that's it by now. NOTE: only the first version of the gem is installed, which is the highest.

#!/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

In Rails 3 you can use a fake cache, very useful in development, this uses ActiveSupport::Cache::NullStore, which is not available for Rails 2, but can be easily integrated with some copy and paste with a little customization.
      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

When I searched the site for koan greed I was not surprised to see 19 answers and though I've seen very performing implementations, I was quite surprised to see that nobody solved the problem with a class(maybe because about_classes was the next set of koans?), which was my first take. I admit I got lost in refactoring before looking for a comparison, but this is just my spare time.
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!

Sunday, 1 April 2012

Realex RealVault ActiveMerchant implementation

The following is the extension of the ActiveMerchant gem that will allow the system to store information about the customer and its credit card in realex, typically this is used for recurring payments (in fact it's the name of the pdf provided by Realex), but in our case the need was for charging customers that don't show up at the hotel. It's not the final refactory.

# 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)