Programming

MySQL utf8mb4 Encoding Breaks ActiveRecord’s Schema Setup

MySQL utf8mb4 Encoding Breaks ActiveRecord’s Schema Setup

I recently wrote about the virtues of true UTF8 (utf8mb4) character sets in MySQL and how to change your database to use it. Today we will discuss a possible problem you may encounter when you do when programming on Ruby on Rails. The error looks something like this:

$ rake db:setup

Mysql::Error: Specified key was too long; max key length is 767 bytes:
CREATE UNIQUE INDEX unique_schema_migrations ON schema_migrations (version)

The problem exists because the utf8mb4 character set uses the full 4 bytes per character rather than the 1-3 of UTF8 (the character set most people mistakenly use thinking they'll have full Unicode compliance). Because of this extra size, the schema_migration may no longer fit.

This small patch will set default mysql string column length to 191 instead of 255 which is the new index limit on utf8mb4 (aka real utf8).

# config/initializers/mysqlpls.rb
require 'active_record/connection_adapters/abstract_mysql_adapter'

module ActiveRecord
  module ConnectionAdapters
    class AbstractMysqlAdapter
      NATIVE_DATABASE_TYPES[:string] = { :name => "varchar", :limit => 191 }
    end
  end
end

 

Using Ruby’s Metaprogramming to Initialize an Object From a Hash

Using Ruby’s Metaprogramming to Initialize an Object From a Hash

Consider the code:

class A
  attr_accessor :b, :c, :d, :e, :h, :i, :x
end

Now imagine that you want to initialize each instance variable to the one that has the same name in the hash.. Imagine all the repetitive and crappy code that would generate.

But this is Ruby and with Ruby there is *nearly* always a better way.  Instead, meta-program it, and mix-it-in.

module constructed_from_hash
 def initialize(h)
  h.each { |k, v| send("#{k}=", v) }
 end
end

class A
 include constructed_from_hash
 attr_accessor :b, :c, :d, :e, :h, :i, :x
end

Nice, elegant and clean. Just the way Ruby code is supposed to be. AND this code will now scale, as more accessors are added to the object over time, the constructor too, wont need reprogramming. If you don't need to do this often, you can pull just the constructor out of the module and put it directly into the class, but this way provides the most flexibility.

Header image taken from Examining Dwemthy’s Array composite pattern. An interesting read in it's own right. check it out.

Ruby Script to Import Google Contact Photos From Gravatar

Google Contact photos are a much neglected feature of the Google Stack. It really adds to the user experience when you see each of your contact photos when you make or receive a call. However, it can be a real pain (especially if you have hundreds of contacts).

But I had an idea recently, to try and match my Google Contact emails with Gravatar and try to auto-populate some of the dozens of contacts that didn't already have a photo (after all a Gravatar is better than nothing).

So I wrote a Ruby script to find my contacts missing a photo and try to update it with a Gravatar (wherever possible). NB: You may need to first install the GData (Google Data) gem by opening a Terminal window and issuing: sudo gem install gdata.

  1. #!/usr/bin/env ruby
  2.  
  3. # Google Contact Photos - Gravatar Importer
  4. # Written by Ashley Angell
  5. # http://ashleyangell.com
  6. # Licenced under Creative Commons with Attribution
  7.  
  8. require "rubygems"
  9. require "gdata"
  10. require "rexml/document"
  11. require "digest/md5"
  12. require "net/http"
  13. include REXML
  14.  
  15. none = 'd5fe5cbcc31cff5f8ac010db72eb000c'
  16. user = ARGV[0]
  17. pass = ARGV[1]
  18.  
  19. client = GData::Client::Contacts.new
  20. client.clientlogin(user, pass)
  21. data = client.get("https://www.google.com/m8/feeds/contacts/#{user}/full?max-results=10000")
  22. myxml = Document.new data.body
  23. p "contacts"
  24. puts "-"*70
  25. i = 0
  26. myxml.each_element("feed/entry") do |e|
  27. begin
  28. gd = e.elements['gd:email']
  29. if !gd.nil?
  30. email = gd.attributes['address'].downcase
  31. hash = Digest::MD5.hexdigest(email)
  32. image_src = "http://www.gravatar.com/avatar/#{hash}"
  33. nil_image = false
  34. image_element = e.get_elements("link[@rel='http://schemas.google.com/contacts/2008/rel#photo']")[0]
  35. if !image_element.nil? and image_element.attributes['gd:etag'].nil?
  36. data = nil
  37. md5 = nil
  38. Net::HTTP.start(URI.parse(image_src).host) do |http|
  39. resp = http.get(URI.parse(image_src).path)
  40. data = resp.body
  41. md5 = Digest::MD5.hexdigest(data)
  42. File.open("#{email}.png", 'w') do |f|
  43. f.puts data if md5 != none
  44. end
  45. end
  46. md5 = Digest::MD5.hexdigest(data)
  47. if md5 != none
  48. puts "#{email} > #{image_src}"
  49. client.put_file(image_element.attributes['href'], "#{email}.png", 'image/png')
  50. i = i + 1
  51. else
  52. puts "#{email} > no match"
  53. end
  54. else
  55. puts "#{email} > skipped (already has photo)"
  56. end
  57. File.delete("#{email}.png") if File.exists?("#{email}.png")
  58. end
  59. rescue Exception => ex
  60. puts ex
  61. end
  62. end
  63. puts "Updated #{i} contact photos"

To execute it, simply copy and paste this into a text editor (or download it and unzip) and from Terminal (command) window and execute the following commands:

  1. sudo chmod +x googlegravatarimporter.rb [Enter]
  2. ./googlegravatarer.rb your.address@gmail.com your_password [Enter]

It will cycle through your Google Contacts and indicate what action was taken. For me, surprisingly updated a few dozen contacts (even more than I expected).

I've posted this here for others that might want to do the same thing but cannot be bothered writing the script for it. Consider it posted here under Creative Commons with Attribution.

'File not found: lib' Error installing Rails Gem

I recently had a problem trying to install Rails 3 on my MacBook with a fresh OSX buying cialis online Snow Leopard:

  1. sudo gem install rails<br />
  2. Password: {entered}<br />
  3. Successfully installed rails-3.0.7<br />
  4. 1 gem installed<br />
  5. Installing ri documentation for rails-3.0.7...<br />
  6. File not found: lib

Turns out this is a somewhat common problem.  But it seems that the solution is easy, just manually reinstall RDoc. To do this run these 3 commands:

  1. sudo gem install rdoc-data<br />
  2. sudo rdoc-data --install<br />
  3. sudo gem rdoc --all --overwrite

The last line in particular will re-generate all the documentation for your installed gems (including Rails) and can take a while, but you should be able to confirm the fix by reissuing the Rails gem install command:

  1. sudo gem install rails

shows that rails now installs properly and says that it has installed both ri and RDoc documentation without issue.

Using Rails’ Flash Messages with AJAX Requests

Have you ever wondered how to get access to the Ruby on Rails' flash message when performing a AJAX or restful web request?  You might hit yourself on the head when you discover how easy it is.  Simply append the flash message to the Response headers.  You could even wrap this in a helper, and using an after_filter to automatically add the header for you on every AJAX response.

  1. class ApplicationController < ActionController::Base
  2. after_filter :flash_headers
  3.  
  4. def flash_headers
  5. # This will discontinue execution if Rails detects that the request is not
  6. # from an AJAX request, i.e. the header wont be added for normal requests
  7. return unless request.xhr?
  8.  
  9. # Add the appropriate flash messages to the header, add or remove as
  10. # needed, but I think you'll get the point
  11. response.headers['x-flash'] = flash[:error] unless flash[:error].blank?
  12. response.headers['x-flash'] = flash[:notice] unless flash[:notice].blank?
  13. response.headers['x-flash'] = flash[:warning] unless flash[:warning].blank?
  14.  
  15. # Stops the flash appearing when you next refresh the page
  16. flash.discard
  17. end

And then you just read the header with whatever you happen to be reading it with. For completeness sake here is an example of how to read the header in JavaScript using Prototype:

  1. new Ajax.Request('/your/url', {
  2. onSuccess: function(response) {
  3. var flash = response.getHeader('x-flash);
  4. if (flash) alert(flash);
  5. }
  6. });

Forget the UML Module for NetBeans!

A while ago, I wrote a blog post on how, with considerable effort, you can get a native UML NetBeans module up and running despite the NetBeans UML module being removed from the standard distribution.

I managed to get mine working, but there is a huge cost - Once you close the project (or the IDE) housing the diagram, you can never reopen it.  Out of pure determination desperation and perseverance I managed to get the diagram I needed, printed and done; but I can never open it and make adjustments.

Apparently, we're all supposed to use SDE for NetBeans by Visual Paradigm now as the "official" replacement, but I tried it, and it was simply fail.  Proprietary and fail.

Fortunately, after taking a punt, I found a UML modelling tool which is not only more functional and better than the NetBean's module was, but looks better too.  It even has the ability to create code from class diagrams (which you can obviously just cut and paste into your NetBeans IDE project of choice.  Its called ArgoUML.

ArgoUML is the leading open source UML modeling tool and includes support for all standard UML 1.4 diagrams. It runs on any Java platform and is available in ten languages.

I've used it a bit now, and I just love it.  I particularly like the way it can make recommendations on how to improve your diagram using its "critics" system.

It's features boast:

  • All 9 UML 1.4 Diagrams supported
  • Platform Independent: Java 5+
  • Click and Go! with Java Web Start
  • Standard UML 1.4 Metamodel
  • UML Profile support with profiles provided
  • XMI Support
  • Export Diagrams as GIF, PNG, PS, EPS, PGML and SVG
  • Available in ten languages - EN, EN-GB, DE, ES, IT, RU, FR, NB, PT, ZH
  • Advanced diagram editing and Zoom
  • OCL Support
  • Forward Engineering
  • Reverse Engineering / Jar/class file Import
  • Cognitive Support
    • Reflection-in-action
      • Design Critics
      • Corrective Automations (partially implemented)
      • "To Do" List
      • User model (partially implemented)
    • Opportunistic Design
      • "To Do" List
      • Checklists
    • Comprehension and Problem Solving
      • Explorer Perspectives
      • Multiple, Overlapping Views

I haven't yet worked out how to create object instances from my class diagrams yet, so I'm not sure if it just doesn't support this or it's user error, but in every other conceivable way, it seems to be an excellent UML modelling application for virtually every OS you can name.

Getting SSI to work in MAMP

It's no secret that I adore my Mac, mostly because it just makes my life easier.  I enjoy the security of OSX, I love it's responsiveness and I love that my operating system doesn't punish me for installing applications and development stacks just to 'play with them'.  A while ago, while looking for a stack that would let me quickly and effortlessly get Apache, MySQL and PHP5 working together without having to muss about with configs and the such, I discovered MAMP and frankly, I adored it instantly.  After a rather large download, it was effortless to install and running it was a cinch.  And better still, the server applications only run when you open the MAMP application and tell them to run, so that you dont loose vital system resources running services you dont need.

Additionally, my IDE of choice, NetBeans can integrate directly with MAMP, so that when you create (for sake of argument) a new PHP project and run it, it automatically puts the project files into the MAMP Apache directory (to be honest you do need to configure the path when you create the project, but its no big deal) making development painless and convenient.

But I did hit a snag recently when for a university assignment I was required to do a XHTML website using HTML Server Side Includes.  I was shocked when I ran my website and my SSI didnt work.

But there is a solution.

To make .shtml work, I deleted the comment-symbols ( # ) in the file http.conf (find it in /Applications/MAMP/conf/apache/ and at the time of writing was near lines 982:

# To parse .shtml files for server-side includes (SSI):
# (You will also need to add "Includes" to the "Options" directive.)
#
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml

Download Microsoft .NET Framework 3.5 SP1 Standalone Full Redistributable Setup Installer

Many applications uses Microsoft .NET Framework 3.5 as development platform, and viagra for sale in uk thus requires .NET Framework to be installed beforehand, else the installation will request to download and install .NET Framework from Internet. On offline system without Internet access or online server with slow downloading speed, the requirement to download setup files through web may hit the wall – a no go.

kamagra shipping

Microsoft initially just provides a minimal size dotnetfx35setup.exe download which is a bootstrapper that will still need to download more files via Internet. For users who prefer to perform offline installation or install .NET Framework 3.5 SP1 without waiting for download to complete will have to download and save a copy of full complete standalone or redistributable Microsoft .NET Framework 3.5 SP1 setup installer, which is finally published by Microsoft.

Microsoft .NET Framework 3.5 SP1 (Service Pack 1) is a full cumulative update that contains many new features building incrementally upon .NET Framework 2.0, 3.0, 3.5, and includes cumulative servicing updates to the .NET Framework 2.0 and .NET Framework 3.0 subcomponents. See KB951847 for list of changes and fixed issues in the .NET Framework 3.5 Service Pack 1.

Download full package of Microsoft .NET Framework 3.5 SP1: dotnetfx35.exe (231 MB)

For known issues and release notes, refer to Microsoft .NET Framework 3.5 SP1 Readme.

Native UML Module for NetBeans

UPDATE: There is a more recent post regarding the Native UML module for NetBeans here.

I have been a long time user of NetBeans IDE. I really like the simplicity and how it is almost an all-purpose IDE for virtually any language you can think of.

However, I was horrified recently when I upgraded to version 6.8, to discover that the UML module was gone, and instead NetBeans insisting I use a third-party UML generator.  So I tried it, and hated it immediately.  I considered rolling back to an earlier version, but first I thought I would try a little voodoo.

I noticed that version 6.9 was released and so I downloaded it, and installed as per normal.  I then found this page (the 6.9 release candidate zip download page) which listed a file called 'netbeans-6.9-201005312001-ml-uml.zip'.  Ah ha.  Since I am on OSX, I opened the package contents up from Applications, unzipped the uml.zip file and dropped the new UML directory into the installation directory.  I started up NetBeans and voila:

I tested the new project, and it worked like a treat (some people who tried various other hacks reported that even though the project appeared, there was issues saving/opening them).

I hope this works for you too, and of course make sure you backup any existing projects - dont come crying to me if you destroy your work trying to implement this!

Extracting Specific Date-time Components in Postgres

When programming, sometimes it's useful to extract various time components from a Date-time field in SQL queries.  For example, you might want to filter the date field by, hour, or year (or both).  Fortunately, Postgres has a easy way to pull this data out within the query itself:

  1. SELECT EXTRACT(hour FROM a_datetime_field) FROM a_table;

If the field was the value '4/5/2009 13:09:00' then that above query would return "13" in the select.

generic for paxil

In a stranger, practical example, I was moving a database from one server to another and for some unknown reason, all the dates in a table were fudged so that instead of being the year 2009, it was 142009, and the seconds were also stuffed up - the result being that any queries I ran against the table threw ADO.NET exceptions because the dates couldn't be parsed properly.  I needed to run a query like this one to set things right again:

  1. UPDATE atable
  2. SET datetimeadded = cast( '2009-' || EXTRACT(month FROM datetimeadded) || '-' ||
  3. EXTRACT(day FROM datetimeadded) || ' ' || EXTRACT(hour FROM datetimeadded) || ':' ||
  4. EXTRACT(minute FROM datetimeadded) AS timestamp),
  5. datetimeupdated =  cast('2009-' || EXTRACT(month FROM datetimeupdated) || '-' ||
  6. EXTRACT(day FROM datetimeupdated) || ' ' || EXTRACT(hour FROM datetimeupdated) || ':' ||
  7. EXTRACT(minute FROM datetimeupdated) AS timestamp);

The casts are needed to get the update to cooperate, but basically this recreates the date time piece-by-piece based on the original date-time value.