The blog has moved to: http://jkamenik.github.com.
The full details of why are here: http://randomsoftwareinklings.blogspot.com/2012/11/the-long-away.html
Random Software Inklings
I tend to do a lot of random research for various packages for use in projects. Most of the time I just make the package work and move on. This means that if I need to do the same thing again I have to go find all my sources again, or remember what I did. This is my attempt to actually document what I have done in a useable way.
Saturday, December 29, 2012
Monday, November 12, 2012
The long away
The Reason
First, let me apologize to my 3 readers that I have been away for so long. There are a lot of reasons why I have been gone, but mainly it boils down to how much I hate the blogger interface for dealing with code.Sure, blogger is a simple platform and does exactly what it says. Sure, it integrates with google plus, twitter, etc... Sure, it was easy to configure, setup and deploy. Sure, it has a lot of features.
But, it sucks for code! And I mean Sucks! For code there are a few very specific hot button items that are must haves:
- Monospaced font and significant whitespace (<pre> in HTML)
- Line numbers
- Syntax highlighting
Not that much to ask, but those features are ONLY ever going to be needed by a programmer. So I can see why they don't get that much attention.
Both the old and the new blogger interface have a way of dealing with this, but it is time consuming and annoying:
- Use gist.github.com as a dumping place for all your code samples
- Create a separate file in the gist for each sample (makes it easier later)
- Make sure the file name has the right extension so that syntax highlighting happens
- Copy the embed codes for each gist
- When editing the blog only use HTML mode!
- The gist code is a javascript so it will only render in preview
- Switching between HMTL and compose sometimes rearranges non-visible items, which means when your page renders your code could be anywhere
- If I am going to write raw HTML I might as well use Markdown, which sucks less and converts to HTML
- Hope that nobody views your blog with JS disabled!
The Solution
After playing with many blogging solution and giving up on Wordpress entirely (Sorry I just cannot get what I want without a LOT of php hacking), I have decided to give a Octopress a serious shot. I use github all the time and even host a few things using github pages.
In case you don't know, Github pages can render Jekyll sites. And Jekyll is a blog aware static site generator, which can read markdown. And Markdown is a much more human friendly markup language then HTML, but compiles into HTML; also, Github uses it everywhere in their site (as do a lot of other places).
So things started to fall into place with Jekyll. I just needed to install a syntax highlighting gem, and design the site. In the process, I stumbled across Octopress, which is a wrapper around a Jekyll site, works with github, has syntax highlighting, provides a clean theme, and has a programmer friendly workflow.
So Octopress is the blog engine for me. And it will reside at http://jkamenik.github.com. I will slowly be transferring all my entries from here, but I doubt I will retire this site entirely.
Friday, March 9, 2012
Factory Girl Automatic Tests
Introduction
Early in a project I started to use factory girl without fully understanding it. After many months of creating steps like "Given /^(\d+) blog exists$/" and "Given /^the following blogs exist:$/" I started to come up with generic functions that would build those steps.
Stupid me for not checking that factory girl already does something like that. All you have to do is include factory girl's step_definitions.rb file:
Once you start using FactoryGirl correctly there are a world of new features that can make your steps both cleaner and more concise. Here are some tips I have found via trial and error.
Tip 1: Do not reinvent the wheel
Factory girl will create steps for all factories that you have register.
Tip 2: Use association, Do not add more steps then are needed
Factory girl association are automatically created before the factory is created and they are automatically linked. It only supports the belongs_to behavior, so keep that in mind.
Using the "Given the following XXX exist" step you can define attributes, on the the association, in the table. If we leave the association out then a default is created. If we define an attribute then it will be found or created using that attribute.
Lets say you have a product and it can belog to a category. You do not need to create a category.
Tip 3: Attaching files via CarrierWave
Since cucumber is a text file it doesn't make much sense for you to define full files in steps. It also doesn't really make sense to embed full file paths in the tests. Instead, you can use a Transient attribute and some code so that in cucumber you define a file name and in the factory it converts to an actual file.
Tip 4: Fixing a circular dependency between two models
Lets say you have a Store model and User model. And a User can both work at and own a Store. If you put associations in both the User and the Store model then each will try to create the other, infinitely. We can reuse the transient method as before to break the circle.
The trick is to avoid defining an association in both factories, but instead use a transient attribute in one factory to simulate the behavior of an association. Also, since transient attributes are not likely to have the same level of sophistication as the associations you should use the association to define the more complex of the two models.
Tip 5: Fixing a circular dependency between the same model
Let say you have a Category model, and that model can belong to another Category (a tree) then you cannot use an association or you get the same infinite recursion issue as before. Here we can use a transient attribute along with an after_create hook to simulate the behavior we want.
Early in a project I started to use factory girl without fully understanding it. After many months of creating steps like "Given /^(\d+) blog exists$/" and "Given /^the following blogs exist:$/" I started to come up with generic functions that would build those steps.
Stupid me for not checking that factory girl already does something like that. All you have to do is include factory girl's step_definitions.rb file:
Once you start using FactoryGirl correctly there are a world of new features that can make your steps both cleaner and more concise. Here are some tips I have found via trial and error.
Tip 1: Do not reinvent the wheel
Factory girl will create steps for all factories that you have register.
Tip 2: Use association, Do not add more steps then are needed
Factory girl association are automatically created before the factory is created and they are automatically linked. It only supports the belongs_to behavior, so keep that in mind.
Using the "Given the following XXX exist" step you can define attributes, on the the association, in the table. If we leave the association out then a default is created. If we define an attribute then it will be found or created using that attribute.
Lets say you have a product and it can belog to a category. You do not need to create a category.
Tip 3: Attaching files via CarrierWave
Since cucumber is a text file it doesn't make much sense for you to define full files in steps. It also doesn't really make sense to embed full file paths in the tests. Instead, you can use a Transient attribute and some code so that in cucumber you define a file name and in the factory it converts to an actual file.
Tip 4: Fixing a circular dependency between two models
Lets say you have a Store model and User model. And a User can both work at and own a Store. If you put associations in both the User and the Store model then each will try to create the other, infinitely. We can reuse the transient method as before to break the circle.
The trick is to avoid defining an association in both factories, but instead use a transient attribute in one factory to simulate the behavior of an association. Also, since transient attributes are not likely to have the same level of sophistication as the associations you should use the association to define the more complex of the two models.
Tip 5: Fixing a circular dependency between the same model
Let say you have a Category model, and that model can belong to another Category (a tree) then you cannot use an association or you get the same infinite recursion issue as before. Here we can use a transient attribute along with an after_create hook to simulate the behavior we want.
Wednesday, November 30, 2011
CI server using Firefox
If you are like me, you always setup a CI to ensure things that you already finished are not broken by things you are currently doing. And if you are like me, you use capybara, selenium-webdriver, and firefox to actually test the results in a browser. The rub comes when the CI server (running headless) needs to run firefox, which needs a screen.
Virtual Frame Buffer (xvfb) is a great package. All it does is provide an X11 interface in memory instead of requiring a screen. Below I detail what I do on Ubuntu, but it should work the same on any Linux distro.
Installing Firefox
Testing Firefox
Once firefox is installed it can be tested on a X11-forwarded ssh connection. X11-forwarding has to be enabled on the server and client and can be tested by checking DISPLAY.
Installing Xvfb
Testing Firefox again
The easiest way to test is to use image magick to take a screen shot of the VFB and save it to an image that can be opened in Firefox. If the image opens and it looks like a firefox browser is running on the google page then you did it correctly.
Create a xvfb startup script
On ubuntu no start script is provided, but a simple one put in /etc/init.d/xvfb is enough.
Getting the CI server to use the VFB
At this point getting a CI server to use Xvfb will depend on how it is started. If you use the Xvfb startup script then the display is :1. All you have to do is export DISPLAY=:1 before the CI server starts.
Virtual Frame Buffer (xvfb) is a great package. All it does is provide an X11 interface in memory instead of requiring a screen. Below I detail what I do on Ubuntu, but it should work the same on any Linux distro.
Installing Firefox
Testing Firefox
Once firefox is installed it can be tested on a X11-forwarded ssh connection. X11-forwarding has to be enabled on the server and client and can be tested by checking DISPLAY.
Installing Xvfb
Testing Firefox again
The easiest way to test is to use image magick to take a screen shot of the VFB and save it to an image that can be opened in Firefox. If the image opens and it looks like a firefox browser is running on the google page then you did it correctly.
Create a xvfb startup script
On ubuntu no start script is provided, but a simple one put in /etc/init.d/xvfb is enough.
Getting the CI server to use the VFB
At this point getting a CI server to use Xvfb will depend on how it is started. If you use the Xvfb startup script then the display is :1. All you have to do is export DISPLAY=:1 before the CI server starts.
Monday, November 21, 2011
Ruby module instance and class methods
A very common idiom especially when code starts to become complicated is to put functions in modules and mix in that behavior to several classes. And a common expansion is to have a single "include" add both instance and class methods.
Here is how to do it:
"include" is used to add a module's instance methods as instance methods to the including class, but it doesn't traverse sub modules. "extend" is used to add a module's instance methods as class methods to a class.
When a module is "included" it can register a callback which is passed the class that is doing the including. And calling "extend" on the base and passing a submodule will cause it to put those methods at the class level. This causes a chain reaction of loading both instance and class methods using a single "include".
Pro Tip: It is possible to cause the same behavior using "extend" by using the "extended" callback; however, this is not common and "include 'x'" reads better then "extend 'y'".
When a module is "included" it can register a callback which is passed the class that is doing the including. And calling "extend" on the base and passing a submodule will cause it to put those methods at the class level. This causes a chain reaction of loading both instance and class methods using a single "include".
Pro Tip: It is possible to cause the same behavior using "extend" by using the "extended" callback; however, this is not common and "include 'x'" reads better then "extend 'y'".
Tuesday, August 16, 2011
The 3N Rule for deployment
As a programmer I am lazy, but in a productive way. It is not that I don't do anything. It is that I only do things a set number of times. I have a simple rule, which I call the "3N rule", which states "I will doing something once, script it the second time, and use the script from then on". Therefore, if I have 3 to N devices to manage then I have a script that takes minimal input and replicates the change on all devices.
I also have a 3N rule for programming, but that is a matter for another time.
By using a script I eliminate a lot of the human error and also increase my productivity because computers are, now days, faster at responding to stimuli then I am. But computers are "swift idiots" so for this to work the environment has got to be controlled. I recommend doing the following:
I also have a 3N rule for programming, but that is a matter for another time.
By using a script I eliminate a lot of the human error and also increase my productivity because computers are, now days, faster at responding to stimuli then I am. But computers are "swift idiots" so for this to work the environment has got to be controlled. I recommend doing the following:
- Use VMs
- Run headless, enable SSH
- Use ClusterSSH or csshX for learning what to script
- Use Capistrano or Fabric for automating change
By using a VM and running headless you remove the temptation to sit at a physical terminal. It also eliminates the fear associated with screwing something up as it is trivial to snapshot a machine and restore its state.
By using SSH and ClusterSSH you enable yourself to start thinking about the cluster as a whole, and more importantly start acting on the cluster as a whole. If some of the servers get out of sync then it makes management more difficult, so by using ClusterSSH you eliminate that problem.
By using Capistrano, or its like, then you eliminate the human error entirely. This is just good policy. Also, a benefit of a deployment script is that it is self documenting (assuming you know how to read).
Sunday, June 26, 2011
ExtJS 3 Views and Controllers
In a previous post I wrote about my impressions of Ext4. The overall impression were that the ideas were sound, but the implementation was still buggy. So instead of waiting (which is not possible in a business sense) I have back-ported the ideas to Ext3. I have not yet figured out how to get stores and models working well, but I have gotten views and controllers works very well.
Layout
Views basically work as is, because that is how ExtJS was designed. Any subclass of a UI widget will work as a view. However, to make the concept of a view work well they should only be instantiated once and have their modification logic in a controller. For this reason I recommend using the following directory layout:
app.js
This should just a Ext.onRead function that instantiates the Viewport.js class. It should also setup any globals that will be used throughout the app and should be included last.
lib/
Since views should only be instantiated once this is the place to put reusable code. Items here will not usually have an xtype because they will be extended by view items.
Controller.js
This is the base class for all controllers. It has the helper to bind to views and look them up afterwards. A small override to Ext.ComponentMgr is required to make everything work.
Content.js
This needs to be a simple card layout so that you can add new items to it.
ContentController.js
This class binds to a something that would change the content panel, like a TreePanel, and then using Ext.ComponentMgr creates a card, adds it to the content, and shows it.
Layout
Views basically work as is, because that is how ExtJS was designed. Any subclass of a UI widget will work as a view. However, to make the concept of a view work well they should only be instantiated once and have their modification logic in a controller. For this reason I recommend using the following directory layout:
- app.js
- ext/
- app/
- controllers/
- Controller.js
- ContentController.js
- lib/
- view/
- layout/
- Content.js
- Viewport.js
- OtherView.js
app.js
This should just a Ext.onRead function that instantiates the Viewport.js class. It should also setup any globals that will be used throughout the app and should be included last.
lib/
Since views should only be instantiated once this is the place to put reusable code. Items here will not usually have an xtype because they will be extended by view items.
Controller.js
This is the base class for all controllers. It has the helper to bind to views and look them up afterwards. A small override to Ext.ComponentMgr is required to make everything work.
Content.js
This needs to be a simple card layout so that you can add new items to it.
ContentController.js
This class binds to a something that would change the content panel, like a TreePanel, and then using Ext.ComponentMgr creates a card, adds it to the content, and shows it.
Subscribe to:
Posts (Atom)