As I am sure many of you have heard Facebook announced their schema to assist with building the semantic web: The Open Graph Protocol. And while Facebook clearly acknowledges they have not done anything particularly new or innovative with it, I think for many simply hearing the concepts and techniques spoken again by a social networking giant signaled the timing is right and we should start to see some real results this time around. So, with all that energy, I drew up my version of the protocol as a ruby implementation to further reinforce and validate my interests in Ruby (again). I’ve been sitting on this code a little while expecting to divine more features for it. However, rather than sitting on it any longer waiting around for the code rot, I thought it best to simply unleash it upon the world complete with rSpec coverage and a single Cucumber feature: Kestrel Open Graph (kog).
To install simply perform:
# Installation of kog sudo gem install kog
Using kog is very simple as illustrated below:
require 'rubygems'
require 'kog'
# Parse a resource and getting the resource
obj = OpenGraph::Parser.parse('http://www.rottentomatoes.com/m/office_space/')
puts obj.class # => OpenGraph::Object
# The object
puts obj.inspect # => #<OpenGraph::Object:0x101b01060 @image="http://images.rottentomatoes.com/images/movie/custom/aa/1087856aa.jpg", @title="Office Space", @url="http://www.rottentomatoes.com/m/office_space/", @site_name="Rotten Tomatoes", @type="movie">
# Accessors
puts obj.type # => movie
puts obj.type?('movie').inspect # => true
puts obj.type?('dog').inspect # => false
That’s it! Now wasn’t that easy?
It took mashing together multiple articles, blog posts, and wikis to put this all together but I finally have a process for hosting a “centralized” shared git repository that honors file permissions for the respective users. The way in which you do this is the following:
On the server:
# Create a git repository sudo mkdir -p /var/git cd /var/git sudo mkdir myproject pushd myproject sudo git init sudo touch .gitignore sudo git add .gitignore sudo git commit -a -m 'Initial import' popd # Clone the bare git components away sudo git clone --bare myproject myproject.git pushd myproject.git # Set the type of shared repository this will be sudo git config core.sharedRepository group popd # Change the file permissions sudo chown -R root:users myproject.git # Replace "users" with your group sudo chmod -R g+ws myproject.git
On the clients:
git clone username@example.com:/var/git/myproject.git
That should be the basics without going a step further and creating a “git” user and group to host the service as. Enjoy!
I’ve been growing a little hungry to dive back into Ruby a bit and the opportunity arose after stumbling on reading about the Collatz Conjecture (of which there is a funny xkcd comic) and finding some spare time on a connecting flight. It basically states that for any number, if you continually divide by two, if even, or multiply by three and add 1, if odd, you will eventually get to 1. All of the intermediate numbers are referred to as the path that make up that number; for example, the number 5 has the following path: [16, 8, 4, 2, 1] where the steps are 5 (x 3 + 1) => 16 (/ 2) => 8 (/ 2) => 4 (/ 2) => 2 (/ 2) => 1. I thought I would have a bit of fun with this and build some utility functions around what you might want to know about two number paths in the collatz conjecture. All of this code was written very hastily but it was fun and killed a couple of hours of boredom stuck on a plane. This is the result:
#!/usr/bin/env ruby
class Collatz
def self.get_convergence_point(number_one, number_two)
self.get_path_intersection(number_one, number_two).first
end
def self.get_path_intersection(number_one, number_two)
# Get the paths
path_one = self.get_path(number_one)
path_two = self.get_path(number_two)
# Return the intersection
path_one & path_two
end
def self.get_path_matrix(number, matrix=Hash.new)
# Get all of the "child" numbers for this number
numbers = self.get_path(number)
# Itterate
numbers.each do |n|
# Save some work
if (matrix[n].nil?)
matrix[n] = self.get_path(n)
# Done
if (n == 1)
return matrix
end
# Recursive
return self.get_path_matrix(n, matrix)
end
end
end
def self.get_step_count(number)
self.get_path(number).length - 1
end
def self.get_path(n, numbers=Array.new)
# Append current itteration
numbers << n
# Done
if (n == 1)
return numbers
end
# Recursive
if(n%2 == 1)
self.get_path((3*n)+1, numbers)
else
self.get_path(n/2, numbers)
end
end
end
## Get some info
matrix_one = Collatz::get_path_matrix(ARGV[0].to_i)
matrix_one_step_count = Collatz::get_step_count(ARGV[0].to_i)
matrix_two = Collatz::get_path_matrix(ARGV[1].to_i)
matrix_path_intersection = Collatz::get_path_intersection(ARGV[0].to_i, ARGV[1].to_i)
matrix_convergence_point = Collatz::get_convergence_point(ARGV[0].to_i, ARGV[1].to_i)
puts matrix_one.inspect
puts matrix_one_step_count.inspect
puts matrix_two.inspect
puts matrix_path_intersection.inspect
puts matrix_convergence_point
## Empty space
puts
puts
## Print "pretty" path
path_one = Collatz::get_path(ARGV[0].to_i)
path_two = Collatz::get_path(ARGV[1].to_i)
path_convergence_point = Collatz::get_convergence_point(ARGV[0].to_i, ARGV[1].to_i)
path_intersection = Collatz::get_path_intersection(ARGV[0].to_i, ARGV[1].to_i)
if path_one.length >= path_two.length
left_path = path_one
right_path = path_two
else
left_path = path_two
right_path = path_one
end
left_path -= matrix_path_intersection
right_path -= matrix_path_intersection
path_intersection.reverse.each do |n|
if (!right_path.empty?)
puts ' ' + n.to_s
else
puts n.to_s
end
end
if (!right_path.empty?)
puts ' / \\'
end
left_path.reverse.each do |x|
next if (x == path_convergence_point)
puts x.to_s + " " + right_path.pop.to_s
end
This yields the output:
$ ruby collatz.rb 7 6
{16=>[16, 8, 4, 2, 1], 5=>[5, 16, 8, 4, 2, 1], 11=>[11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1], 22=>[22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1], 17=>[17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1], 1=>[1], 34=>[34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1], 40=>[40, 20, 10, 5, 16, 8, 4, 2, 1], 7=>[7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1], 2=>[2, 1], 13=>[13, 40, 20, 10, 5, 16, 8, 4, 2, 1], 8=>[8, 4, 2, 1], 52=>[52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1], 20=>[20, 10, 5, 16, 8, 4, 2, 1], 4=>[4, 2, 1], 26=>[26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1], 10=>[10, 5, 16, 8, 4, 2, 1]}
16
{16=>[16, 8, 4, 2, 1], 5=>[5, 16, 8, 4, 2, 1], 6=>[6, 3, 10, 5, 16, 8, 4, 2, 1], 1=>[1], 2=>[2, 1], 8=>[8, 4, 2, 1], 3=>[3, 10, 5, 16, 8, 4, 2, 1], 4=>[4, 2, 1], 10=>[10, 5, 16, 8, 4, 2, 1]}
[10, 5, 16, 8, 4, 2, 1]
10
1
2
4
8
16
5
10
/ \
20 3
40 6
13
26
52
17
34
11
22
7
I take the train each day into work and frequently encounter someone pedeling their wares or passing out flyers as I exit the terminal on my way in to work. This day being no exception I encounter a female lunging at me with something in her hand while demanding “Here!”. I’d been bothered before to take a flyer or newspaper but never have I had anyone be so in my face about it. Naturally I was turned off of whatever she was offering, until I looked down and saw this:
My initial reaction was that someone or some company just might crazy or stupid enough to hand out a hundred dollar bill with a note attached as some sort of whacky marketing campaign so I obliged her offer and took what she offered. Immediately after I took it into my hand the “too good to be true” thought started to creep in so I inspected the dimensions of what I had just received:
A phony! Hey now, that’s not fair! But they already had me. The “money” was already in my hand and I was walking further away from the peddler. Of course my next reaction was to laugh and ask who was so wickedly clever and I discover another, albeit less surprising, find:
Ahhhhh! It’s tax season! And I haven’t done my taxes yet! You bastards!
Update: One other thing I realized is that the depths of cleverness of using a hundred dollar bill as the cover for your leaflet is that if it is tossed on the ground as trash someone else will likely come along and the process repeat itself. Brilliant!
I found that setting up MongoDB to be a session store using MongoMapper was, at first glance, non-obvious: that is, until I discovered devise. At first, I tried (and failed) to setup sessions in authlogic and then moved to the other end of the spectrum and attempted to role my own authentication and session store using this gist as a starting point. While it worked it felt wrong and I foresaw rewriting a ton of features that came for free with most authentication plugins. So, after an even more exhaustive search, I found devise; what a wonderful find! Nothing in devise said it wouldn’t work and I indeed found that to be the case; it was really agnostic to the session store and extremely simple to setup. Since devise is built atop warden.
So lets get started, first off you need to get the required gems and a skeleton app:
sudo gem install ruby-debug mongo mongo_ext mongo_mapper warden devise rails myapp cd myapp rm public/index.html
Setup the environment.rb with some changes we will require:
# config/environment.rb config.gem 'mongo_mapper' config.gem 'devise'
Update the route for the home controller:
# config/routes.rb # devise user definition map.devise_for :users map.resource :user,nly => [:new, :create, :edit, :update] # root map.root :controller => :user, :action => :sign_in
Generate the scaffold for the session and user model:
script/generate devise_install script/generate devise User
Modify the generated user model:
# app/models/user.rb class User include MongoMapper::Document devise :registerable, :authenticatable, :confirmable, :recoverable, :rememberable, :trackable, :validatable end
Sterilize the logs for sensitive information:
# app/controllers/application_controller.rb filter_parameter_logging :password, :password_confirmation
Remove ActiveRecord from the environment:
# config/envrionment.rb config.frameworks -= [ :active_record ]
Replace database.yml with the following:
# config/database.yml development: adapter: mongodb database: myapp-development host: localhost test: adapter: mongodb database: myapp-test host: localhost production: adapter: mongodb database: myapp-production host: localhost
Add mongo_mapper YAML initializer:
# config/initializers/mongo_mapper.rb # load YAML and connect database_yaml = YAML::load(File.read(RAILS_ROOT + '/config/database.yml')) if database_yaml[Rails.env] && database_yaml[Rails.env]['adapter'] == 'mongodb' mongo_database = database_yaml[Rails.env] MongoMapper.connection = Mongo::Connection.new( mongo_database['host']) MongoMapper.database = mongo_database['database'] end
Enable mongo_mapper support for devise:
# config/initializers/devise.rb Devise.setup do |config| config.orm = :mongo_mapper end
You can now startup the server:
script/server -u
Now point your browser to http://127.0.0.1:3000/users/sign_up and sign up for an account.
Use the mongo client to get out the confirmation code:
mongo
> use myapp-development
> db.users.find();
{ "_id" : ObjectId("4c9e9118af5ee501860230004"), "encrypted_password" : "18cf5678ba4ef9d412c3b7bdea48794b7c69ec3a", "created_at" : "Mon Mar 15 2010 18:44:56 GMT-0700 (PDT)", "updated_at" : "Mon Mar 15 2010 19:18:41 GMT-0700 (PDT)", "confirmation_sent_at" : "Mon Mar 15 2010 18:44:56 GMT-0700 (PDT)", "last_sign_in_ip" : null, "current_password" : "abc123", "last_sign_in_at" : null, "sign_in_count" : 0, "password_salt" : "3xyzQfMwJeyAZa9tXYZ2", "remember_token" : "ArStvJ7ABzEkzE_feixT", "reset_password_token" : null, "current_sign_in_ip" : null, "remember_created_at" : null", "confirmation_token" : "C0fuZMksMC7rhOgCxQef", "current_sign_in_at" : null, "email" : "user@example.com", "confirmed_at" : null }
You can now navigate to http://127.0.0.1:3000/users/confirmation?confirmation_token=C0fuZMksMC7rhOgCxQef and confirm the account. Once this is complete you can then goto http://127.0.0.1:3000/users/sign_in to verify that sign is working. Obviously this merely gets you a very bare bones rails app that talks to MongoDB and where I am going to leave it to you. Next steps you will probably want to take will be generating a root controller (e.g. home) and placing links to the sign_in and sign_up pages.
I just read an article from Google which piqued my interest: Google has announced that they will be offering fiber optic broadband as part of an experiment they are running. This sparked one of those moments where a slow chuckle begins to turn into a rumbling thunder of laughter. You see, as a resident of the City of Mountain View (and I am not the only one), I do not trust that Google will get this experiment any more right than they did the wireless experiment here. I found great humor that this article would even mention the WIFI experiment because it has been a complete and utter failure. Furthermore, I would not trust the service level from a Google broadband connection farther than I can throw my Linksys 54G Wireless router.
As you can see, I have 18 access points within reach of my wireless card at this moment. I believe all of these are utilized, not so much because my neighbors are concerned with information security (which arguably they very much are), but from a complete failure of the Google WIFI experiment. I did not even think I had that many neighbors! I could perceive ditching my wireless internet if the Google WIFI were remotely reasonable. I do not stream video, download large amounts of data, host a site, or do anything thirsty for bandwidth. I imagine at least half my neighbors would probably be in a similar situation and could just as easy ditch their wireless internet were it not for the terrible (read: unavailable) Google WIFI service. All in all, Google fiber optic broadband will likely be no different.
UPDATE: There is an entirely different slant to this news article than I had written about above; namely that Google is becoming a pervasive end-to-end data collection behemoth. The article mentions “connecting remote hospitals” and “helping students” which are flowery ways of painting the fact that Google would like to gain access to a new demographic. For Google to fill in a bigger, and much more detailed, picture it must get its tentacles deeper in to these untapped regions of the country. Similarly, across the pond, in Britain, Google is looking to be a potential investor in giving a boost to Britain’s fiber network. Keeping pace a related slashdot post that asks is Google too big to fail? and raises concern over this same point: Google datasets are getting ever more massive and the potential amount of information gathered within is scary, even to those less paranoid about their online identity.
As many know PHP have dynamic methods (or magic methods) for producing an environment that, at run-time, is much different than one conceives at first blush. It is largely the inclusion of these magic methods that brought PHP forward and lead to many elegant and inventive solutions. These can be found in nearly every major framework and library that scatter the PHP landscape. Indeed, they let you do very crafty things; take, for example, allowing for the custom dispatch of controller actions in Zend Framework or how Doctrine uses them to perform serialized caching for objects. These examples really can really show off what PHP’s best intentions are. However, like any tool, what it was intended for, and what others are using it for, in practice, can often be at odds. My beef is with the magic accessors and the way I see them employed in many scenarios.
The use of the magic accessors (__get and __set) have allowed for the rapid growth and expansion of objects beyond anyones wildest dreams and now we are paying severely for the bloat and overhead. On top of that, often coupled with this, is the lack of validation of values following overly optimistic assumptions about the values being set. Let me show an example of such a class to make this more clear:
class User
{
protected $_data=array();
public function &__get($key)
{
$value = null;
if (isset($this->_data[$key])) {
$value = $this->_data[$key];
}
return $value;
}
public function __set($key, $value)
{
$this->_data[$key] = $value;
}
public function __isset($key)
{
return isset($this->_data[$key]);
}
public function __unset($key)
{
unset($this->_data[$key]);
}
}
What this now affords developers is the ability to, anywhere in code where they have a User object instance, create arbitrary invalidated values on the User object:
for($i=0; $i<1000000; $i++) {
array_push($user->foo, new Foo($i));
}
$user->bar = 45.352135;
$user->baz = 'I CAN HAZ ANY VALUE I WANT! MUHAHAHA!';
$user->bat = memcache_get('some_invalid_value_from_mc');
// ...
var_dump(strlen(serialize($user))); // => 134523592
My argument centers around the misuse of these magic accessors, particularly in the case where you are persisting the object (as would most likely be the case for a User object). If you have a value you are putting into an object you should be able to, in a very straightforward manner, validate it (see my post A Tailored Approach to Object Validation). What better way than to explicitly specify an instance variable and a getter and setter method for it? You can still use the magic accessors but perhaps as a catch all for values which seemed to appear out of thin air. Take, for example, the way I think most setups should be done or modeled to closely resemble:
class User
{
protected $_name;
protected $_age;
/* ... */
public function getAge()
{
return $this->_age;
}
public function getName()
{
return $this->_name;
}
public function setAge($age)
{
$minimumAge = 0;
$maximumAge = 130;
$validator = new Validator_Integer_Between($minimumAge, $maximumAge);
if (!$validator->valid($age)) {
throw new ValidationException('The age attribute must be between the values [' . $minimumAge . '] and [' . $maximumAge . ']');
}
$this->_age = $age;
}
public function setName($name)
{
$regEx = "/^[A-Za-z]+$/";
$validator = new Validator_String_Matches($regEx);
if (!$validator->valid($name)) {
throw new ValidationException('The name attribute must match the regular expression pattern [' . $regEx . ']');
}
$this->_name = $name;
}
public function __get($key)
{
throw new Exception('User::__get(' . $key . '): Attempt to get a non-existent attribute [' . $key . ']');
}
public function __set($key, $value)
{
throw new Exception('User::__set(' . $key . ', ' . $value . '): Attempt to set a non-existent attribute [' . $key . '] to value [' . $value . ']');
}
public function __isset($key)
{
throw new Exception('User::__isset(' . $key . '): Attempt to check for non-existent attribute [' . $key . ']');
}
public function __unset($key)
{
throw new Exception('User::__unset(' . $key . '): Attempt to unset a non-existent attribute [' . $key . ']');
}
}
As you can see any value that “falls through the cracks” will be caught and dealt with. In this way we are able to implement any craziness in the magic accessors, should we ever need do anything “magical”, and use concrete getters and setters so we are able to more readily (and cleanly) allow for the validation of every value set into our object, not to mention its also faster. If you have a million values in your user object you should have at least two million accessor methods (1 million gets, and 1 million sets). Adding a new attribute to the class, creating its getter method, and its setter method forces you to think about what you are doing and whether you need the value or not.














