Sha256: 2b5c44de19833b0456225d76f1bb21269068eb07853b383f526cfe62508c45b6

Contents?: true

Size: 1.93 KB

Versions: 5

Compression:

Stored size: 1.93 KB

Contents

module PGArrays
  module ReferencesBy
  	class RelationHolder < Struct.new(:relation, :field, :klass)
  	  
  	  def referenced(obj)
  	  	ids = obj.read_attribute(field) || []
 	  	klass.find( ids.sort ).sort_by{|o| ids.index(o.id)}
  	  end
  	  
  	  def set_referenced(obj, value)
        value = value.map{|v| 
  	      case v
  	  	    when ActiveRecord::Base then v.id
  	  	    when nil then nil
  	  	    else v.to_i
  	  	  end
  	  	}.compact
  	  	obj.write_attribute( field, value )
  	  end
  	  
  	  def validate(obj)
  	  	has_ids = klass.find(:all, :select=>'id', :conditions=>{:id=>obj.read_attribute(field)}).map(&:id)
  	  	unless has_ids.sort == obj.read_attribute(field).sort
  	  	  obj.errors.add(relation, :wrong_array_reference)
  	  	end
  	  end
  	  
  	  def for_referenced(obj_klass)
  	  	condition = lambda do |obj| 
  	  	  { :conditions=>{field.to_sym => case obj when klass then obj.id else obj.to_i end} } 
  	  	end
  	  	obj_klass.send(:named_scope, "#{relation}_include", condition )
  	  end
  	  
  	end
  	
  	module ClassMethods
  	  def references_by_array( relation, options = {} )
  	  	unless ActiveSupport::Memoizable === self
  	  	  extend ActiveSupport::Memoizable
  	  	end

  	  	relation = relation.to_s.pluralize
  	  	field = "#{relation.singularize}_ids"
  	  	klass_name = (options[:class_name] || relation).to_s.singularize.camelize
  	    klass = klass_name.constantize
  	    holder = RelationHolder.new(relation, field, klass )
  	    
  	    define_method(relation) do
  	      holder.referenced(self)
  	    end
  	    memoize relation
  	    
  	    define_method("#{relation}=") do |value|
  	      flush_cache(relation)
  	      holder.set_referenced(self, value)
  	    end
  	    
  	    if options[:validate]
  	      validate {|o| holder.validate(o)}
  	    end
  	    
  	    holder.for_referenced(self)
  	  end
  	  
  	end
  end
end

ActiveRecord::Base.extend PGArrays::ReferencesBy::ClassMethods

Version data entries

5 entries across 5 versions & 1 rubygems

Version Path
ar_pg_array-0.8.4 lib/ar_pg_array/references_by.rb
ar_pg_array-0.8.3 lib/ar_pg_array/references_by.rb
ar_pg_array-0.8.2 lib/ar_pg_array/references_by.rb
ar_pg_array-0.8.1 lib/ar_pg_array/references_by.rb
ar_pg_array-0.8.0 lib/ar_pg_array/references_by.rb