Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

« Newer Snippets
Older Snippets »
Showing 11-20 of 34 total

Rake task to clear Rails log files

# Truncates all *.log files in log/ to zero bytes
rake log:clear

Using 64 bit primary keys with migrations

I've got an application which may need more IDs than the standard 32 bit ones typically provide. MySQL has a BIGINT variable type, but it is a little tricky to convince Rails and Migrations to use it. The instructions are for MySQL, but should be easily transferable to other DBs.

1. Monkeypatch ActiveRecord::ConnectionAdapters::MysqlAdapter#native_database_types by appending it to config/environment.rb and add two new types. I've named them int64 and int64_pk

class ActiveRecord::ConnectionAdapters::MysqlAdapter
  def native_database_types #:nodoc:
    {
      :primary_key => "int(11) DEFAULT NULL auto_increment PRIMARY KEY",
      :int64_pk    => "bigint DEFAULT NULL auto_increment PRIMARY KEY",
      :int64       => { :name => "bigint" },
      :string      => { :name => "varchar", :limit => 255 },
      :text        => { :name => "text" },
      :integer     => { :name => "int", :limit => 11 },
      :float       => { :name => "float" },
      :decimal     => { :name => "decimal" },
      :datetime    => { :name => "datetime" },
      :timestamp   => { :name => "datetime" },
      :time        => { :name => "time" },
      :date        => { :name => "date" },
      :binary      => { :name => "blob" },
      :boolean     => { :name => "tinyint", :limit => 1 },
    }
  end
end


2. In the table creation migration, create the table WITHOUT a primary key column, and then add the column manually, referencing int64_pk above:

create_table :slices, :id => false do |t|
       t.column :cheese_id, :integer
       t.column :plant, :string
       t.column :date, :datetime
     end
    add_column :events, :id, :int64_pk
end



3. In tables referencing this one, mark the foreign_id fields as int64:

create_table :fondues do |t|
      t.column :cheese_id, :int64
      t.column :party_id, :integer
      t.column :kirsch_id, :integer
end



4. It turns out that the c-based mysql bindings do NOT do let you set primary keys via the sequence because it coerces the
insert_id into 32 bits at mysql.c:532. There are two way to fix this:

a. Use the pure-ruby gem (ie, remove the c-gem)

b. Patch and rebuild the c-gem by changing line 352 (in version 2.7):

   return INT2NUM(mysql_insert_id(GetHandler(obj)));


Extending this to use LL2NUM solves the issue:

   return LL2NUM(mysql_insert_id(GetHandler(obj)));



5. One last thing, in environment.rb:

  # Use SQL instead of Active Record's schema dumper when creating the test database.
  # This is necessary if your schema can't be completely dumped by the schema dumper,
  # like if you have constraints or database-specific column types
  config.active_record.schema_format = :sql


We need to deal with sql, rather than ruby, schemas.

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

Note that I've decided that ONLY the cheese table needs 64bit IDs -- other references are still integers. If you wanted ALL primary keys to be 64 bits, you could have the monkeypatch look like:

class ActiveRecord::ConnectionAdapters::MysqlAdapter
  def native_database_types #:nodoc:
    {
      :primary_key    => "bigint DEFAULT NULL auto_increment PRIMARY KEY",
.
.
.

Reset user password based on another users

When you first create an app you might not have time *cough* to add special user password reset features. Especially if you don't have many users.

Here's a quick script to set the password of a user to another user (say a manually created user 'tester' with a known password).

namespace :user do
  desc 'Reset user (USER=username) password to that of username "tester" (or FROM=username env)'
  task :reset => :environment do
    reset_username = ENV['USER']
    unless ENV['USER']
      puts 'Require "USER=username" for user to be reset'
      next
    end
    reset_user     = User.find_by_username reset_username
    unless reset_user
      puts "Cannot find user: #{reset_username}"
      next
    end
    from_username  = ENV['FROM'] || 'tester'
    from_user      = User.find_by_username from_username
    unless from_user
      puts "Cannot find user: #{from_username}"
      next
    end
    
    reset_user.crypted_password = from_user.crypted_password
    reset_user.salt             = from_user.salt
    reset_user  .save
    puts 'User password reset'
  end
end

Remove temporary captcha images

desc "Remove captcha images"
task :remove_captcha_files do
  captcha_img_path = "#{RAILS_ROOT}/public/images/captcha_img/"
  Dir.foreach(captcha_img_path){|file| File.delete(captcha_img_path+file) if (/^.*.jpg$/).match(file)} if File.exist?(captcha_img_path)
end

Deploying to different locations with Capistrano

// description of your code here
In your deploy.rb file:

if ENV["SERVER"] && ENV["SERVER"] == "production"
  set :primary_server, "production.com"
  set :user, "ben"
elsif ENV["SERVER"] && ENV["SERVER"] == "staging"
  set :primary_server, "staging.local"
  set :user, "ben"
else
 ...
end

role :web, primary_server
role :app, primary_server
role :db,  primary_server, :primary => true



The you say:
rake deploy SERVER=staging

Switch Oracle CLOB to VARCHAR2

This rake task creates a database script to change all Oracle CLOB columns to VARCHAR2 columns.

Changing Oracle CLOBs to VARCHAR2s can result in a huge performance increase, especially if the database and app servers are not close together on the network.

namespace :db do
  task :fix_clobs => [:environment] do |t|
    @outfile = File.expand_path(File.join(RAILS_ROOT,"db","fix_clobs.sql"))
  
    File.open(@outfile, "w") do |file|
      ActiveRecord::Base.connection.tables.each do |table_name|
        begin
          model = eval(table_name.classify)
          model.columns.each do |column|
            if column.sql_type == "CLOB"
              file.write("ALTER TABLE #{table_name} ADD #{column.name}_temp VARCHAR2(4000);\n")
              file.write("UPDATE #{table_name} SET #{column.name}_temp = #{column.name};\n")
              file.write("COMMIT;\n")
              file.write("ALTER TABLE #{table_name} DROP COLUMN #{column.name};\n")
              file.write("ALTER TABLE #{table_name} RENAME COLUMN #{column.name}_temp TO #{column.name};\n")
              file.write("\n")
            end
          end
         rescue => ex
           puts "Failed for #{table_name} with #{ex.class}"
         end
      end
    end
  end
end

Adjust Database Sequences

If loading data through fixtures or other means with hard-coded IDs, database sequences may need to be adjusted. This is written for Oracle.

namespace :db do
  task :adjust_sequences => :environment do
    ActiveRecord::Base.connection.tables.each do |table|
      begin
        count = ActiveRecord::Base.count_by_sql("SELECT MAX(id) FROM #{table}")
        seq = "#{table}_seq"
        ActiveRecord::Base.connection.execute("DROP SEQUENCE #{seq}")
        ActiveRecord::Base.connection.execute("CREATE SEQUENCE #{seq} START WITH #{count+1}")
      rescue => ex
        puts "Failed for #{table} with #{ex.class}"
      end
    end
  end
end

Useful Rake tasks for Subversion setup with Rails

This was originally written by Jake at http://blog.unquiet.net/archives/2005/11/06/helpful-rake-tasks-for-using-rails-with-subversion/ .. but that site seems not to be showing content properly, so I salvaged this from the Google cache. I also added two new lines to make it remove /tmp folder which is now in Rails.

Just dump this into a file called svn.rake in your lib/tasks folder, and use rake configure_for_svn to sort everything out on your initial check out:

desc "Configure Subversion for Rails"
task :configure_for_svn do
  system "svn remove log/*"
  system "svn commit -m 'removing all log files from subversion'"
  system 'svn propset svn:ignore "*.log" log/'
  system "svn update log/"
  system "svn commit -m 'Ignoring all files in /log/ ending in .log'"
  system 'svn propset svn:ignore "*.db" db/'
  system "svn update db/"
  system "svn commit -m 'Ignoring all files in /db/ ending in .db'"
  system "svn move config/database.yml config/database.example"
  system "svn commit -m 'Moving database.yml to database.example to provide a template for anyone who checks out the code'"
  system 'svn propset svn:ignore "database.yml" config/'
  system "svn update config/"
  system "svn commit -m 'Ignoring database.yml'"
  system "svn remove tmp/*"
  system "svn commit -m 'Removing /tmp/ folder'"
  system 'svn propset svn:ignore "*" tmp/'
end
   
desc "Add new files to subversion"
task :add_new_files do
   system "svn status | grep '^\?' | sed -e 's/? *//' | sed -e 's/ /\ /g' | xargs svn add"
end

desc "shortcut for adding new files"
task :add => [ :add_new_files ]

SVN revision from shell

I use this to set the subject of an email that notifies my team of a Capistrano deploy. The part of interest is how it gets the subversion revision number with a few piped shell commands.

echo "Subject: [rake deploy] Deployed revision `cd /home/www/current ; svn info | grep Revision | sed "s/Revision: //"` on `hostname` at `date`" > ~/sendmail_tmp

Create YAML test fixtures from database in Rails

As found at http://media.pragprog.com/titles/fr_rr/code/CreateFixturesFromLiveData/lib/tasks/extract_fixtures.rake

desc 'Create YAML test fixtures from data in an existing database.  
Defaults to development database.  Set RAILS_ENV to override.'

task :extract_fixtures => :environment do
  sql  = "SELECT * FROM %s"
  skip_tables = ["schema_info"]
  ActiveRecord::Base.establish_connection
  (ActiveRecord::Base.connection.tables - skip_tables).each do |table_name|
    i = "000"
    File.open("#{RAILS_ROOT}/test/fixtures/#{table_name}.yml", 'w') do |file|
      data = ActiveRecord::Base.connection.select_all(sql % table_name)
      file.write data.inject({}) { |hash, record|
        hash["#{table_name}_#{i.succ!}"] = record
        hash
      }.to_yaml
    end
  end
end
« Newer Snippets
Older Snippets »
Showing 11-20 of 34 total