Advertise here!

It Isn't "Zero Deploy"

Patrick Peak has written up an article with his thoughts after attending a presentation by David Geary about Rails. In the presentation David said that Rails was “zero deploy time”.

The quote is misleading, and Patrick was mislead. Rails is not zero deploy, it’s “zero compile”. The difference is that you can edit a file in development and reload your browser to get the changes – there’s no intermediate compilation. The Java world has on-the-fly compilation of JSPs and some can even do .java – but the fact remains there’s a an intermediate compilation step, and that not every Java developer has the environment or toolset to do that on-the-fly compilation (or probably more likely, most don’t).

Patrick went on to assume all sorts of bad practices were common amongst rails programmers, but we’ll just be nice and say that he was mislead by the quote and be done with the whole affair. (He also erroneously noted that there’s nothing like Ant for Ruby. First, Ant isn’t particularly language-specifc. Beyond that, Rake is an excellent tool for Ant-like tasks that uses Ruby code as declarations – not XML).

Rails deployment is probably remarkably similar to any other language. You work in development mode locally, test your changes, and eventually push the changes to the server. A good discussion of this is written up by Jamis Buck.

I’m looking forward to see the release of the “release manager.” It’s certain to make it easier to practice good deployment techniques with Rails.

Update: It appears that this has also been commented on by DHH, Dave Thomas, and the original Ant (and Tomcat) author himself, James Duncan Davidson (who also goes into details about how he and Mike Clark of Pragmatic Automation fame deploy their rails app.)

Posted at 7pm on 07/15/05 | Posted in , , , | no responses | read on

Ruby, Rails and DoubleRenderErrors... Oh my!

There's a new "feature" that's been added in Rails 0.13.0 that is a bit of a hack to fix behavior that a lot of people didn't feel was correct. In Rails, you can actually call a redirect or render method and instead of returning immediately Rails will continue execution until it hits the end of the method or an explicit return.

I think the Rails developers did the right thing in adding the new exception, because almost all users expected that a render or redirect would immediately return - I know I did. It also affords any strange hacks out there that wanted this behavior to still achieve it by catching the exception and ignoring it. In any case, I'd agree that this behavior should have been built into the render and redirect actions from the beginning. I can't really think of any situation where you'd want to render/redirect and then continue to execute...

Posted at 2pm on 07/11/05 | Posted in , , | no responses | read on

Database conversion

Following on the heels of my earlier entry about db_structure_dump, I’ve created another small useful Ruby script.

As I said before, my production databse is Oracle 10g and so is my own development database - but the development databases of the others helping out are MySQL. Now that I can dump the CREATE TABLE statements for my Oracle databases I need some way to convert back and forth between MySQL and Oracle syntax – since both aren’t really standard. Or at least I need to be able to dump my development oracle DB to SQL and then convert it to MySQL for the others.

Below is the hack I created that will take an Oracle database’s structure (or  sqlite, odbc, mssql and mysql)and convert it to standard SQL, then to MySQL syntax(since MySQL can’t handle VARCHAR’s longer than 255, for intance).

The code is not generic enough to be useful for everyone, but should give a good start. Watch out if you:

  • Don’t use ID as your primary key. This is assumed right now, but a smarter script could check for keys.
  • Actually use NUMBER in Oracle as a DECIMAL (and want to retain that in MySQL, rather than have it converted to INTEGER).
  • Have join tables (since usually you won’t use ID as the primary key, you’ll have to manually fix the primary key).

 

class SQLStandardizer

def initialize(type, source)
    @data_type, @data = type, source
    init_substitutions
  end     
    
  # Convert data to compatible SQL
  def convert
    replacements = @subst[@data_type]
    new_data = @data
    replacements.each do |original, replacer|
      new_data.gsub!(original, replacer)
    end
    new_data
  end    
  
   # Initialize the substitution array
  private
  def init_substitutions
    @subst = {}
    @subst['mysql'] = {"int"=>"INTEGER","dec"=>"DECIMAL"}
    @subst['oracle'] = {"BFILE"=>"BLOB",
 				"CLOB"=>"TEXT",
 				"DATE"=>"DATETIME",
 				"LONG"=>"BIGINT",
 				"LONG RAW"=>"BIGINT",
 				"NCHAR"=>"CHAR",
 				"NCLOB"=>"TEXT",
 				"NUMBER"=>"DECIMAL",
 				"NVARCHAR2"=>"VARCHAR",
 				"RAW"=>"BLOB",
 				"VARCHAR2"=>"VARCHAR",
 				"DOUBLE PRECISION"=>"DECIMAL",
 				"\r\nLOGGING"=>"",
 				"\r\nNOCACHE"=>"",
 				"\r\nNOPARALLEL"=>"",
 				" BYTE"=>""}
    @subst['odbc'] = {"LONGCHAR"=>"BLOB"}
    @subst['sqlite'] = {"INTEGER(10)"=>"INTEGER"}
    @subst['mssql'] = {"nvarchar"=>"VARCHAR",
				"nchar"=>"CHAR",
				"int identity"=>"INTEGER",
				"ntext"=>"TEXT",
				"int"=>"INTEGER",
				"image"=>"LONGBLOB",
				"money"=>"FLOAT" }
  end
end

class DBSpecializer
  def initialize(type, source)
    @data_type, @data = type, source
  end
  
  # Right now we can only convert to MySQL
  def convert
    return @data if @data_type != 'mysql'
    new_data = @data.gsub(/VARCHAR\((\d+)\)/) do |match|
      length = $1.to_i
      if length > 255
        'TEXT'
      else
        "VARCHAR(#{length})"
      end
    end
    # We don't really use decimals
    new_data.gsub!('DECIMAL', 'INTEGER')
    # Make primary keys auto-incremented
    new_data.gsub!(' ID INTEGER NOT NULL', ' ID INTEGER NOT NULL AUTO_INCREMENT')
    # Set up primary key and initial auto-increment value
    # FIXME What if our primary key is not ID?
    new_data.gsub!(');', ",\n PRIMARY KEY (`id`)\n) AUTO_INCREMENT=1;")
    new_data
  end
end


if __FILE__ == $0
  from = 'oracle'
  to = 'mysql'
  source_file = 'production_structure.sql'
  output_file = "converted_#{source_file}"
  source = open(source_file) do |f|
    f.readlines.join
  end
  # Convert from oracle to mysql
  standardized = SQLStandardizer.new(from, source).convert
  converted = DBSpecializer.new(to, standardized).convert
  open(output_file, 'w') do |f|
    f << converted
  end
end
Posted at 3pm on 07/08/05 | Posted in , , | no responses | read on

Rails 0.13.0 Released

Don’t be late to the party! Go get Rails 0.13.0 now and be the coolest kid on your block for 3.412 seconds.
Posted at 7pm on 07/06/05 | Posted in , , , | no responses | read on

Older posts: 1 ... 6 7 8 9