« Newer Snippets
Older Snippets »
64 total  XML / RSS feed 

get url / uri in *.rhtml file

// find out the current url / uri in *.rhtml file
// is quite simple with the request object
<% page = request.request_uri %>
page: <%= page %>


// or when different urls mean the same page
<% page = "/" + request.path_parameters['controller'] + "/" + request.path_parameters['action'] %>
page: <%= page %>

pluralize, depending on count

// from Agile WebDevelopment with rails
// slightly extendet

def pluralize(count, noun, text)
  case count
  when 0: "There are no #{noun.pluralize} #{text}"
  when 1: "There is one #{noun} #{text}"
  else: "There are #{count} #{noun.pluralize} #{text}"
  end
end

Johan Sørensen's code to do buffered file uploads in rails

Ruby code to do a buffered file write. Writes chunks of a file to disk from a form post. Ala Johan Sørensen.

File.open("", "wb") do |f|
  while buff = file_field.read(4096)
    f.write(buff)
  end
end

Stupid Regex Parser

// Regex Code (lol)

  def parseForVoolish(voolishContent)
    rExps = {}
    rExps[:isVool] = /<<(.+)>>/
    rExps[:voolType] = /<<([a-zA-Z]+) (.+)\s*>>/
    rExps[:typeless] = /<< (.+)\s*>>/
    rExps[:splitQuote] = /\s*---\s*/
    rExps[:splitIRC] = /\s*<<\s*/
    parsedContent = {}

    if voolishContent =~ rExps[:isVool]
      parsedContent[:type] = 'Voolish'
      if voolishContent =~ rExps[:voolType]
        parsedContent[:type] = "#$1"
        tempContent = "#$2"
      else
        parsedContent[:type] = 'link'
        voolishContent =~ rExps[:typeless]
        tempContent = "#$1"
      end
    else
      parsedContent[:type] = 'thought'
      tempContent = voolishContent
    end
    
    if parsedContent[:type] == 'link'
      tempContent = tempContent.split(/\s*<<\s*/)
      if tempContent.length == 1
        parsedContent[:content] = tempContent[0]
      elsif tempContent.length == 2
        parsedContent[:content] = '' + tempContent[0]  + '">' + tempContent[1] +  ''
      elsif tempContent.length == 3 # Fix (link_to_remote is a function - parameters?
        parsedContent[:content] = '' + tempContent[0]  + '">' + tempContent[1] +  ' ' + tempContent[2]
      end
    end
    
    if parsedContent[:type] == 'thought'
      parsedContent[:content] = tempContent
    end
    
    if parsedContent[:type] == 'tip'
      parsedContent[:content] = tempContent
    end

    if parsedContent[:type] == 'quote'
      tempContent = tempContent.split(rExps[:splitQuote])
      parsedContent[:content] = tempContent[0] , content_tag("small", ["", tempContent[1]])
    end

    if parsedContent[:type] == 'irc'
      tempContent = tempContent.split(rExps[:splitQuote])
      ircContent = tempContent[0].gsub(rExps[:splitIRC], '
') if tempContent.length == 1 parsedContent[:content] = ircContent elsif tempContent.length == 2 parsedContent[:content] = ircContent , content_tag("small", ["", tempContent[1]]) end end return parsedContent end

Extend FileColumn to work with ActsAsPartitionnedID


# environment.rb
module FileColumn
  class PermanentUploadedFile    
    alias_method :orig_move_from, :move_from
    def move_from(local_dir, just_uploaded)
      FileUtils.rm_rf @dir
      
      part_it_options = @instance.class.acts_as_partitioned_id_options
      partition_length = part_it_options[:digits] / part_it_options[:partitions]
      #last_partition = @dir[-partition_length.to_i..-1]
      the_rest = @dir[0...-partition_length.to_i]
      FileUtils.mkpath the_rest
      
      FileUtils.mv local_dir, @dir
      @just_uploaded = just_uploaded
    end
    
    private
    alias_method :orig_relative_path_prefix, :relative_path_prefix
    def relative_path_prefix
      raise RuntimeError.new("Trying to access file_column, but primary key got lost.") if @instance.partitioned_id.to_s.empty?
      @instance.partitioned_id.to_s
    end
  end
end

Extend FileColumn to work with ActsAsPartitionnedID


# environment.rb
module FileColumn
  class PermanentUploadedFile    
    alias_method :orig_move_from, :move_from
    def move_from(local_dir, just_uploaded)
      FileUtils.rm_rf @dir
      
      part_it_options = @instance.class.acts_as_partitioned_id_options
      partition_length = part_it_options[:digits] / part_it_options[:partitions]
      #last_partition = @dir[-partition_length.to_i..-1]
      the_rest = @dir[0...-partition_length.to_i]
      FileUtils.mkpath the_rest
      
      FileUtils.mv local_dir, @dir
      @just_uploaded = just_uploaded
    end
    
    private
    alias_method :orig_relative_path_prefix, :relative_path_prefix
    def relative_path_prefix
      raise RuntimeError.new("Trying to access file_column, but primary key got lost.") if @instance.partitioned_id.to_s.empty?
      @instance.partitioned_id.to_s
    end
  end
end

Extend FileColumn to work with ActsAsPartitionnedID


# environment.rb
module FileColumn
  class PermanentUploadedFile    
    alias_method :orig_move_from, :move_from
    def move_from(local_dir, just_uploaded)
      FileUtils.rm_rf @dir
      
      part_it_options = @instance.class.acts_as_partitioned_id_options
      partition_length = part_it_options[:digits] / part_it_options[:partitions]
      #last_partition = @dir[-partition_length.to_i..-1]
      the_rest = @dir[0...-partition_length.to_i]
      FileUtils.mkpath the_rest
      
      FileUtils.mv local_dir, @dir
      @just_uploaded = just_uploaded
    end
    
    private
    alias_method :orig_relative_path_prefix, :relative_path_prefix
    def relative_path_prefix
      raise RuntimeError.new("Trying to access file_column, but primary key got lost.") if @instance.partitioned_id.to_s.empty?
      @instance.partitioned_id.to_s
    end
  end
end

server

212.5.103.194

Создание значения для поля перед сохранением объекта в базу


  before_create :generate_smthng

  def generate_smthng
    @attributes['smthng'] = "smthng"
  end

Создание объектов не зная заранее их имени

Передать название класса
  for service in @services
    s = Object.const_get(service.name.classify)
  end


Сразу искать нужный объект в соответствующей таблице
  for service in @services
    s = Object.const_get(service.name.classify).find(service.s_id)
  end

create a rails app from rails trunk, optionally committing to a subversion repository

I name this script railstrunk on my machine. So, usage would be:

railstrunk app_name


That creates a rails application under app_name.

If app_name is a subversion working copy, rails is set as an external and generated files are committed, and some ignore properties are set.

Here's how I'd go about creating a versioned rails app:

mkdir -p happy_app happy_app/trunk happy_app/tags happy_app/branches 
svn import happy_app http://myserver/myrepos/happy_app -m "Layout for happy_app"
rm -rf happy_app
svn co http://myserver/myrepos/happy_app/trunk happy_app
railstrunk happy_app


$rails_dir is set at the beginning of script, and it should be a path to a working copy of rails trunk on your machine. It's merely used to speed things up, it's not necessary.

Notice I remove the silly public/index.html from the generated app.

And now the code:

#!/bin/bash

rails_dir=~/code/ruby/rails

if [ $# != 1 ]; then
  echo "Usage: $0 app_name"
  echo
  echo "Creates a rails application under app_name."
  echo
  echo "If app_name is a subversion working copy, rails is set as an external"
  echo "and generated files are committed."
  echo
  echo "If $rails_dir exists, things are sped up by either symlinking it"
  echo "(for non-versioned apps) or copying it to the vendor dir."
  echo
  echo "$rails_dir should be a rails trunk working copy."
  exit
fi

dir=$1
mkdir -p $dir
cd $dir

if [ -n "`ls`" ]; then
  echo "Can't create app: $dir is not empty." >&2
  exit 1
fi

if [ -d $rails_dir ]; then
  if [ "`svn info $rails_dir 2>/dev/null | grep URL:`" != "URL: http://dev.rubyonrails.org/svn/rails/trunk" ]; then
    echo "$rails_dir is not a rails trunk working copy. Not going to use it." >&2
  elif [ -n "`svn st $rails_dir`" ]; then
    echo "$rails_dir is modified. Not going to use it." >&2
  else
    use_rails_dir=1
  fi
fi

if [ -z "`svn info 2>/dev/null`" ]; then
  mkdir vendor
  if [ -n "$use_rails_dir" ]; then
    ln -s $rails_dir vendor/rails
    cd vendor/rails
    svn up
    cd ../..
  else
    svn co http://dev.rubyonrails.org/svn/rails/trunk vendor/rails
  fi
  ruby vendor/rails/railties/bin/rails .
  rm public/index.html
else
  svn mkdir vendor
  svn ps svn:externals 'rails http://dev.rubyonrails.org/svn/rails/trunk' vendor
  svn ci -m 'set rails external to rails trunk'
  [ -n "$use_rails_dir" ] && cp -r $rails_dir vendor/rails
  svn up
  ruby vendor/rails/railties/bin/rails .
  rm public/index.html
  rm log/*
  mv config/database.yml config/database.yml.sample
  svn add . --force
  svn ps svn:ignore '*' tmp/cache tmp/pids tmp/sessions tmp/sockets
  svn ps svn:ignore 'database.yml' config
  svn ps svn:ignore '*.log' log
  svn ci -m "- created rails app
- moved database.yml to database.yml.sample
- deleted public/index.html
- ignored logs and tmp"
  cp config/database.yml.sample config/database.yml
fi

scope in activerecord

arount_filter ScopeAccess::Filter.new(Secret,:mine) 


def mine 
   {:find=>{:conditions=>["user_id=?",1]}, :create=>{:user_id=>1}} 
end 


def index 
   @secrets=Secret.find(:all) 
end 


def new 
   secret = Secret.create(:name=>rand(10000)) 
   if (secret.new_record?) 
     flash[:notice] = "Could not create Secret" 
   end 
   redirect_to :action=>"index" 
end 

Rails RMagick, image upload not in the model

Sometimes you don't want image upload in the model. Here's a controller class I use to upload a recipe image, standardize the size, create a thumbnail, and write them out.

This code uses a "attr_accessor :file" in the recipe model. file is not a table field, it's just a temporary variable for storing the data, before I load it into RMagick.
def do_upload_image
         image_types = ["image/jpeg", "image/pjpeg", "image/gif", "image/png", "image/x-png"]
         
         @recipe = Recipe.find(params[:id])
         @recipe.update_attributes(params[:recipe])
         logger.info "@recipe.file = " + @recipe.file.to_s
         if !@recipe.file.blank?
                 if (@recipe.file.size != 0) 
                         logger.info "content_type = " + @recipe.file.content_type.to_s
                         logger.info "size = " + @recipe.file.size.to_s
                         if (image_types.include?@recipe.file.content_type.chomp)
                         
                                 if @recipe.file.size < 2097152
                                         @recipe.file.rewind
                                         
                                         # Load the file field directly into the blob, straight from memory and into RMagick!  No need to write the raw file out to the filesystem
                                         pic = Magick::Image.from_blob(@recipe.file.read)[0]

                                         # I want to place the image inside a 200x200 jpg, with a white background. 
                                         # so all my images are the same size, while maintaning proportions.
                                         width = pic.columns
                                         height = pic.rows
                                         if (width > height)
                                                 pic.scale!((200.0/width.to_f))
                                         else
                                                 pic.scale!((200.0/height.to_f))
                                         end
                                         
                                         back = Magick::Image.new(200,200) {
                                                 self.background_color = 'white'
                                                 self.format = 'JPG'
                                         }
                                         back.composite!(pic, Magick::CenterGravity, Magick::InCompositeOp)
                                         
                                         # Now scale this down for a thumbnail
                                         thumb = back.scale(50,50)
                                         
                                         # Add a rand to the filename, so if we upload a new image, we're shown it, instead of whatever we have cached.
                                         rand = Kernel.rand(1000).to_s

                                         File.open(RAILS_ROOT + "/public/images/recipes/" + @recipe.id.to_s + "-" + rand + ".jpg", "wb") do |f|
                                                 f.write(back.to_blob)
                                         end
                                         File.open(RAILS_ROOT + "/public/images/recipes/" + @recipe.id.to_s + "-" + rand + "t.jpg", "wb") do |f|
                                                 f.write(thumb.to_blob)
                                         end

                                         @recipe.picture = "/images/recipes/" + @recipe.id.to_s + "-" + rand + "." + "jpg"
                                         @recipe.thumbnail = "/images/recipes/" + @recipe.id.to_s + "-" + rand + "t." + "jpg"
                                         @recipe.file = nil
                                         @recipe.save
                                         
                                         flash[:notice] = 'Image Uploaded and Thumbnailed'
                                         redirect_to :action => "edit", :id => @recipe
                                         #session[:recipe] = @recipe
                                 else
                                         flash.now[:error] = "File size greater then 2 Megabytes, please upload a smaller file."    
                                         render :action => 'upload_image', :id => @recipe
                                 end 
                         else 
                                 flash.now[:error] = "File doesn't seem to be JPG, GIF, or PNG, please ensure it is a valid image file."    
                                 render :action => 'upload_image', :id => @recipe
                         end
                 else
                         flash.now[:error] = "Unable to upload the file you selected, please try again."    
                         render :action => 'upload_image', :id => @recipe
                 end
         else
                 flash.now[:error] = "Unable to upload the file you selected, please try again."    
                 render :action => 'upload_image', :id => @recipe
         end
         
 end

Test helper for colorfull logging

Helper methods defined in this test_helper.rb make test.log colorfull and allow to easy find specific test cases and failures. To log test names use following template for test method:

def test_creates_entry
  log_test_name
  # Rest of your test code goes here
  # ...
end


test/test_helper.rb

ENV["RAILS_ENV"] = "test"
require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
require 'test_help'

module Test::Unit::Assertions
  def assert_block(message="assert_block failed.") # :yields:
    _wrap_assertion do
      if (! yield)
        logger.debug("\e[0;41mFailure:\e[m #{message}")
        raise Test::Unit::AssertionFailedError.new(message.to_s)
      else
        logger.debug("\e[0;32mSuccess\e[m")
      end
    end
  end
end

class Test::Unit::TestCase
  # Transactional fixtures accelerate your tests by wrapping each test method
  # in a transaction that's rolled back on completion.  This ensures that the
  # test database remains unchanged so your fixtures don't have to be reloaded
  # between every test method.  Fewer database queries means faster tests.
  #
  # Read Mike Clark's excellent walkthrough at
  #   http://clarkware.com/cgi/blosxom/2005/10/24#Rails10FastTesting
  #
  # Every Active Record database supports transactions except MyISAM tables
  # in MySQL.  Turn off transactional fixtures in this case; however, if you
  # don't care one way or the other, switching from MyISAM to InnoDB tables
  # is recommended.
  self.use_transactional_fixtures = true

  # Instantiated fixtures are slow, but give you @david where otherwise you
  # would need people(:david).  If you don't want to migrate your existing
  # test cases which use the @david style and don't mind the speed hit (each
  # instantiated fixtures translates to a database query per test method),
  # then set this back to true.
  self.use_instantiated_fixtures  = false

  def logger
    RAILS_DEFAULT_LOGGER
  end

  def log_test_name(test_name=nil)
    test_name = caller[0].match(/`(test_[a-z_]+)'$/) unless test_name
    logger.debug "\n\e[1m#{self.class}::\e[0;31m#{test_name}\e[m\n"
  end
end

class ActionController::Integration::Session
  def logger
    RAILS_DEFAULT_LOGGER
  end

  def log_step_name(step_name=nil)
    step_name = caller[0].match(/`(test_[a-z_]+)'$/) unless step_name
    logger.debug "\n\e[1m#{step_name}\e[m"
  end
end

symbolic link

ln -s /home/user/railsapps/app1/public /home/user/public_html/app1

Dynamic time based finder for ActiveRecord

I think it's pretty nice. Get all records within a railsified period of time (7.days.ago, 12.months.ago). I can do cool things like Workout.within_12_days or Workout.within_12_hours. Further conditions can be given as a hash, and will be transposed onto the end of the :conditions.

Workout.within_n_units(:user_id => 12) #-> Workout.find(:all, :conditions => 'created_at > n.units.ago and user_id = 12')


class Workout < ActiveRecord::Base
  class << self
    def within_n_temporal_units(number, units, further_conds={})
      conds = "created_at > '#{eval("#{number}.#{units}.ago").to_s(:db)}'"
      further_conds.each {|key, val| conds << " and #{key} = #{val}"}
      Workout.find(:all, :conditions => conds)
    end
    
    def method_missing(name, *args)
      return within_n_temporal_units($~[1], $~[2], args[0] || {}) if name.to_s =~ /within_(\d+)_(\w+)/
      raise NoMethodError, "undefined method `#{name}' for #{self}:Class"
    end
  end
end

Get the name of the controller used, when inside a view.

controller.controller_name

ActiveRecord DOM IDs

The solution—or at least a nice, cheap bandaid that can be applied easily, consists of adding a method to ActiveRecord::Base to help generate these ids without any brainpower involved.

Here’s a very simple implementation that I use in my projects, courtesy of Jamis Buck:



class ActiveRecord::Base
  def dom_id(prefix=nil)
    display_id = new_record? ? "new" : id
    prefix ||= self.class.name.underscore
    prefix != :bare ? "#{prefix.to_s.dasherize}-#{display_id}" : display_id
  end
endSo, you can do stuff like this in your views:

<ul>
<% @entries.each do |entry| %>
  
  • > <%= entry.body %>
  • <% end %> And stuff like this in your controller: def remove_entry entry = JournalEntry.find(params[:id]) update_page do |page| page[entry.dom_id].remove end end

    ruby stored procedures

    There are alot of reasons to use stored procedures. One of the most compelling reasons is that a system has already been built with stored procedures and interfacing with it cannot be by raw SQL. This situation is mainly caused by DBA’s whose job it is to control the flow of information into and out of the database. In “enterprise” situations this is the norm.


      @connection = OCI8.new("db_user", "db_password", "db_name")
    
      plsql = @connection.parse("BEGIN P_MYPROCEDURE.my_method(:out); END;")
      plsql.bind_param(':out', OCI8::Cursor) 
      plsql.exec
    
      cursor = plsql[':out']
      plsql.close
    
      x = ''
      while r = cursor.fetch()
        x = x + r.join(', ') + '
    ' end @out = x @connection.logout


    This code assumes you are using Rails 1.1 as an engine and that you have setup the database.yml for Oracle (10g in this post). The OCI8 object instantiated on the first line is in the OCI8 library which is loaded by Rails, specified in database.yml.

    Interfacing with Oracle and its stored procedures pretty much requires some knowledge about Oracle which has some very specific concepts that something like MySQL does not.

    First, to pass local variables to the stored procedure’s “in” and “out” variables, you must explicitly “bind” them.

    Second is the notion of “cursor”.

    Author: hksintl on http://blog.hksintl.com/

    Фильтр на обновление только разрешенных полей

    %w(name email address).each { |f| @person[f] = params[:person][f] }
    
    « Newer Snippets
    Older Snippets »
    64 total  XML / RSS feed