Rails says, "Missing pdf-writer" when pdf-writer is unpacked in vendor/gems

Issue:
*"Missing these required gems: pdf-writer = 1.1.8"*

config/environment.rb:
Issue:
*"Missing these required gems: pdf-writer = 1.1.8"*

config/environment.rb:
1
  config.gem "pdf-writer", :lib => "pdf/writer", :version => '1.1.8'

That looks write... what's the issue? Turns out my new server didn't have the required dependencies.

I added this above the config/gem line:

1
  require "#{RAILS_ROOT}/vendor/gems/pdf-writer-1.1.8/lib/pdf/writer.rb"

and saw:

1
2
  no such file to load -- color
  no such file to load -- transaction-simple      # after fixing color

the fixes:
1
2
  gem install color
  gem install transaction-simple

remove the require line, and voila!

Anthenticating against PayFlowPro for Rails with ActiveMerchant

Rails is fortunate to have ActiveMerchant, a gem that provides a standard interface for billing. Unfortunately, there are a wide variety of gateways out there and each has their own "uniqueness." I experienced PayFlowPro's "uniqueness" today and thought I would share my now-working spike code.

THE PARTNER FIELD

The partner field below is optional. If you leave it blank, the default will be PayPal. The other option, apparently, is VeriSign. I have included it here because magical, undocumented parameters confuse people.

MERCHANT LOGIN

in my case, this was the company name without any spaces. It's the same as the merchant login required to log in to the PayflowPro website.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

  gateway = ActiveMerchant::Billing::PayflowGateway.new(
    :login             => 'my_company_name',    # 'Merchant Login from the login page
    :user              => 'my_username',
    :password          => 'ComPliCatedP4sSw0rd',
    :partner           => 'PayPal'
  )

credit_card = ActiveMerchant::Billing::CreditCard.new(
                      :number => '5105105105105100',
                      :month => '9',
                      :year => '2011',
                      :first_name => 'Longbob',
                      :last_name => 'Longsen',
                      :verification_value => '123',
                      :type => 'master'
                    )

# Make a $1 purchase (100 cents)
response = gateway.purchase(100, credit_card)
puts response.success?
puts response.message

MOVING FROM A SPIKE TO REAL CODE

Copy the above code, replace your company name, and get that to say "Accepted"... once that's done, check back for my blog entry on the easiest way to set up ActiveMerchant in a Rails app.

ISSUES I EXPERIENCED

PayFlowPro response 26 - Invalid Vendor Account

I was using my username where my merchant login should have been.

PayflowPro response 1 - User authentication failed

Here I was submitting the company name as my :login but was not including my username under :user



REFERENCES

com.googlegroups.activemerchant - Payflow Pro Integration

Payflow Gateway - User authentication failed

Triangles and Chat Bubbles with pure CSS

This is pretty awesome.

http://www.dinnermint.org/css/creating-triangles-in-css/comment-page-2/#comment-313

Now if only it worked in IE. :(

Automated Testing for Infrastrure

I have a client whose website is subject to HIPAA regulations. I just finished setting up SSL for them. I also set up redirects so that:

http://domain.com => https://www.domain.com
http://www.domain.com => https://www.domain.com

It all works now. Unfortunately, I've become accustomed to the feeling of security that I get from automated tests. I can't use rspec here, because that configuration is on the server. I have signed up for monitoring service, but that won't tell me if somehow https://www.domain.com starts serving insecure pages. (most modern browsers will flip, but that doesn't get me around HIPAA.) What if the server crashes, has to be rebuilt, and I forget to set up the SSL stuff? It could be weeks before someone discovers that it isn't there, and that isn't good enough.

Not sure yet what to do.

HTML5 GeoLocation Accuracy

I spent some time looking in to HTML5 features this morning. The first one on the list is GeoLocation. This demo gave a position within a block of my house:

http://html5demos.com/geo

Interestingly, when I went to visit the page again, it located me within feet of my previous house, more than 500 miles away. According to the Chrome GeoLocation notes, it uses data including wireless networks to find your location, so I assume Google located my wireless router both places.

validates_uniqueness_of results in " undefined method `text?' for nil:NilClass "

I had the following model:

1
2
3
4
5
6
7
8
9
10
11
12
class Visit < ActiveRecord::Base

  belongs_to :visit_type
  belongs_to :patient

  validates_presence_of :visit_type
  validates_presence_of :patient
  validates_presence_of :date

  validates_uniqueness_of :visit_type

end

I changed :visit_type to :visit_type_id and it went away.

Web Dev Tools - Color Scheme Designer

Color Scheme Designer
colorschemedesigner.com

As any of my clients will tell you, my design skill falls somewhere between "enh" and "meh." Fortunately, someone smarter than me has found some math that can help. I use this tool to find colors that match the existing colors. Once I've found a set of colors that look good, I can bookmark the color scheme in a folder for that client, and reference it whenever I need to look at their color scheme.

Another great, free tool!

MySQL says " Incorrect column specifier for column 'x' "

My rails app uses a database of dubious origin, so I wasn't shocked when I had issues. Because I imported the database from sql, I first noticed the issue when running tests. Tests start with

rake db:test:clone

which starts by regenerating db/schema.rb using

rake db:schema:dump

My db/schema.rb then contained columns like this:

table.float :somefloat :limit => 255

I'm pretty sure you can't have a limit without a precision and scale... in my case, I created this migration:

alter_column :table, :field, :decimal

and everything was golden.

users and profiles

I find myself, yet again^n, considering users and profiles.

Say you have the following models:

- User
- Doctor
- Patient

Of course, the concept of user is not the same as the concept of a person. User might be more accurately called Login, since it could be a bot or a guest login used by 100 various anonymous people.

your views have access to current_user. We'll make our lives easier by ssuming that current_user is always populated with a valid user.

What I remember thinking last time I was in this bruhaha was that a user could have one or more profiles. That's what we conveniently have here. A user can be a doctor, and if so, they have a doctor profile... license number, type of practice, whatever. That same person could be a patient. If so, we'll have information like... emergency contact, last_check_up, allergies.

So you can ask whether a user can see a patient. And obviously this falls under the User model since it's all about authentication and authorization.

1
2
3
4
5
6
7
class User

  def can_view?( patient )
    (self == patient ) || (self.doctor && patient.doctor == self.doctor)
  end

end


ok... so now I want to welcome this user. If they are a doctor, I want to prepend their name with "Dr." first_name and last_name are on User.

1
2
3
4
5
6
class User
  def fullname
    [title, first_name, last_name].join(' ')
 end
end
-

ok great. At some point I'm running through a list of doctors and I'll want to output their names.

1
2
3
4
5
class Doctor
  def to_s
    self.user.to_s
  end
end

(a) we've already said that a user isn't necessarily a doctor; could be a group.
(b) for this app, there's no guarantee a doctor even has a login.

I don't want to store first_name, last_name twice... so that leads me to the conclusion that I need a Person model.

Person
first_name
last_name
dob
blah

So then we get:
Doctor#person_id
Patient#person_id
User#person_id ????
maybe, instead of that...
Person#user_id

so then
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class User
  def to_s
    person.to_s
  end
end

class Person
  def to_s
    title, first_name, last_name
  end
end

class Doctor
  def to_s
    person.to_s
  end
end

# same for patient  

ok this seems very sensible.

Why Ruby Complains about Nested Parentheses

Every time a dev asks me why Ruby doesn't like nested arguments without parens, I draw a blank, but I swear that it's an issue.

Here's an example of the issue:

1
=link_to h @person.philosophy, @person.philosophy

it seems really obvious right now. I'm not sure why I can't think of that when it's clinch time. Anyway, this can be the obviously intended call:

1
=link_to( h( @person.philosophy ), @person.philosophy )

or the unfortunate( and invalid, since h takes 1 not 2 arguments )

1
=link_to( h( @person.philosophy, @person.philosophy ))

changing an agile ticket with user story and acceptance criteria from a traditional ticket

This is a real-life example of a ticket write by a client that I converted into an "agile" user story with acceptance criteria, provided for those who want to find out whether there would be value for them in transitioning and those who want to understand the differences between them.


1
2
3
Title: Users can create a category from the Add Item screen

The category drop down will contain a new item called "Add a New Category". When this option is selected a new text field will appear to give the category a name and possibly to select an icon.

first step: user story

1
2
-Title: Users can create a category from the Add Item screen
+Title: As a user I want to create a category on the fly from the Add Item Screen so that I can keep the data I have already entered on the new item screen.

add acceptance criteria using [given/]when/then format

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
- The category drop down will contain a new item called "Add a New Category".
- When this option is selected a new text field will appear to give the category a name and possibly to select an icon.
- When the user saves the item the new category will be created and the new item will appear in that category
+ Scenario: Fields Magically Appear
+ When I am on the new item screen
+ And I select 'Add a New Category' from 'Category'
+ Then I will see "Category Name"
+ And I will see "Category Icon"
+ NOTE: that submitting the form below will cause a request/response, but won't
+ create the item because we haven't filled in 'Name', a required field. Being back on
+ the form is convenient, though, because it's easier to write an automated test against
+ a form.
+ Scenario: Adding a Category
+ Given there is not a category named 'Pocket Protectors'
+ When I am on the new item screen
+ And I select 'Add a New Category' from 'Category'
+ And I fill in 'Category Name' with 'Pocket Protectors'
+ And I select "house" from "Category Icon"
+ And I submit the form
+ Then 'Category' should be 'Pocket Protector'
+ Scenario: Can't create duplicate category names
+ Given there is a category named 'Pocket Protectors'
+ When I am on the new item screen
+ And I select 'Add a New Category' from 'Category'
+ And I fill in 'Category Name' with 'Pocket Protectors'
+ And I select "house" from "Category Icon"
+ And I submit the form
+ Then 'Category' should be 'Add a New Category'
+ And 'Category Name' should be 'Pocket Protector
+ and 'Category Icon' should be 'house'

dd_roundies fails for AJAX with IE8

Rounding things in IE8 is one of the biggest farses ever.

After some research, I'm using dd_roundies. I won't explain how it works, because you don't deserve that kind of suffering. It seems to work for rounding objects in IE before the page is set to the "ready" state, but it's failing for me in ajax requests (and in fact any javascript that happens after the page hits the "ready" state.)

I found this bit in the code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
if (DD_roundies.IE8 && document.attachEvent && DD_roundies.querySelector) {
        document.attachEvent('onreadystatechange', function() {
                if (document.readyState == 'complete') {
                        var selectors = DD_roundies.selectorsToProcess;
                        var length = selectors.length;
                        var delayedCall = function(node, radii, index) {
                                setTimeout(function() {
                                        DD_roundies.roundify.call(node, radii);
                                }, index*100);
                        };
                        for (var i=0; i<length; i++) {
                                var results = document.querySelectorAll(selectors[i].selector);
                                var rLength = results.length;
                                for (var r=0; r<rLength; r++) {
                                        if (results[r].nodeName != 'INPUT') { /* IE8 doesn't like to do this to inputs yet */
                                                delayedCall(results[r], selectors[i].radii, r);
                                        }
                                }
                        }
                }
        });
}

I already had the round method (below) to use jquery for rounding when that was an option, and roundies otherwise. I wasn't able to find a way to get IE to toggle the ready state of the document on ajax calls, so I created a method trigger_late_rounding( ).

I'll be replacing BrowserDetect with DD_roundies.IEwhatever as soon as I get around to it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function round( selector, radius )
{
  if( radius == null )
  {
    radius = "10px";
  }

  if( BrowserDetect.browser == 'Explorer' )
  {
    DD_roundies.addRule(selector, radius);
  }
  else
  {
    $(function(){
      $(selector).corner(radius);
    });
  }
}

function trigger_late_rounding()
{
  var selectors = DD_roundies.selectorsToProcess;
  var length = selectors.length;


In your ajax .js, just...

1
2
round('.popup', '10px');
trigger_late_rendering();

ugly but effective.

It would be better to have patched dd_roundies, but it's not on github or ... whatever... if dd_roundies is still being maintained and you know where it lives, shoot me a note.

Getting started generating PDFs with Prince

Download and uncompress Prince:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
jw@gallifrey:~$ curl http://www.princexml.com/download/prince-7.1-linux.tar.gz -o prince.tar.gz
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 3879k  100 3879k    0     0   763k      0  0:00:05  0:00:05 --:--:--  940k
jw@gallifrey:~$ tar -xzf prince.tar.gz
jw@gallifrey:~$ cd prince-7.1-linux/
jw@gallifrey:~/prince-7.1-linux$ ls
jw@gallifrey:~/prince-7.1-linux$ install.sh  lib  LICENSE  README
jw@gallifrey:~/prince-7.1-linux$ sudo ./install.sh
Prince 7.1

Install directory
    This is the directory in which Prince 7.1 will be installed.
    Press Enter to accept the default directory or enter an alternative.
    [/usr/local]:

Installing Prince 7.1...
Creating directories...
Installing files...

Installation complete.
    Thank you for choosing Prince 7.1, we hope you find it useful.
    Please visit http://www.princexml.com for updates and development news.


Based on the documentation

jw@gallifrey:~/prince-7.1-linux$ prince http://app.local/reports/my_report.html -o /code/client/app/public/sample.pdf

IT WORKS! but it's kinda ugly.

add pdf.css based on the boom microformat ...
add .cover-page, .chapter, .cover-notes, etc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
@page {
  size: 8.5in 11in;
  margin: 0.75in;
}

p, .cover-notes {
  line-height: 1.7em;
}

.titlepage, div.chapter, div.appendix {
  page-break-after: always;
}

.titlepage {
  page: blank;
  margin: 1in 0.75in 0.75in;
  text-align: center;
}

.document-heading {
  font-size: 0.5in;
  padding: 1in 0;
}

.cover-notes{
  font-size: 0.3in;
}

h1, h2, h3, h4, h5, h6 {
  page-break-after: avoid;
}

h1 {
string-set: document-heading content();
}

h2 {
string-set: chapter-heading content();
}

q::before {
  content: "\201C";
}

q::after {
  content: "\201D";
}

/* This can be alternated so that left and right facing pages are opposites; In my case, this isn't useful, so I merged it to one. */

@page {
  @top-left {
    content: string(document-heading, first);;
  }
  @top-right {
    content: string(chapter-heading, first);
  }
  @bottom {
    content: counter(page);
  }
}

/* don't show document title in the heading on the cover page. */
@page blank :right {
  @top-left {
    content: normal;
  }
}

jw@gallifrey:~/prince-7.1-linux$ prince http://app.local/reports/my_report.html -s http://app.local/stylesheets/pdf.css -o /code/client/app/public/sample.pdf



jw@gallifrey:~$
jw@gallifrey:~$ sudo gem install princely
Successfully installed princely-1.2.5
1 gem installed

---

Session Data / Cookies don't persist in IE

Rails fails with 500

I spent at least six hours isolating this issue so I thought I'd save someone else some trouble.

Say you have a site fu.com ... if you're doing any SEO work (or if you just want things to be clean) you'll 301 redirect all traffic from fu.com to www.fu.com. You can do this with Rails with a before_filter in your Rails ApplicationController.

When the user hits http://fu.com, Rails may send back a session-expiring cookie with your session id. It then redirects the user to http://www.fu.com. Rails may send back a session-expiring cookie from that domain. This confuses IE and causes it to ignore changes to the session cookie.

The trivial fix is to move the redirect upstream, in my case to Apache.

It's odd that this didn't happen in firefox or chrome, so I assume there's more to the story, but it's working now so I'm leaving it alone. :)

[Valuable] parsing attributes

This post is me thinking 'out loud' about how to add custom parsing ruby gem valuable

In the past I ran into quite a few situations where I wanted to parse / process / format certain attributes as they came in. There seemed to be a lull in that so I hadn't implemented it, but now I find myself wanting it again. I'm looking at several ways to implement it and I'm not sure which one(s) are best.

Here's how you can do it now:

1
2
3
4
5
6
7
8
class Beer < Valuable

  has_value :born_on, :klass => Time

  def born_on=(value)
    attributes[:born_on] = value.is_a?(String) ? Time.parse(value) : value
  end
end

I like the simplicity here. No extra code is added to valuable, but it's still readable. I don't like the fact that you have to know to set it to attributes[:born_on]. That should be abstracted.

You could always call super...

option one: make no changes, call super

1
2
3
4
5
6
7
8
class Beer < Valuable

  has_value :born_on, :klass => Time

  def born_on=(value)
    super( value.is_a?(String) ? Time.parse(value) : value )
  end
end

I initially didn't like this because I had an idea in my head of some code I wanted to add, not making changes is really growing on me. Could I just update the documentation and release a new version with 'new functionality'? :)

The code generated by valuable is absent... but looking at the generated constructor, really, we're not missing anything.

It's almost pointless to even have :klass => Time as Time.new(...) will result in 'ArgumentError: wrong number of arguments (1 for 0)', though it does provide a sort of executable comment...

option two: Indicate the method to use to parse.

1
2
3
4
5
6
7
8
class Beer < Valuable

  has_value :born_on, :parse_with => :born_on_parser

  def born_on_parser( value )
    value.is_a?(String) ? Time.parse(value) : value
  end
end

I'm not fond of this. Should it be an instance or class-level method? I guess instance makes sense, but then I almost feel like it should be reading attributes instead of having a value passed in. If static, well, that makes even less sense as instance-level setters would be calling class-level parsers... enh. I guess it's not a travesty, but not my favorite.

option three: provide a proc to the has_value method

1
2
3
4
5
6

class Beer < Valuable

  has_value :born_on, :parse_with => Proc.new {|value| value.is_a?(String) ? Time.parse(value) : value }

end

This starts to seem cluttered.

option four: separately provide parsing that would be added to the setter:

1
2
3
4
5
6
7
8
class Beer < Valuable

  has_value :born_on

  parse( :born_on ) do |value|
    value.is_a?(String) ? Time.parse(value) : value
  end
end

I like this alot, but it's my second-favorite to option 1, just leave it.