Thursday, 26 July 2007

google analytics problems?



Since yesterday google analytics seems to be experiencing problems.

Some login problems were experienced and a delay in the processing was announced.

Now in the dashboard I can see funny things like the image above (47 visits and no pageviews, quite a mistery). In the specific case the correct data should be 0 visits since I know yesterday there was no activity on that specific regexp-filtered profile.

Statistics for july the 25th have stopped at 17 GMT for me.

sh*t happens, at google too.

-- update 30 july

Today for some accounts google analytics data are delayed again.
In my case data last update is 6.00 AM GMT july 29 so at the moment the delay is more than one day.

Wednesday, 6 June 2007

ruby on rails params and empty strings

A little annoyance I've found using ruby on rails is the following:

If in your model you have some strings that can be null, and the user doesn't fill the related fields in the web form, rails will end up storing an empty string "" instead of the good old NULL in the database.

Now, this is for sure not a big problem but it has some implications that might affect the model validations and it can be even worse if the rails app is not the only program writing in the database, in this last case you easily end up with a mix of empty string and NULL values in the column making trickier to write queries conditions that involve that column.

Now I was playing today to fix this problem and I came with a solution that uses SimpleDescriptor.

For any model that uses SimpleDescriptor as described in this post the following is a way to have NULL saved in the database instead of the empty string ''

first you need to define the clean_strings method


def clean_strings
self.class.described_as(:string).each do { |field| send("#{field}=", nil) if send(field) == '' }
end


and then add the clean_strings method in your before_validation callback


before_validation :clean_strings


Starting from this moment your model will just save NULL instead of an empty string and the :allow_nil => true in the model validations will start behaving as expected.

Monday, 4 June 2007

Simple Descriptor, code less validate more

After 6 month I've released a new version of Simple Descriptor.

This gem makes possible to attach some extra informations to a generic ruby class, but its mission is now includes specific methods to allow more control and flexibility on ActiveRecord validations, in addition to this, Simple Descriptor may help you in building a consistent approach in areas where rails doesn't.

Let's start getting our hands dirty, first of all install the gem


sudo gem install simple_descriptor


after that you need to require the gem i.e in your config/environments.rb file

require 'simple_descriptor'


now let's tweak our Employee ActiveRecord model

the migration to create the Employee model will be

class CreateEmployees < ActiveRecord::Migration
def self.up
create_table :employees do |t|
t.column :first_name, :string, :limit => 30, :null => false
t.column :middle_name, :string, :limit => 10, :null => true
t.column :last_name, :string, :limit => 30, :null => false
t.column :gross_wage, :integer, :null => false
t.column :personal_email, :string, :limit => 100, :null => false
end
end

def self.down
drop_table :employees
end

the basic model definition will be

class Employee < ActiveRecord::Base
end

to get some validations for free we need to add 2 lines of code

class Employee < ActiveRecord::Base
extend SimpleDescriptor::ClassDescriptor
validates_ar_descriptions
end

These 2 extra lines will

  • validates_presence_of every field defined as NOT NULL

  • validates_length_of every field defined with a limit

  • validates_numericality_of every field defined as anumber


but there some extra as well, fire the console of your rails app and type

Employee.described_as :string

this will return all the fields defined as string in the database.
Now always in the console try

Employee.maxlegth(:first_name)

this will return 30 which is the maximum length of the first_name field

Or again you can have the list of the required fields

Employee.described_as :required
=> [:first_name, :gross_wage, :last_name, :personal_email]


Or you can ask your model if specific field is required

Employee.describes? :first_name as => :required
=> true

If you want to inspect a bit more what's happening behind the scenes you can use

Employee.descriptions

Now, let's say you have some different models i.e. Employee, Manager, Consultant and in all these models you have some sensible fields you want to show only to authorized people.

If you use Simple Descriptor for all these models you can easily define which fields contains sensible informations, for the Employee it would be


class Employee < ActiveRecord::Base
extend SimpleDescriptor::ClassDescriptor
validates_ar_descriptions
describe :gross_wage as => :sensible
end

Starting from this moment you can ask the Employee class if a field is sensible or not

Employee.describes? :gross_wage, :as => :sensible
=> true

Employee.describes? :first_name, :as => :sensible
=> false

Or you can obtain the list of sensible fields

Employee.described_as :sensible
=> [:gross_wage]

This may help you to manage sensible data show rules in your views or in your controller.

To know more about Simple Descriptor you can just visit the online docs

Thursday, 17 May 2007

ActiveRecord :select with :include

ActiveRecord is an important slice of the joy included in Ruby on Rails, writing a SQL database driven application without actually writing any SQL is really pleasurable.

But sometime, even in the joy you get some pain.
The pain for me arrived when I was working on some reporting feature that was pulling various data across a quite long chain of has_many relationships.

I experienced a quite high load in the DB at the moment of the query and after that seconds of CPU full load eaten by my ruby process.
I checked what was going on in my log/development.log and I noticed the query was extracting all the columns of every table even if I specified a :select option, this turned a query originally quite light into a heavy one.

I googled a bit and I found out that with ActiveRecord, if you specify :select and :include option you don't get anymore 100% joy but just 50%, your :select statement will be ignored.

Today I'm trying to put back some percent of the joy.

select_with_include gem is meant to move the joy level up to 80% (no, not 100% yet)

select_with_include will allow you to specify a limited :select statement like


"table1.column1, table1.column3, table2.column2"


or like


"table1.*, table2.column3, table2.column4, talbe3.*"


At the moment you can't specify functions or calculated fields. There are reason for that and I'm going to discuss these reason in the next posts. I'll try as well to explain how this gem works around the original ActiveRecord code.

For the moment you're invited to get select_with_include gem using


sudo gem install select_with_include


and test it yourself specifying


require 'select_with_include'


in your config/environment.rb file.

If you're a script/console user you can just try, while you

tail -f log/development.log

to launch the same find with :include and :select with and without requiring the gem.

If you find any issue you're really welcome to use the issue tracker


And if you want to know more just stay tuned for the next posts

Wednesday, 16 May 2007

attachment_fu and Rmagick FAT thumbnails

I'm using attachment_fu on the project I'm currently working on, using it to process the images the users upload.

As backend I use Rmagick, since it was already used in the same app. At some point I felt curious about the size in kb of the thumbnails generated, to estimate the increase of bandwidth the new feature would add on the server.

I quickly spotted the size of the generated jpegs was unreasonable for the pixel size of them.

It turned out that attachment_fu + Rmagick on Ubuntu 6.0.6 and Ruby 1.4 aren't compressing jpegs.

To fix here's a one line patch on attachment_fu.

this patch sets the jpeg quality to 85%


[~]$ cat atch_fu/attachment_fu_rmagick_compression.patch
Index: lib/technoweenie/attachment_fu/processors/rmagick_processor.rb
===================================================================
--- lib/technoweenie/attachment_fu/processors/rmagick_processor.rb (revision 2864)
+++ lib/technoweenie/attachment_fu/processors/rmagick_processor.rb (working copy)
@@ -45,9 +45,9 @@
else
img.change_geometry(size.to_s) { |cols, rows, image| image.resize!(cols, rows) }
end
- self.temp_path = write_to_temp_file(img.to_blob)
+ self.temp_path = write_to_temp_file(img.to_blob {self.quality = 85})
end
end
end
end
-end
\ No newline at end of file
+end