Today I needed to add a select box for the internationals phone country codes.
This is also known as E.164
I wasn’t able to find a library for that, except for: https://github.com/hexorx/countries that I used as a base and extended this way:
c = ISO3166::Country::Data.map{ |_,v| v["country_code"].to_i }
codes = c.uniq.sort.map{ |v| "+#{v}" }
Now you can use the array in an options_for_select helper
There is a time when every SaaS need to get his money, and maybe you choose to get them month by month.
This is a post about the steps that I took to integrate Paypal recurring payments, and the problems that I run into.
The most common and known library for payment, and the one I was using for instant payment with Paypal is the ActiveMerchant gem, an huge container of all the payment gateway of the galaxy.
The gem is great, until you realize that you need recurring payments….
Some users provided forks with their own implementatios, but there wans’t a clean solution, and some messy code inside a huge library for me was not the way to go.
My Choice:
gem "paypal-recurring", "~> 1.1.0"
Before the integration of the gem is important to understand what we are going to do and why.
I attach an image from the Paypal developer website, that explain all the steps needed for a recurring payment:
WARN: The files in this section are only examples, the code miss some basic security, that can be easly added when integrated in your project.
Using the examples provided by the gem, and a little help from a recent Railscasts I ended up with this integration.
Subscription model: here you can manage the relations with the customers. One customer has many subscriptions, and a subscription belongs to a plan.
class Subscription
Through the paypal method we can access the PaypalPayment model, that manage the code between the gem “paypal-recurring” and our code.
The PaypalPayment module is as follow:
class PaypalPayment
def initialize(subscription)
@subscription = subscription
end
def checkout_details
process :checkout_details
end
def checkout_url(options)
process(:checkout, options).checkout_url
end
def make_recurring
payment = process(:request_payment)
if payment.approved? && payment.completed?
# Set the subscription as paid
end
recurring = process(:create_recurring_profile, {period: :monthly, frequency: 1, start_at: Time.zone.now + 30.days})
@subscription.update_attribute(:paypal_profile_id, recurring.profile_id)
end
def cancel_recurring
ppr = PayPal::Recurring.new(:profile_id => @subscription.paypal_profile_id)
ppr.cancel
end
private
def process(action, options = {})
options = options.reverse_merge(
token: @subscription.paypal_token,
payer_id: @subscription.paypal_payer_id,
description: @subscription.name,
amount: @subscription.amount,
currency: "USD",
ipn_url: "http://www.example.com" + "/paypal/notifications/#{@subscription.id}"
)
response = PayPal::Recurring.new(options).send(action)
raise response.errors.inspect if response.errors.present?
response
end
end
Checkout details: return some details about the customer that is subscribing to our website, like name and email address.
Checkout url: return the url of paypal where we need to redirect the customer to give us the permission to create a recurring payment.
Make recurring: Create an instant payment, and a recurring profile. Note: The first month is paid with the instant payment, so the recurring start from the next month.
Cancel recurring: Cancel the recurring profile
Everything is glued in the controller
class PaymentsController :notification
before_filter :load_subscription
def checkout
redirect_to @subscription.paypal.checkout_url(
return_url: "http://www.example.com" + "/paypal/review/#{@subscription.id}",
cancel_url: "http://www.example.com" + "/paypal/cancel/#{@subscription.id}"
)
end
def review
@subscription.update_attributes(paypal_token: params["token"], paypal_payer_id: params["PayerID"])
end
def complete
@subscription.paypal.make_recurring
end
def cancel
end
# Manage the paypal IPN
#
def notification
notify = PaypalNotification.new(request.raw_post)
if notify.acknowledge
begin
if notify.complete? && @subscription.amount == notify.amount
# Mark as paid
else
# Mark as error and investigate
end
rescue => e
# Mark as error and investigate
raise
end
end
render :nothing => true
end
private
def load_subscription
@subscription = Subscription.find(params[:id])
end
end
This steps should be enough to integrate paypal into your app. Paypal also provide a sandbox in wich you can create fake account and test that everything is working as expected.
Payment is mostly done in Paypal and model code, the views can be styled to reflect your website aspect and don’t require specific code.
On another post I will show how to manage the IPN with a custom library.
The code in this post can be found in this Gist: https://gist.github.com/4197985
Today I had the need to create a thumbnail, from an image uploaded with Carrierwave, based on the image orientation, landscape or portrait. It was very simple, and I’m going to share with you how I’ve done it. My application is a Rails 3.1, with Carrierwave and MiniMagick. Place inside the initializers folder a file, containing a custom Carrierwave processor config/initializers/carierwave.rb
module CarrierWave
module MiniMagick
def from_orientation(portrait, landscape)
manipulate! do |img|
if img[:width] > img[:height] # Landscape
width, height = landscape
else # Portrait
width, height = portrait
end
img.resize "#{width}x#{height}>"
img
end
end
end
end
version :thumb do
process :from_orientation => [[184, 130], [140, 197]]
end
In this days I’m implementing an analytics system for social media with Redis, so I’ve updated my Chef cookbook repo.
In the “readme” you can find detailed instruction to test the cookbook with Vagrant.
The repo can be found on Github: https://github.com/McRipper/Chef-Cookbooks.
Today I was writing a library to access some API, in the design process I started wondering if in Ruby is possible to use some sort of namespacing on class.
All that I wanted was concatenating methods, like you do on active record objects. I show you the solution that I found:
module Test
module Foo
def bar
@namespace = "bar"
self
end
def bar_quack
puts "Quack!"
end
end
end
module Test
class Base
def initialize
puts "Init!"
end
def method_missing(method, *args)
if @namespace
self.send("#{@namespace}_#{method}", *args)
else
super
end
end
include Test::Foo
end
end
In this way you can do this:
test = Test::Base.new
#=> Init!
test.bar
#=>
test.bar_quack
#=> Quack!
test.bar.quack
#=> Quack!
The code works by implementing a method missing in the Base class, and a namespace method in the module that you want namespaced. All the method in the module must have the format: namespace_method.
Now when you call the namespace method an instance variable is set with the namespace, and self is returned.
Because the method cannot be found method missing is triggered, and is the instance variable is set we send the method with the namestace.
This is a quick way that I foud to achive a prettier way to access mehods. Bye!
Today I started studing the Evernote Api for a new project.
The first thing after reading the website was searching for the gem that provide a wrapper over the Thrift interface of Evernote.
Simple and easy, just add the gem to the Gemfile, bundle install and write a small piece of code inside the project to test api key
Nobody ever said life was easy… The program exit with and error
1.9.3-p0/lib/ruby/gems/1.9.1/gems/thrift-0.8.0/lib/thrift/transport/http_client_transport.rb:47:in `initialize': can't convert nil into String (TypeError)
WTF? The error seems to be in the Thrift gem… Let’s start searching on Google. Nobody seems to have the same problem, it must be my fault! Then the idea… Try with another ruby version, I use rbenv to change my ruby version… 1.8.7… No error!
Some Google digging later I find that the problem is with enconding in the new Ruby. A fork of Thrift with the fix is on Github. Good!
Another test and another error: cannot change encoding on frozen String! This seems simple, let’s add a dup on the string… and Done!
Now the example work again with ruby 1.9.3-p0 and 1.9.3-p125
How I make the change? I fork the github project, make the fix and do a pull request… No way! Thrift Github repo contains code for a lot of languages, and I can’t understand how to specify in bundle how to use it!
The idea… “RECREATE ALL THE PRJECTS”. Long story short I’ve recreated the repo for the project. To get yourself up and running without hassle add this to your Gemfile:
gem "evernote", "~> 1.2.0", :git => "git://github.com/McRipper/evernote.git"
gem "thrift", :git => "git://github.com/McRipper/thrift-1.9.3.git"
gem "thrift_client", "~> 0.8.1", :git => "git://github.com/McRipper/thrift_client.git"
I wrote this post to share with the community the hours I’ve spent figuring out this mess. The solution is very ugly and quick, but I think that in the future the various gems will be fixed and this hack can be removed!
Ruby is a great language because some tasks can be achieved in different ways.
The way you choose can be the most readable and beautiful.
Today I want to show you different ways to do a sum on values returned from different methods.
def negative
25
end
def positive
25
end
def neutral
50
end
The result that we want is this:
(negative + positive + neutral)
# => 100
First way: collect all the values in an array and then inject + on it. (http://apidock.com/ruby/Enumerable/inject)
%w(negative positive neutral).collect{ |m| send(m) }.inject(:+)
# => 100
Or: pass to the inject method the values that we want sum to be initialized, in this case 0, and a second variable m as the method name.
%w(negative positive neutral).inject(0) {|sum, m| sum + send(m) }
# => 100
That’s all!
To keep my Js code clean with the Rails 3 asset pipeline I remove the require tree from the main application js file, then to load only the file that correspond to the correct controller I created this helper:
Helper
def js_controller
js = []
path = controller.controller_path.split("/")
path.shift
while path.size > 0
js << (["frontend"] << path).join("/")
path.pop
end
return js.reverse
end
Layout
-js_controller.each do |js|
=javascript_include_tag js
Design by Simon Fletcher. Powered by Tumblr.
© Copyright 2010