Module: Magnetic::Field

Defined in:
lib/magnetic/field.rb

Defined Under Namespace

Modules: DSL Classes: Set

Constant Summary collapse

Base =
Object.prototype do
  name nil
  owner nil
  #controller nil
  model nil
  #interface nil
  #records nil
  value nil
  #path nil
  type :html 

  def __
    @__ ||= Pervasives::Proxy.new(self)
  end

  def to_s
    value.to_s
  end

  attribute('template_root'){ File.join RAILS_ROOT, 'app', 'views', 'magnetic' }
  attribute('template_dir'){ File.join template_root, File.join(*owner.name.gsub(%r/^:+/,'').split(%r/::/)).downcase }
  attribute('template_base'){ name }
  #attribute('template_ext'){ type.to_s  }
  attribute('template_prefix'){ File.join(template_dir, template_base) }
  attribute('template_inline'){ send "template_inline_#{ type }" }
  attribute('template_text'){ nil }
  attribute('template_map'){ { 'html' => 'rhtml', 'xml' => 'rxml' } }

#
# TODO - this needs to be thought out further
#
  def render *argv 
    raise 'recursive render!' if defined?(@inside_render) and @inside_render
    @inside_render = true
    begin
      field = self

      type = argv.delete_first{|arg| String === arg or Symbol === arg } || self.type
      type = type.to_s

      options = argv.delete_first{|arg| Hash === arg} || {}
      options.to_options!

      msg = options.delete(:render) || :render_to_string

      text = options[:text] || template_text rescue nil
      inline = options[:inline] || template_inline rescue nil

      unless text or inline
        file = options[:file] 
        unless file
          ext = (template_map[type] || type).gsub %r/^\.?/, '.'
          options[:file] = template_prefix + ext
        end
      end

      controller.clone.instance_eval do
        @field = field 
        (options[:locals] ||= {}).update :field => @field 
        send msg, options
      end
    ensure
      @inside_render = false
    end
  end

  def configure options = {}, &block
    options.to_options!
    prototyping do
      options.each do |k,v|
        begin
          __send__ "#{ k }=", v
        rescue
          __attribute__ k => v
        end
      end
    end
    prototyping &block
    self
  end
  alias_method 'configured', 'configure'

  def to_proc
    @to_proc ||= lambda do |options|
      options.to_options!
      field = self
      value = options[:value]
      unless value.nil?
        sc =
          class << value
            self
          end
        sc.module_eval do
          define_method :field do
            field.configure options
            field
          end
        end
      end
    end
  end


  def to_proc
    @to_proc ||= lambda do |options|
      field = self
      field_options = options.to_options
      value = options[:value]
      raise ArgumentError, "no value in <#{ options.inspect }>" unless value
      value.extend ConfiguredFieldMethod
      value.field = field 
      value.field_options = field_options
    end
  end

  module ConfiguredFieldMethod
    attr_writer 'field'
    attr_writer 'field_options'

    def field
      @field_options.each do |k, v|
        unless @field.respond_to? k
          sc =
            class << @field
              self
            end
          sc.module_eval{ attribute k }
        end
        @field.send "#{ k }=", v
      end
      @field
    end
  end

  def === other
    Base.class === other
  end
end