MySQL Gem Installation Under RedHat Enterprise Linux

Posted by Tres Mon, 03 Nov 2008 09:34:00 GMT

Installing the mysql Gem under RHEL/CentOS requires you to specify where MySQL is installed. Just point Gem to the mysql-config bin & you’re good to go:

gem install mysql -- --with-mysql-config=/usr/bin/mysql_config

Posted in , , ,  | Tags , , ,

Pushing a Branch Back to a Git Project Repository

Posted by Tres Sat, 18 Oct 2008 03:41:00 GMT

As a former SVN-evangelist, I can say that I came to Git with quite a bit of speculation – wondering why we need just another revision control system. Subversion already did everything we needed – so why mess around with something else.

After using Git for the last few months, I can say that I’m truly won-over. It seems like more-of-the-same at the outset, but as you get deeper into it, it really proves to be one of those really well thought out things you run into every once in a while; I’d liken the move from Subversion to Git something akin to the move from Procedural to Object Oriented Programming. Once you ‘get it,’ there’s really no going back.

Anyway, on to the point of all this.

So you use git push to push a branch you’ve created back up to the project repository.

git push origin DescriptiveBranchName

Posted in  | Tags , , ,

Using Mixins With Rails

Posted by Tres Thu, 28 Aug 2008 12:53:00 GMT

Mixins are one of the most powerful constructs that Ruby provides. Mixins give you the power of multiple inheritance without all the inherent complexities and problems associated with multiple inheritance. The best part of using mixins is how extremely simple they are to use. Just include the module you want to mixin and then call any of the functions defined in the module.

Using mixins with rails is just as easy, the only problem is figuring out where to put your mixin (opinionated programming, you know). Just put your mixin into the lib directory of your rails project and you’ll be good to go. Once you’ve got the file in the right spot, just

  require 'module_file_name'
  include ModuleName

Then call the function you want to use, and you’re set.

Posted in , ,  | Tags ,

Using Amazon S3 With Loaded Flash Images

Posted by Tres Fri, 15 Aug 2008 18:00:00 GMT

Security policies in flash require that images be loaded from the same domain as the swf file is hosted on. This doesn’t really become an issue until you’re using BitmapData.draw() to convert the flash vector image into a raster graphic.

If you’re seeing SecurityError: Error #2122 when attempting to use BitmapData.draw(), you can fix this by setting up a Policy file on S3 for your bucket.

Now you might be saying, “I don’t have access to anything outside my bucket, how can I set up a file named crossdomain.xml in the root level of s3.amazonaws.com?” Well, never fear, Amazon has already given us a way to access buckets via vhost name. Just use bucket_name.s3.amazonaws.com to access your files, and you’re golden.

Update 15 Aug 2008

My friend, Lyle just wrote to say that you can also use a CNAME with s3 to have the same effect:

BTW, if you set up a CNAME to point to s3.amazonaws.com and create a bucket with the same name, you can access it that way as well. i.e. http://s3.vmann.net/public_key.asc is my gpg public key, stored in bucket named ‘s3.vmann.net’

Posted in ,  | Tags , , , ,

Rake Tasks to Simplify Seed Data Management in Rails

Posted by Tres Tue, 12 Aug 2008 13:34:00 GMT

Here’s a couple of snippets of goodness – rake seed:dump and rake seed:load

If you’re using yaml fixtures to store seed data for quick db deployment, then these should help out. If you’re still trying to manage seed data with your migrations, you might want to look into using yaml files instead. These rake tasks use a db/fixtures folder by default.

Put these tasks into the lib folder of your rails project.

Here’s dump.rake

namespace :seed do
  desc 'Dump a database to yaml fixtures.  Set environment variables DB
      and DEST to specify the target database and destination path for the
      fixtures.  DB defaults to development and DEST defaults to RAILS_ROOT/
      db/fixtures.'
      task :dump => :environment do
        path = ENV['DEST'] || "#{RAILS_ROOT}/db/fixtures"
        db   = ENV['DB']   || 'development'
        sql  = 'SELECT * FROM %s'

        ActiveRecord::Base.establish_connection(db)
        ActiveRecord::Base.connection.select_values('show tables').each do |table_name|
          i = '000'
          File.open("#{path}/#{table_name}.yml", 'wb') do |file|
            file.write ActiveRecord::Base.connection.select_all(sql %
      table_name).inject({}) { |hash, record|
              hash["#{table_name}_#{i.succ!}"] = record
              hash
            }.to_yaml
          end
        end
      end

      # ActiveRecord::Base.connection.select_values('show tables')
      # is mysql specific
      # SQLite:  ActiveRecord::Base.connection.select_values('.table')
      # Postgres
      # table_names = ActiveRecord::Base.connection.select_values(<<-end_sql)
      #    SELECT c.relname
      #    FROM pg_class c
      #      LEFT JOIN pg_roles r     ON r.oid = c.relowner
      #      LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
      #    WHERE c.relkind IN ('r','')
      #      AND n.nspname IN ('myappschema', 'public')
      #      AND pg_table_is_visible(c.oid)
      # end_sql
end

and here’s load.rake

namespace :seed do
  desc "Load seed fixtures (from db/fixtures) into the current environment's database."
  task :load => :environment do
    require 'active_record/fixtures'
    Dir.glob(RAILS_ROOT + '/db/fixtures/*.yml').each do |file|
      Fixtures.create_fixtures('db/fixtures', File.basename(file, '.*'))
    end
  end
end

Posted in ,  | Tags , , ,

Restore Deleted Files With Git

Posted by Tres Tue, 12 Aug 2008 13:28:00 GMT

This one is pretty easy, but for the fact that the built-in help doesn’t mention git ls-files.

To view deleted files use git ls-files –deleted

To restore deted files just use git checkout – <deleted_file>

Too easy.

Posted in  | Tags , , ,

Creating XML With Rails 2.1

Posted by Tres Sun, 10 Aug 2008 18:08:00 GMT

So there’s lots of documentation out there on creating XML via Rails. The problem is that it’s not really kept up with all the changes that have occurred. Here’s a few quick items that may be helpful when creating XML with Rails 2.1.

• When creating an instance of XMLBuilder, use ::Builder::XmlMarkup.new instead of Builder::XmlMarkup.new.

• When creating your view, use the extension .xml.builder instead of .xml.erb

• When rendering the template from the controller, make sure that the content type headers are set for xml and that you’re not rendering the layout. The controller should have a section that looks something like this:


    headers["Content-Type"] = "text/xml"

    respond_to do |format|
      format.xml { render :template => 'options.xml.builder', :layout => false }
    end

Posted in , ,  | Tags ,

Edge Rails and DB Migrations Getting "DEFAULT NULL NULL"

Posted by Tres Fri, 08 Aug 2008 07:04:00 GMT

It appears that in cases where :null => false is set for any column in a migration, the entire migration requires the newer migration syntax. Edge rails enforces the new syntax for migrations, not by failing to run, but by creating an invalid SQL statement.

So, a statement like this:

     t.column :buzzword_level_id, :string

will end up as SQL like this:

    `buzzword_level_id` varchar(255) DEFAULT NULL NULL

and will promptly bomb out. Google is more confusing than helpful in this instance because this was formerly a bug that affected all migrations, and was recently fixed; however, the fix relies upon using the new syntax for migrations. So, rewriting the migration like this:

      t.string :buzzword_level_id

fixes the problem.

Posted in ,  | Tags , ,

Read error: Errno::EPERM: Operation not permitted When Using Mongrel

Posted by Tres Thu, 17 Jul 2008 08:23:00 GMT

It’s always the little things…

So I’m setting up rails and nginx on my production server, everything is humming along. I set up monit to start and monitor the mongrel instances, set up nginx and set up the reverse proxy, and then I try accessing my app and see this in the logs:

Wed Jul 16 15:34:05 -0700 2008: Read error: #
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel/http_response.rb:137:in `write'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel/http_response.rb:137:in `write'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel/http_response.rb:95:in `send_header'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel/http_response.rb:146:in `finished'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel.rb:165:in `process_client'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel.rb:285:in `run'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel.rb:285:in `initialize'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel.rb:285:in `new'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel.rb:285:in `run'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel.rb:268:in `initialize'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel.rb:268:in `new'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel.rb:268:in `run'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel/configurator.rb:282:in `run'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel/configurator.rb:281:in `each'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel/configurator.rb:281:in `run'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/mongrel_rails:128:in `run'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel/command.rb:212:in `run'
/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/mongrel_rails:281

Since I’m running this in a FreeBSD Jail, I assume that it’s access to something in /dev. I look at the rails installation that was done via ports and start upgrading gems and looking at all the easy stuff.

Finally, I look at

/usr/local/lib/ruby/gems/1.8/gems/mongrel-1.1.5/bin/../lib/mongrel/http_response.rb:137:in `write'

Here’s the function Mongrel is complaining about:

  def write(data)
      @socket.write(data) # <== here's line 137
      rescue => details
      socket_error(details)
    end

Ye olde firewall problem…

So I had some rules set up to pass all internal traffic across my jailed servers on my FreeBSD server through the firewall, something like this:

pass quick all on $external_interface from self to any modulate state

This was to be a little “safety rule;” something that would keep things open even if something was added later on to block a set of ports globally.

This was setting up a race condition with the state table and ultimately had the effect of almost always killing mongrel connections both directly and through the nginx load balancer.

Posted in , , ,  | Tags , , ,

Rails 2.1.0 and mysql_bigint Plugin Don't Get Along

Posted by Tres Thu, 10 Jul 2008 07:57:00 GMT

Introduced with Rails 2.1.0 were a whole host of cool new things, like git plugin installation and better migration management. Also introduced was the idea of “smart integer columns,” which will automatically decide whether a int type should be tinyint, smallint, mediumint, int, or bigint just by passing an integer value with the :limit option.

“Cool,” you might be saying, “they’re getting the mysql activerecord adapter and the postgres adapter in sync. I no longer need to worry about making database specific migrations if I’m using 64 bit integers!! How can there be anything bad about that?”

So the problem with the “smart integer columns” implementation is that it uses the same syntax as the postgres adapter , but the interpretation of the values is completely different. The postgres adapter and mysql_bigint plugin use bytes to identify the integer type. Smart integer columns simply interprets the integer value as the display width of the integer.

This has already been fixed in EDGE rails, so the good news is, the mysql_bigint plugin won’t be necessary for much longer.

Posted in  | Tags , ,

"Identifier name is too long" When Indexing Multiple Columns In MySQL With ActiveRecord

Posted by Tres Thu, 03 Jul 2008 00:29:00 GMT

MySQL has a 100 character limit on the length of the name of an index, which ActiveRecord will cross when creating an index for a table that has multiple foreign keys and other data that is to be indexed. If you’re seeing a message like the following when building indexes:

Mysql::Error: #42000Identifier name 'index_duper_on_us_id_and_hair_id_and_leaf_id_and_number_id_and_super_id_and_created_at_and' is too long: 
CREATE  INDEX `index_duper_on_us_id_and_hair_id_and_leaf_id_and_number_id_and_super_id_and_created_at_and_completed` ON `duper` 
(`us_id`, `hair_id`, `leaf_id`, `number_id`, `super_id`, `created_at`, `completed`)

just manually assign a name to the index by appending :name => “[MANUALINDEXNAME_HERE]” to the index you’re creating. So in our example above, the line in the migration would look like this:

  add_index :duper, [:us_id, :hair_id, :leaf_id, :number_id, :super_id, :created_at, :completed], :name => "duper_index"

Posted in ,  | Tags , ,

gem update One-Liner To Update Everything

Posted by Tres Wed, 14 May 2008 01:44:00 GMT

Here’s an easy one-liner to get ruby gem and all installed gems up to the latest available version:

gem update -y --system --include-dependencies && gem update -y --include-dependencies

Newer versions of gem include dependency installs and are not interactive, so you don’t need to use the flags outlined above. Just use:

gem update --system && gem update

Posted in ,  | Tags , , , ,

MacPorts Breaks After Trying to Remove Corrupt Archive

Posted by Tres Wed, 14 May 2008 00:51:00 GMT

I’m a big fan of package management systems for installing and managing everything on a *nix system. From portupgrade on FreeBSD to yum/RPM on RedHat, I use the package management system to install and maintain everything I possibly can.

On OS X, I’ve been using MacPorts back since they were Darwin Ports, and before that I was using Fink. MacPorts closely resembles portupgrade on FreeBSD.

MacPorts is generally excellent, especially because everything is tucked away in opt, so if I ever decide that I don’t want MacPorts around anymore, I have one place to go to get rid of everything.

Anyway, today was the first time I really had an issue with MacPorts. Trying to get Mysql5 installed on my laptop, I happened to download a corrupt tar archive.

sudo port install mysql5
--->  Fetching mysql5
--->  Attempting to fetch mysql-5.0.51.tar.gz from http://mysql.mirrors.pair.com/Downloads/MySQL-5.0/
--->  Attempting to fetch mysql-5.0.51.tar.gz from http://mysql.he.net/Downloads/MySQL-5.0/
--->  Verifying checksum(s) for mysql5
Error: Checksum (md5) mismatch for mysql-5.0.51.tar.gz
Error: Checksum (sha1) mismatch for mysql-5.0.51.tar.gz
Error: Checksum (rmd160) mismatch for mysql-5.0.51.tar.gz
Error: Target org.macports.checksum returned: Unable to verify file checksums
Error: Status 1 encountered during processing.

My response was to clean out the distfiles, like I would with FreeBSD. I thought I’d be nice and use the built-in port clean instead of just removing the downloaded file:

sudo port clean mysql5
--->  Cleaning mysql5

But that just made MacPorts angrier:

sudo port install mysql5
--->  Verifying checksum(s) for mysql5
Error: Target org.macports.checksum returned: Could not open file: /opt/local/var/macports/distfiles/mysql5/mysql-5.0.51a.tar.gz
Error: Status 1 encountered during processing.

The key was to use the –all flag on the port clean command:

sudo port clean --all mysql5

Posted in ,  | Tags

Root Permissions Required to Send ICMP Echo Request From Java using java.net.InetAddress

Posted by Tres Mon, 12 May 2008 09:31:00 GMT

Since Java 5, we’ve been able to send ICMP Echo requests using java.net.InetAddress; however, under *nix like systems, you’ll need root level permissions to get things running. If you don’t have the correct system permissions, java.net.InetAddress will silently fail, letting you know that every single host you attempt to test is down.

The following utility will do an ICMP Echo check & ensure that the user running the utility has the correct permissions.



import java.net.*;
import com.sun.security.auth.module.UnixSystem;

/**
 *
 * @author Tres Wong-Godfrey
 */
public class IcmpEcho {

    public static void main(String[] args) {
        String host = null;
        int timeOut = 3000;
        boolean isUp = false;
        boolean validRequest = true;
        String output = "";
        long uid = -1;

        UnixSystem user = new UnixSystem();
        uid = user.getUid();

        if (args.length != 1) {
            System.out.println("ICMP echo check requires a single argument -- the hostname");
            System.exit(1);
        }

        if (uid != 0) {
            System.out.println(" ICMP echo check requires root permissions");
            System.exit(2);

        }

        host = args[0];
        try {
            isUp = InetAddress.getByName(host).isReachable(timeOut);
        } catch (SecurityException $e) {
            System.out.println(" ICMP echo check requires root permissions");
            validRequest = false;

        } catch (UnknownHostException $e) {
            System.out.println(" Unknown host: " + host);
            validRequest = false;

        } catch (Exception $e) {
            System.out.println("Unknown error");
            $e.printStackTrace();
            validRequest = false;

        }

        if (validRequest == true) {
            output = (isUp == true) ? host + " is up" : host + " is down";
        }
        System.out.println(output);

    }
}


Posted in ,  | Tags ,

Serializing Objects Into Session Data For Object Persistence in PHP

Posted by Tres Sun, 11 May 2008 14:18:00 GMT

One of the biggest problems that we find in the realm of PHP web applications is that there is no native object persistence between page requests. Clients getting around in a PHP application normally means instantiating and re-instantiating objects as needed. A page that needs access to the Client object wound create a new Client() every time client data were needed, or keep a bunch of global variables held in session data.

Because of the way some web applications are engineered, for some unfortunate databases, this meant that every page hit was another call to the database to populate the instance variables associated with the current client. For some unfortunate web app maintainers, this meant that they needed to figure out why their global session variable wasn't returning expected results.

An easy way to get around this is to use session variables to store objects. It is almost just like object serialization to a file in Java; however, PHP won't serialize anything but the single object you want to store; it doesn't take care of class parents, interfaces being implemented or any other instantiated objects that may be required to maintain state. In PHP the developer is responsible for making sure that any object dependencies are also serialized and de-marshalled as needed.

The upside is that PHP will not only allow you to serialize your objects, but makes the serialization, marshaling process automatic.

So if you're using sessions for your site anyway, you can get object persistence for free. Just assign your object by reference to the session variable that you want to use. So, for our Client example above, we'd do something like this:

$client_object = &$_SESSION['client_object'];
$client_object = new Client( $client_id );

print( "First Name: " . $client_object->getClientFname() . "\n" );
print( "Last Name: " . $client_object->getClientLname() . "\n" );
print( "Balance Due: " . $client_object->getClientBalance() . "\n" );

One caveat here is that your class must be defined before the session_start() function call is made in your program. This is easy if you're using an __autoload() function to provide access to your classes; just place the session_start() call after your __autoload() and everything should Just Work.

Posted in ,  | Tags , , ,

Older posts: 1 2 3 4 ... 7