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 endWe 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.
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 ...
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 endThe 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 endA 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 endAs 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.
