Opensteam_blog_logo4
opensteam.net | rss | search | archive
Results (escape to close):

form_tag block in a helper-method

Posted by michael.schaerfer on 24-Jul-08 at 07:45


According to this Ticket, using form_tag with a block in a helper-method is broken in rails 2.1.

Here is a, not so elegant but working, solution:
   1  def render_form_tag_in_helper( _erbout, url, *args )
   2    form_tag( url ) do
   3      concat( submit_tag("button"), binding )
   4    end
   5  end
We have to pass the _erbout-variable to the helper-method in order to make the form_tag-method work. And to add elements to the form (submit_buttons, text_fields, etc), we have to call concat (to add the elements to the _erbout variable) with the current binding.
Comments: 0 (view/add your own) Tags: code

Column/Attribute names for a model

Posted by michael.schaerfer on 23-Jul-08 at 20:06

A quick way to get all column/attribute names for a model: (normal columns are Strings, association-attributes are Symbols)

   1  # returns all columns/attributes for a model
   2  # column-names used for associations (foreign_keys) are replaces by their
   3  # association-names (as symbol).
   4  def get_column_names_for( record )
   5    # get all column-names, check for foreign_keys and replace them by association_name
   6    record.columns.collect(&:name).collect { |c|
   7        (a = check_association( record, c ) ).empty? ? c : a.collect(&:name)
   8    }.flatten.uniq + 
   9    # get all has_one/has_many/habtm association names
  10    record.reflect_on_all_associations.select { |a| a.macro.to_s =~/^has/ }.collect(&:name)
  11  
  12  end
  13    
  14    
  15  def check_association( record, string )
  16    # check if +string+ (like "artist_id") is a foreign_key for an association
  17    # if yes, return association.
  18    record.reflect_on_all_associations.select { |a| a.options[:foreign_key] ? 
  19      a.options[:foreign_key].to_sym == string.to_sym : 
  20      a.name.to_s.foreign_key.to_sym == string.to_sym }
  21  end

Useful if you want to build like an automatic scaffold function or ...

Comments: 0 (view/add your own) Tags: code

State-Pattern using Modules

Posted by michael.schaerfer on 22-Jul-08 at 21:20


In the last weeks, we tried to implement a state-pattern for our orders, simply put: different states means different functionality.
We tried various approaches, like simple state-symbols, state-classes (to hold the state-specifc methods and return new states), state-associations and the very nice AASM plugin by Scott Barron.
But all this techniques felt very clumsy for our simple needs and not so ... 'ruby-like'.

Then i stumbled across Jay Fields Post and really liked the approach of using just state-modules and delegating to the instance_method ('cause all modules included in a class are just ancestors of this class!).

Here a brief overview of our solution:
   1  # the order-class
   2  class Order
   3    include StateLogic
   4  
   5    #states
   6    include Finished
   7    attr_accessor :state
   8  end
The StateLogic Module (defines the 'fire_event' method to delegate to the state-module).
   1  module StateLogic
   2    def fire_event(name, *args, &block)
   3      state_module = self.state.classify.constantize
   4      
   5      if state_module.instance_methods(false).include?(name)
   6        state_module.instance_method(m).bind( self ).call( *args, &block )
   7      else
   8        puts "event '#{name}' not defined for state '#{state}'"
   9        return false
  10      end
  11    end
  12  end
A State-Module
   1  module Finished
   2    def self.included(base)
   3      self.instance_methods(false).each do |m|
   4        base.class_eval do
   5          define_method(m) { |*args| fire_event(m,*args) }
   6        end
   7      end
   8    end
   9  
  10    #an event
  11    def say_something
  12      puts "now in state '#{state}'"
  13    end
  14  
  15  end    
As you can see, we override every state-module instance_method in the receiver-class to call the fire_event method. And in this method, we check if the current state-module defines such an instance_method, bind it to the order-instance and call it (or printing an error message, if no such method is defined in the current state-module.)
Pretty simple!

openSteam v0.9.1 soon!

Posted by michael.schaerfer on 22-Jul-08 at 21:08

We're currently working hard on the next openSteam release (v0.9.1).

A full list of new features will come in the next days, but for now: there will be invoices and shipments, lots of refactored code, many states and a simple extension-mechanism for the admin-backend.

Comments: 0 (view/add your own) Tags: release