Archive for July, 2007

Weirdness Problem Solved!!!

When I posted at the Rails-Forum, I also emailed the internal DevChix list (sorry boys!) because I was totally at wits end about this problem. (got no response from Rails-Forum BTW) and at least I got some ideas...

Jen-Mei said to try this:

RUBY:
  1. Out of curiosity, when you run the Ruby console, what do you get when
  2. you type:
  3.  
  4. ActiveRecord::Base.connection.native_database_types[:string]
  5.  
  6. or just
  7.  
  8. ActiveRecord::Base.connection.native_database_types
  9.  
  10. ?
  11.  
  12. This is the array that ActiveRecord should be using to convert from
  13. the type you use in your migrations to database types.
  14.  
  15. I'm running MySQL 5. When I run it, I get:
  16.  
  17.                       >> ActiveRecord::Base.connection.native_database_types[:string]
  18.                        => {:name=>"varchar", :limit=>255}
  19.  
  20. Are you getting the same? The way it's running for you, it almost
  21. seems like it's returning nil or "string".

That worked as expected!! So that was not the problem...

Sandi M. had this idea:

RUBY:
  1. Looking in rails 1.2.3, I see that
  2.  
  3.     ActiveRecord::ConnectionAdapters::ColumnDefinition (1) has method
  4.       def sql_type
  5.         base.type_to_sql(type.to_sym, limit, precision, scale) rescue type
  6.       end
  7.  
  8. If this method raises an error, you'd get your original value back for the type.
  9.  
  10. It would be really interesting to go into this bit of code and change it to
  11.  
  12.       def sql_type
  13.         begin
  14.           base.type_to_sql(type.to_sym, limit, precision, scale)
  15.         rescue Exception => e
  16.           print e.backtrace.join("\n")   
  17.           raise "type_to_sql failed with #{e.class} #{e.message} for #{type}"
  18.         end
  19.       end
  20.  
  21. One would guess, looking at the type resolution code for various adaptors, that your install is missing, or didn't load, the adapter class which contains the type translation code for your database.  This backtrace should help locate the problem.

By this point, we had taken the conversation to instant messenger..

Hmm... so I saw it trying to work... I got an error saying argument error with expecting 4 params and only getting 2! Jen-Mei had me do a grep to see if type_to_sql is defined anywhere -- and AH HA.. there was a plugin -- mysql_bigint that was installed, and it had redefined the method and that was the culprit. This was a codebase that I inherited so I didn't even know what that plugin was used for or anything.

Here was the code in mysql-bigint plugin

RUBY:
  1. def type_to_sql(type, limit = nil) #:nodoc:
  2.           mysql_integer_types = %w{tinyint smallint mediumint intger bigint}
  3.         unless self.class.method_defined? :native_database_type
  4.           native = native_database_types[type]
  5.         else
  6.           native = native_database_type(type, limit)
  7.           limit = nil if mysql_integer_types.include? native[:name] # mysql doesn't use limit to indicate bytes of storage.
  8.                                           # Need to reassign native representation below.
  9.         end
  10.         limit ||= native[:limit]
  11.         column_type_sql = native[:name]
  12.         column_type_sql <<"(#{limit})" if limit
  13.         column_type_sql
  14.       end
  15.     end

Did a bit of research and found I had an old version installed:

http://www.northpub.com/articles/2006/10/29/new-version-of-mysql_bigint-rails-plugin

Quote from the site: "I received some feedback that edge Rails broke some things in the mysql_bigint plugin . I've checked in a new version that works correctly with edge rails. Thanks to Jamie Orchard-Hayes for a patch that fixed a few of these issues!"

So, I see there's a fix for it... but upon further investigation, the plugin is not use in the application at all! So I removed it for now.

Things I learned:

  • Check your plugins
  • Don't be afraid to dive into the rails code and print stuff to logs to see whats going on
  • Don't keep plugins laying around that are not in use
  • Probably a good idea to document what plugins are used and what for in the README
  • How to actually RUN the unit tests for rails (see the readme in the test dir), this way I knew for sure that my checkout of rails worked and it was something with my application code
  • DevChix ROCK!!

Comments

Weirdness and Coolness in Rails

Coolness

First the cool thing... and I think I have a good reason for this... I have a model that is not tied to any particular table, but is a summary table for about 8 tables. Rather than cluttering up my controller with a bunch of stuff, I am putting into a model (keeping REST in mind). I could have put it in the lib dir as a module.. but.. I thought i'd try it in the models dir, so i don't have to require it etc. And later I realized I need a bunch of fixtures for it, so I think its pretty handy as a model. Of course, I took out the base class of active record

app/model/summary.rb

RUBY:
  1. class Summary
  2.    attr_reader :date_from, :date_to
  3.    attr_writer :date_from, :date_to
  4.  
  5.   def has_dates?
  6.     (self.date_from && self.date_to) ? true : false
  7.   end
  8.  
  9.   def job_count
  10.     if self.has_dates?
  11.        Job.count(:conditions => ["completed_at BETWEEN ? and ?", self.date_from, self.date_to])
  12.     else
  13.       Job.count(:conditions => "completed_at IS NOT NULL")
  14.    end
  15.    
  16.    ...
  17. end

I might want to get the count of jobs for ALL time or a data range, so if there are dates set, it uses those. In addition to jobs, I need to do some 'not so easy" counting of other date and so i started changing my test fixtures to something like this:

test/fixtures/summary_report/jobs.yaml

RUBY:
  1. <% 1.upto(30) do |num| %>
  2. job_<%=num%>:
  3.   id: <%= num %>
  4.   created_at: <%=(Time.now - 1000).to_s(:db) %>
  5.   finished_at: <%= Time.now.to_s(:db) %>
  6.   name: One more number <%= num %> Awesome Job
  7. <% end %>

I have a bunch of other tests and I found one of them was not quite right, and my additional fixtures for the summary report messed it up. So I made a directory in test/fixtures/summary_report and then loaded the fixed in my summary test as such:

test/unit/summary_test.rb

RUBY:
  1. require File.dirname(__FILE__) + '/../test_helper'
  2.  
  3. class SummaryTest <Test::Unit::TestCase
  4.   fixtures 'summary_report/jobs',
  5.             'summary_report/people'
  6.  
  7.   def setup
  8.     @s = Summary.new
  9.   end
  10.  
  11.   def test_job_count_all
  12.     assert_equal 50, @s.job_count
  13.   end
  14.   ...

So I put fixtures for a particular set of tests in a directory in fixture. Is there a better way to do this?

Weirdness

I put it in a post I made on ruby-forum.com but here it is again:

Basically, when I try to use a rails version higher tha 1.1.6 in my vendor/rails directory my migrations don't have "varchar" they have "string" !! WTF! ... I even tried sqlite and same thing.

I've searched all over the web and mailing lists and can't find any info
on this problem.

I have a site built with Rails 1.1.6  I ran

rake rails:freeze:edge TAG=rel_1-2-3

I ran db:migrate (on a fresh database)

 rake db:migrate VERSION=1 --trace
(in /home/nola/projects/tardis/website/trunk)
** Invoke db:migrate (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute db:migrate
== AddContact: migrating
======================================================
-- create_table(:contacts)
rake aborted!
Mysql::Error: You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the right syntax to
use near 'string DEFAULT NULL, `city` string DEFAULT NULL)
ENGINE=InnoDB' at line 1: CREATE TABLE contacts (`id` int(11) DEFAULT
NULL auto_increment PRIMARY KEY DEFAULT NULL, `name` string DEFAULT
NULL, `city` string DEFAULT NULL) ENGINE=InnoDB
/home/nola/projects/tardis/website/trunk/config/../vendor/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:128:in
`log'
/home/nola/projects/tardis/website/trunk/config/../vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb:243:in
`execute'
/home/nola/projects/tardis/website/trunk/config/../vendor/plugins/mysql_bigint/lib/mysql_bigint.rb:32:in
`create_table'
/home/nola/projects/tardis/website/trunk/config/../vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb:353:in
`create_table'
/home/nola/projects/tardis/website/trunk/config/../vendor/rails/activerecord/lib/active_record/migration.rb:275:in
`method_missing'
/home/nola/projects/tardis/website/trunk/config/../vendor/rails/activerecord/lib/active_record/migration.rb:259:in
`say_with_time'
/usr/lib/ruby/1.8/benchmark.rb:293:in `measure'
/home/nola/projects/tardis/website/trunk/config/../vendor/rails/activerecord/lib/active_record/migration.rb:259:in
`say_with_time'
/home/nola/projects/tardis/website/trunk/config/../vendor/rails/activerecord/lib/active_record/migration.rb:273:in
`method_missing'
./db/migrate//001_add_contact.rb:3:in `real_up'
/home/nola/projects/tardis/website/trunk/config/../vendor/rails/activerecord/lib/active_record/migration.rb:212:in
`migrate'
/usr/lib/ruby/1.8/benchmark.rb:293:in `measure'
/home/nola/projects/tardis/website/trunk/config/../vendor/rails/activerecord/lib/active_record/migration.rb:212:in
`migrate'
/home/nola/projects/tardis/website/trunk/config/../vendor/rails/activerecord/lib/active_record/migration.rb:335:in
`migrate'
/home/nola/projects/tardis/website/trunk/config/../vendor/rails/activerecord/lib/active_record/migration.rb:330:in
`migrate'
/home/nola/projects/tardis/website/trunk/config/../vendor/rails/activerecord/lib/active_record/migration.rb:297:in
`up'
/home/nola/projects/tardis/website/trunk/config/../vendor/rails/activerecord/lib/active_record/migration.rb:288:in
`migrate'
/home/nola/projects/tardis/website/trunk/config/../vendor/rails/railties/lib/tasks/databases.rake:4
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:392:in `execute'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:392:in `execute'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:362:in `invoke'
/usr/lib/ruby/1.8/thread.rb:135:in `synchronize'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:355:in `invoke'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:1739:in `top_level'
/usr/lib/ruby/gems/1.8/gems/rake- 0.7.3/lib/rake.rb:1739:in `top_level'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:1761:in
`standard_exception_handling'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:1733:in `top_level'
/usr/lib/ruby/gems/1.8/gems/rake- 0.7.3/lib/rake.rb:1711:in `run'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:1761:in
`standard_exception_handling'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake.rb:1708:in `run'
/usr/lib/ruby/gems/1.8/gems/rake- 0.7.3/bin/rake:7
/usr/bin/rake:1

----------------------------

SO Basically, its trying to put in a sql create statement like this:

CREATE TABLE contacts (
 `id` int(11) DEFAULT NULL auto_increment PRIMARY KEY DEFAULT NULL,
 `name` string DEFAULT NULL,
 `city` string DEFAULT NULL
) ENGINE=InnoDB

string? when it should put in VARCHAR(255) .. weird huh?

Here's the migration:

class AddContact < ActiveRecord::Migration
  def self.up
    create_table :contacts do |t|
      t.column :name, :string
      t.column :city, :string
    end
  end

  def self.down
    drop_table :contacts
  end

Any ideas? I've also tried with rel_1-2-0 too... and get the same
result. I can create a table with ints or no fields just fine. When I
remove vendor/rails then its fine.

Comments (3)

Perl Survey

Hey ... a friend at oscon send me this survey PerlSurvey ... if you do perl, take it and let your voice be heard!

Comments (1)

Nifty Rails Stuff

I've been kinda on a rails spree lately, I guess I've had some free time and also redoing a rails 1.1.6 project (and was noob then and no clue of what I was doing) and updating it to use REST.

I got Geoffrey Grosenbach PeepCode's REST Tutorial, which is very awesome and well worth the 9 bucks. Its over an hour long! I also got the RJS Tutorial which is also awesome. I can't wait till payday to get the $40 pack so I can get some more! There's just something about SEEING something work that makes it stick sometimes.

Also I spent some time on Railscasts which features a ton of short demos on rails topics. Very cool. In particular i liked Testing Without Fixtures which is cool because sometimes fixtures are a PITA!

When watching one of the PeepCode screencasts I saw him using "autotest" .. a cool toy which I must have too! I searched for it and found this posting on his blog. Now I'm autotesting all the time :) It basically monitors your rails site and runs the test everytime you change your code.

I've been using e-TextEditor and slowly learning the shortcuts. I love the font that was on PeepCode's screen cast and found a link on the PeepCode FAQ where I can download it. For Free! And it mentioned the name of the theme used in Textmate -- which happened to be the one I had found in e-Text-Editor and was using. No wonder I liked it! I also used this font in my Putty settings and changed the awful default colors (esp that dark blue! hard to see!). e-TextEditor is in Beta but its in great shape and i was so happy to see a "close all tabs" feature put into the latest build. I'll be ecstatic when they make a linux version.

Comments

A Lightbulb Just Went On

I was starting a redo of a old (rails 1.1.6) site and thought I'll store the rails in the vendor directory so I don't have to worry about what version is installed in the server, so I looked up this nifty Article on SitePoint where they explain how to do that. Installing and Managing Edge Rails.

I started with some basic steps to "redo" my old site.. used the controller generator.. whoa.. huh? ".html.erb" .. I instant messaged a friend, Carmelyne and said whats up with ".html.erb" .. she is like, oh thats edge rails. I thought I had installed 1.2 release instead but on closer inspection I did indeed install edge. I must have had the version number wrong or something. Doh, oh well.. let me try it anyways.

In further discussion.. she suggested i look at using REST.. "isn't it just for webservices?" i ask, she said no. I'm not doing anything that I will need to publish web services for.... its just a bakery order site. But, I did a little research and Carmelyne pointed me to some resources.... and I got it!

A lightbulb went on!

I used the scaffold in edge to build my model... looked at the controller...looked at routes.rb ... and i got it. :)

Read these to understand what the heck I am talking about:
A Series of 5 articles on REST and Rails - very basic and helped me understand how, what why of REST and Rails.
REST on Rails - another good one

I feel like I've been a bird with my head in the sand. I'd read stuff before but never understood how, what and why of REST.

More to follow as it sinks in.

Comments