Developing static HTML emails is a pain in the butt. For best results, you need to inline all of your styles at HTML attributes instead of using real CSS (externally or inline). You also typically find yourself being very repetitive with your markup if you have a bunch of static emails that share common elements.
MailMatic to the rescue.
MailMatic is a Ruby gem, that is really just a mashup of tools, that aims to ease the burden of creating and maintaining static HTML emails. It uses StaticMatic, Haml, Sass, and Compass to let you author your HTML emails with all of the facilities you enjoy while creating your dynamic site: templates, partials, helper functions, inline Ruby code, reuse of markup and styles, etc. It uses Premailer to convert the HTML/CSS generated from Haml/Sass into self-contained HTML files that inline all of their styles. Premailer even gives you warnings about styles that may not work nicely in certain email readers.
Armed with this, you can accelerate your ability to crank out static HTML emails, and lessen the burden of maintaining them.
To get started with MailMatic, check out its installation and usage instructions on github at: https://github.com/scottwb/mailmatic.
Showing posts with label rubygems. Show all posts
Showing posts with label rubygems. Show all posts
Monday, August 15, 2011
Tuesday, July 19, 2011
The ask_geo gem: find the time zone for a given latitude and longitude
The Google Maps API has all kinds of great services like geocoding and reverse geocoding, but it lacks an API to determine a timezone from a latitude and longitude. This kind of service would come in handy, for example, when you are picking a point on Earth and scheduling an event there in the point's local time. It could also be useful for automatically determining a website visitor's current local time based on the geolocation obtained from their browser or IP address.
There is a service called GeoNames, which comes close to serving this need. However, its look-ups are based on "closest point of interest", which means that you can get errors when you are near borders, and some locations may not return any results at all.
There is another service called EarthTools which doesn't have this problem, but it only returns the current offset from UTC at that point. That is great if you only care about the current local time, but leaves you stranded if you need to account for Daylight Savings Time on some future or past date.
After a bit of searching, I came across a great free service called AskGeo. AskGeo provides a very simple JSON-over-HTTP API (or XML if you prefer to party like it's 1999). AskGeo uses a real time zone map, so every point on earth returns a result, and returns real Olson IDs for time zones, so you can look up DST transitions, leap seconds, etc.
I gave AskGeo a try and it works great...and it's fast! Since there was no ready-made Ruby gem that provided a client API, I decided to create one.
Introducing the ask_geo gem: https://github.com/scottwb/ask_geo
It can be installed as a ruby gem. See the github page for installation and usage instructions.
Labels:
geolocation,
ruby,
rubygems,
timezone
Tuesday, May 31, 2011
Encrypted Cookie Store that works with Rails 3.0
If you like the benefits using Rails's CookieStore, but want to store possibly sensitive data in the cookie, then encrypted_cookie_store is for you. It works like CookieStore, but encrypts the cookie payload so that it cannot be read by the client.
If you are using Ruby on Rails 3.0.0 or higher (but not yet Rails 3.1), then you'll need my fork of encrypted_cookie_store that fixes it for Rails 3.
To install it:
gem install scottwb-encrypted_cookie_store
Then add to your bundler Gemfile:
gem 'scottwb-encrypted_cookie_store', :require => 'encrypted_cookie_store'
Then read the rest of the installation/configuration instructions.
Background
For Rails 2.3, the folks at Phusion created encrypted_cookie_store, which you'd install as a plugin, and it worked great. I used it for a long time.
However, they never updated it for Rails 3. That's where Ben Sales came in. He forked this project and made it work for Rails 3...in the pre-release days, that is. Ben did all the work to get it packaged up as a gem and updated it to work with Rails 3 railties and initializers.
Unfortunately, sometime between Rails 3.0.0.beta3 and 3.0.0.beta4, the layout of AbstractStore and CookieStore changed quite a bit, pushing a lot of the functionality out to Rack, and breaking the encrypted_cookie_store gem.
That's where I come in. I basically did the minimal amount of work required to get it to work with Rails 3.0 (tested on 3.0.0, 3.0.7, and 3.0.8.rc4), got all the specs working again, and created a new gem called 'scottwb-encrypted_session_cookie'.
It doesn't work in Rails 3.1, but I'll probably remedy that once Rails 3.1 officially releases. I'm also happy to accept patches if anyone else onces to tackle that.
This is a nice gem. Maybe some day I'll make a push to clean it up and lobby to have it as one of the packaged options that ships with Rails...
Saturday, December 4, 2010
Installing curb gem on Mac OS X 10.6 (Snow Leopard)
If you have previously installed curl with something like:
sudo port install curl +ssl
and then try to install the curb gem like:
sudo gem install curb
and you find yourself getting an error that looks something like this:
In file included from /opt/local/include/curl/curl.h:44,
from curb.h:12,
from curb.c:8:
/opt/local/include/curl/curlrules.h:144: error: size of array ‘__curl_rule_01__’ is negative
/opt/local/include/curl/curlrules.h:154: error: size of array ‘__curl_rule_02__’ is negative
lipo: can't open input file: /var/folders/wX/wX64Cb+PGjG-EXuklO+I+k+++TI/-Tmp-//ccKIrqTY.out (No such file or directory)
make: *** [curb.o] Error 1
Then, I think I have a solution for you. Change your curb install command to this instead:
sudo env ARCHFLAGS="-Os -arch x86_64 -fno-common" gem install curb
It seems a number of people on the web suggest re-installing curl as a universal binary using something like:
sudo port install zlib +universal
sudo port upgrade --enforce-variants openssl +universal
sudo port install curl +universal
I do not like this approach. The original problem is that you installed an x86_64 version of curl (which is the default, as it should be) but you are trying to install a universal version of curb (which is unfortunately the default). Instead of re-installing curl to be universal, which is wasteful and takes forever, install curb using the x86_64 flags to build it. This is what you want, it works, and it only takes a few seconds.
Monday, July 5, 2010
Install a Rails App's dependencies where 'rake gems:install' fails.
Using rake gems:install to install the gem dependencies of your Rails 2 app just doesn't seem to work. There are a number of problems you may encounter:
Problem 1: It depends on Rails.
You have to manually install Rails before you can use rake gems:install. Ok, so this might not be that big of a deal, but consider this scenario:
- Your app is running in production on rails 2.3.4.
- You upgrade your app to rails 2.3.5, including the RAILS_GEM_VERSION.
- You deploy your app.
- Your deployment script calls rake gems:install to keep the dependencies up to date with each new release.
- That fails with something that looks like:
Problem 2: Sometimes, for some reason, it just doesn't work.
Sometimes (most times) you add a new config.gem command to environment.rb. The next deployment runs rake gems:install and it fails with the complaint that you are missing the very gem you are hoping it will install for you. For example, in a working Rails 2.3.5 project, add this line to environment.rb:
config.gem 'sanitize', :version => '1.2.1'
Then, run rake gems:install, and it fails with a "Missing these required gems:" message, e.g.:
WTF? It's telling me to run the command I just ran, to install the missing gem that's preventing that command from running.
Problem 3: It depends on your Rails environment.
This can create a circular dependency where some file (particularly vendored plugins/gems) can require a gem to be loaded before the task to install it runs. For example, consider that some file in your vendor directory does this:
require 'gdata'
Then naturally, you add this to environment.rb:
config.gem 'gdata'
The next time you run rake gems:install, it will fail with a "no such file to load" error, e.g.:
The Solution: rails_gem_install
I have created a new tool called rails_gem_install to help alleviate this problem. Use this instead of rake gems:install, and you should be much more successful at getting all your Rails app's dependencies installed without manual intervention.
To install:
gem install rails_gem_install
To use:
cd my_rails_appRAILS_ENV=production rails_gem_install
This will install all the gems required to run your app in the production environment, including Rails. Replace rake gems:install in your deployment scripts with rails_gem_install, and as you change config.gem requirements, those gems will be properly installed.
See the github project page for more details.
How It Works
The main principle behind this tool is that it does not depend on Rails. It creates its own module named Rails that provides some of the functionality from the real Rails that it needs, up until the point that Rails is installed. Then, it only loads some very specific parts of Rails that implement the gem dependency and installation mechanisms, without actually running the app's Rails::Initializer and loading all of its environment, plugins, etc.
First, it runs a simple rake -T to see if it complains about Rails missing. It parses the output of this, and if necessary, installs the indicated version of Rails.
Next, it parses out the config.gem statements and uses those to ensure all the listed gems requirements are met, and installs those that aren't. It does this without actually loading Rails or the app environment. This carries us most of the way.
Finally, it runs the rake gems command and parses its output to detect all the kinds of errors described above and install the corresponding gems. This step is repeated until rake gems does not complain anymore.
Subscribe to:
Posts (Atom)
