module RearUtils

Public Class Methods

ar?(model) click to toggle source
# File lib/rear/utils.rb, line 238
def ar? model
  [:connection, :columns, :reflect_on_all_associations].all? do |m|
    model.respond_to?(m)
  end
end
associated_model_controller(model, ensure_mounted = false) click to toggle source
# File lib/rear/utils.rb, line 15
def associated_model_controller model, ensure_mounted = false
  ctrl = ObjectSpace.each_object(Class).find do |o|
    EUtils.is_app?(o) && o.respond_to?(:model) && o.model == model
  end
  unless ctrl
    ctrl = initialize_model_controller(model)
    ctrl.label(false) # automatically generated controllers not shown in menu
  end
  ctrl.mounted? || ctrl.mount if ensure_mounted
  ctrl
end
dm?(model) click to toggle source
# File lib/rear/utils.rb, line 245
def dm? model
  [:repository, :properties, :relationships].all? do |m|
    model.respond_to?(m)
  end
end
dom_id_generator(*args) click to toggle source
# File lib/rear/utils.rb, line 276
def dom_id_generator *args
  (args + [args.__id__]).flatten.join('__').gsub(/\W+/, '')
end
extract_ar_assocs(model, any = false) click to toggle source
# File lib/rear/utils.rb, line 51
def extract_ar_assocs model, any = false
  model.reflect_on_all_associations.inject(ASSOCS__STRUCT.call) do |map, r|
    
    target_model = extract_associated_ar_model(model, r) ||
      raise(NameError, "Was unable to detect model for %s relation" % r)

    target_pkey = r.options[:primary_key] || target_model.primary_key
    if any || target_pkey  # models without primary key not handled by default
      
      target_pkey = target_pkey.to_sym if target_pkey
      readonly = nil
      belongs_to_keys = {source: nil, target: nil}

      assoc_type = case r.macro
      when :belongs_to
        belongs_to_keys[:source] = (r.options[:foreign_key] || ActiveSupport::Inflector.foreign_key(r.name)).to_sym
        belongs_to_keys[:target] = target_pkey
        :belongs_to
      when :has_one
        readonly = true if r.options[:through]
        :has_one
      else
        :has_many
      end

      map[assoc_type].update r.name => {
                type: assoc_type,
                name: r.name,
        remote_model: target_model,
         remote_pkey: target_pkey,
            readonly: readonly,
              dom_id: dom_id_generator(model, assoc_type, r.name),
        belongs_to_keys: belongs_to_keys
      }.freeze
    end
    map
  end.freeze
end
extract_ar_columns(model) click to toggle source
# File lib/rear/utils.rb, line 169
def extract_ar_columns model
  unless model.table_exists?
    puts "WARN: %s table does not exists!" % model.table_name
    return [[], :id]
  end
  pkey = nil
  columns = model.columns.inject([]) do |f,c|
    name, type = c.name.to_sym, c.type.to_s.downcase.to_sym
    type = COLUMNS__DEFAULT_TYPE unless COLUMNS__HANDLED_TYPES.include?(type)
    (c.primary && pkey = name) ? f : f << [name, type]
  end
  [columns.freeze, pkey]
end
extract_associated_ar_model(model, assoc) click to toggle source
# File lib/rear/utils.rb, line 33
def extract_associated_ar_model model, assoc
  class_name = assoc.options[:class_name] ||
    ActiveSupport::Inflector.camelize(ActiveSupport::Inflector.singularize(assoc.name.to_s))
  if (ns = class_name.to_s.split('::')).size > 1
    return ns.inject(Object) {|n,c| n.const_get c}
  else
    if (ns = model.name.split('::')).size > 1
      ns.pop
      model_namespace = ns.inject(Object) {|n,c| n.const_get c}
    else
      model_namespace = Object
    end
    return model_namespace.const_get(class_name)
  end
  nil
end
extract_assocs(model, *args) click to toggle source
# File lib/rear/utils.rb, line 28
def extract_assocs model, *args
  send('extract_%s_assocs' % orm(model), model, *args)
end
extract_columns(model) click to toggle source
# File lib/rear/utils.rb, line 164
def extract_columns model
  send('extract_%s_columns' % orm(model), model)
end
extract_constant(smth) click to toggle source
# File lib/rear/utils.rb, line 281
def extract_constant smth
  return Object.const_get(smth) if smth.is_a?(Symbol)
  return smth.sub('::', '').split('::').inject(Object) {|o,c| o.const_get(c)} if smth.is_a?(String)
  smth
end
extract_dm_assocs(model, any = false) click to toggle source
# File lib/rear/utils.rb, line 91
def extract_dm_assocs model, any = false
  model.relationships.entries.inject(ASSOCS__STRUCT.call) do |map, r|
    _, target_pkey = extract_dm_columns(r.target_model)
    if any || target_pkey # only models with a primary key are handled by default

      readonly = nil
      belongs_to_keys = {source: nil, target: nil}

      assoc_type = case r.class.name.split('::')[2]
      when 'ManyToOne'
        belongs_to_keys[:source] = r.source_key.first.name.to_sym
        belongs_to_keys[:target] = r.target_key.first.name.to_sym
        :belongs_to
      when 'OneToOne'
        readonly = true if r.options[:through]
        :has_one
      else
        :has_many
      end

      map[assoc_type].update r.name => {
                type: assoc_type,
                name: r.name,
        remote_model: r.target_model,
         remote_pkey: target_pkey,
            readonly: readonly,
              dom_id: dom_id_generator(model, assoc_type, r.name),
        belongs_to_keys: belongs_to_keys
      }.freeze
    end
    map
  end.freeze
end
extract_dm_columns(model) click to toggle source
# File lib/rear/utils.rb, line 184
def extract_dm_columns model
  pkey = nil
  # TODO: find a way to handle Enum columns
  columns = model.properties.inject([]) do |f,c|
    name, type = c.name.to_sym, c.class.name.to_s.split('::').last.downcase.to_sym
    type = COLUMNS__DEFAULT_TYPE unless [:serial].concat(COLUMNS__HANDLED_TYPES).include?(type)
    (type == :serial && pkey = name) ? f : f << [name, type]
  end
  [columns.freeze, pkey]
end
extract_sq_assocs(model, any = false) click to toggle source
# File lib/rear/utils.rb, line 126
def extract_sq_assocs model, any = false
  model.associations.inject(ASSOCS__STRUCT.call) do |map,an|
    a = model.association_reflection(an)
    
    target_model = extract_constant(a[:class_name])
    _, target_pkey = extract_sq_columns(target_model)
    
    if any || target_pkey # only models with a primary key are handled by default
      readonly = nil
      belongs_to_keys = {source: nil, target: nil}

      assoc_type = case a[:type]
      when :many_to_one
        belongs_to_keys[:source] = a[:key]
        belongs_to_keys[:target] = a[:primary_key] || target_pkey
        :belongs_to
      when :one_to_one
        readonly = true if a[:through]
        :has_one
      else
        :has_many
      end

      map[assoc_type].update a[:name] => {
                type: assoc_type,
                name: a[:name],
        remote_model: target_model,
         remote_pkey: target_pkey,
            readonly: readonly,
              dom_id: dom_id_generator(model, assoc_type, a[:name]),
          belongs_to_keys: belongs_to_keys
      }.freeze
    end
    map
  end.freeze
end
extract_sq_columns(model) click to toggle source
# File lib/rear/utils.rb, line 196
def extract_sq_columns model
  pkey = nil
  columns = model.db_schema.inject([]) do |map,(n,s)|
    if s[:primary_key]
      pkey = n
      map
    else
      type = s[:db_type].to_s.split(/\W/).first.to_s.downcase.to_sym
      unless COLUMNS__HANDLED_TYPES.include?(type)
        type = s[:type].to_s.downcase.to_sym
        unless COLUMNS__HANDLED_TYPES.include?(type)
          type = COLUMNS__DEFAULT_TYPE
        end
      end
      map << [n, type]
    end
  end
  [columns.freeze, pkey]
end
initialize_model_controller(model) click to toggle source

just define controller, do not set model

# File lib/rear/utils.rb, line 5
def initialize_model_controller model
  return model.const_get(:RearController) if model.const_defined?(:RearController)
  ctrl = model.const_set(:RearController, Class.new(E))
  RearControllerSetup.init(ctrl)
  ctrl.map EUtils.class_to_route(model)
  ctrl.model model
  ctrl
end
is_orm?(model)
Alias for: orm
normalize_html_attrs(attrs) click to toggle source
# File lib/rear/utils.rb, line 271
def normalize_html_attrs attrs
  (attrs||{}).inject({}) {|h,(k,v)| h.merge k.to_s.downcase => v}
end
number_with_delimiter(n) click to toggle source
# File lib/rear/utils.rb, line 266
def number_with_delimiter n
  n.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, '\1,')
end
orm(model) click to toggle source
# File lib/rear/utils.rb, line 259
def orm model
  [:ar, :dm, :sq].find {|o| send('%s?' % o, model)}
end
Also aliased as: is_orm?
quote_ar_column(model, column) click to toggle source
# File lib/rear/utils.rb, line 222
def quote_ar_column model, column
  model.connection.quote_column_name(column)
end
quote_column(model, column) click to toggle source
# File lib/rear/utils.rb, line 217
def quote_column model, column
  send('quote_%s_column' % orm(model), model, column)
end
quote_dm_column(model, column) click to toggle source
# File lib/rear/utils.rb, line 227
def quote_dm_column model, column
  property = model.properties.find {|p| p.name == column}
  model.repository(model.repository_name).adapter.property_to_column_name(property, false)
end
quote_sq_column(model, column) click to toggle source
# File lib/rear/utils.rb, line 233
def quote_sq_column model, column
  model.db.quote_identifier(column)
end
sq?(model) click to toggle source
# File lib/rear/utils.rb, line 252
def sq? model
  [:db_schema, :columns, :dataset, :associations].all? do |m|
    model.respond_to?(m)
  end
end

Private Instance Methods

ar?(model) click to toggle source
# File lib/rear/utils.rb, line 238
def ar? model
  [:connection, :columns, :reflect_on_all_associations].all? do |m|
    model.respond_to?(m)
  end
end
associated_model_controller(model, ensure_mounted = false) click to toggle source
# File lib/rear/utils.rb, line 15
def associated_model_controller model, ensure_mounted = false
  ctrl = ObjectSpace.each_object(Class).find do |o|
    EUtils.is_app?(o) && o.respond_to?(:model) && o.model == model
  end
  unless ctrl
    ctrl = initialize_model_controller(model)
    ctrl.label(false) # automatically generated controllers not shown in menu
  end
  ctrl.mounted? || ctrl.mount if ensure_mounted
  ctrl
end
dm?(model) click to toggle source
# File lib/rear/utils.rb, line 245
def dm? model
  [:repository, :properties, :relationships].all? do |m|
    model.respond_to?(m)
  end
end
dom_id_generator(*args) click to toggle source
# File lib/rear/utils.rb, line 276
def dom_id_generator *args
  (args + [args.__id__]).flatten.join('__').gsub(/\W+/, '')
end
extract_ar_assocs(model, any = false) click to toggle source
# File lib/rear/utils.rb, line 51
def extract_ar_assocs model, any = false
  model.reflect_on_all_associations.inject(ASSOCS__STRUCT.call) do |map, r|
    
    target_model = extract_associated_ar_model(model, r) ||
      raise(NameError, "Was unable to detect model for %s relation" % r)

    target_pkey = r.options[:primary_key] || target_model.primary_key
    if any || target_pkey  # models without primary key not handled by default
      
      target_pkey = target_pkey.to_sym if target_pkey
      readonly = nil
      belongs_to_keys = {source: nil, target: nil}

      assoc_type = case r.macro
      when :belongs_to
        belongs_to_keys[:source] = (r.options[:foreign_key] || ActiveSupport::Inflector.foreign_key(r.name)).to_sym
        belongs_to_keys[:target] = target_pkey
        :belongs_to
      when :has_one
        readonly = true if r.options[:through]
        :has_one
      else
        :has_many
      end

      map[assoc_type].update r.name => {
                type: assoc_type,
                name: r.name,
        remote_model: target_model,
         remote_pkey: target_pkey,
            readonly: readonly,
              dom_id: dom_id_generator(model, assoc_type, r.name),
        belongs_to_keys: belongs_to_keys
      }.freeze
    end
    map
  end.freeze
end
extract_ar_columns(model) click to toggle source
# File lib/rear/utils.rb, line 169
def extract_ar_columns model
  unless model.table_exists?
    puts "WARN: %s table does not exists!" % model.table_name
    return [[], :id]
  end
  pkey = nil
  columns = model.columns.inject([]) do |f,c|
    name, type = c.name.to_sym, c.type.to_s.downcase.to_sym
    type = COLUMNS__DEFAULT_TYPE unless COLUMNS__HANDLED_TYPES.include?(type)
    (c.primary && pkey = name) ? f : f << [name, type]
  end
  [columns.freeze, pkey]
end
extract_associated_ar_model(model, assoc) click to toggle source
# File lib/rear/utils.rb, line 33
def extract_associated_ar_model model, assoc
  class_name = assoc.options[:class_name] ||
    ActiveSupport::Inflector.camelize(ActiveSupport::Inflector.singularize(assoc.name.to_s))
  if (ns = class_name.to_s.split('::')).size > 1
    return ns.inject(Object) {|n,c| n.const_get c}
  else
    if (ns = model.name.split('::')).size > 1
      ns.pop
      model_namespace = ns.inject(Object) {|n,c| n.const_get c}
    else
      model_namespace = Object
    end
    return model_namespace.const_get(class_name)
  end
  nil
end
extract_assocs(model, *args) click to toggle source
# File lib/rear/utils.rb, line 28
def extract_assocs model, *args
  send('extract_%s_assocs' % orm(model), model, *args)
end
extract_columns(model) click to toggle source
# File lib/rear/utils.rb, line 164
def extract_columns model
  send('extract_%s_columns' % orm(model), model)
end
extract_constant(smth) click to toggle source
# File lib/rear/utils.rb, line 281
def extract_constant smth
  return Object.const_get(smth) if smth.is_a?(Symbol)
  return smth.sub('::', '').split('::').inject(Object) {|o,c| o.const_get(c)} if smth.is_a?(String)
  smth
end
extract_dm_assocs(model, any = false) click to toggle source
# File lib/rear/utils.rb, line 91
def extract_dm_assocs model, any = false
  model.relationships.entries.inject(ASSOCS__STRUCT.call) do |map, r|
    _, target_pkey = extract_dm_columns(r.target_model)
    if any || target_pkey # only models with a primary key are handled by default

      readonly = nil
      belongs_to_keys = {source: nil, target: nil}

      assoc_type = case r.class.name.split('::')[2]
      when 'ManyToOne'
        belongs_to_keys[:source] = r.source_key.first.name.to_sym
        belongs_to_keys[:target] = r.target_key.first.name.to_sym
        :belongs_to
      when 'OneToOne'
        readonly = true if r.options[:through]
        :has_one
      else
        :has_many
      end

      map[assoc_type].update r.name => {
                type: assoc_type,
                name: r.name,
        remote_model: r.target_model,
         remote_pkey: target_pkey,
            readonly: readonly,
              dom_id: dom_id_generator(model, assoc_type, r.name),
        belongs_to_keys: belongs_to_keys
      }.freeze
    end
    map
  end.freeze
end
extract_dm_columns(model) click to toggle source
# File lib/rear/utils.rb, line 184
def extract_dm_columns model
  pkey = nil
  # TODO: find a way to handle Enum columns
  columns = model.properties.inject([]) do |f,c|
    name, type = c.name.to_sym, c.class.name.to_s.split('::').last.downcase.to_sym
    type = COLUMNS__DEFAULT_TYPE unless [:serial].concat(COLUMNS__HANDLED_TYPES).include?(type)
    (type == :serial && pkey = name) ? f : f << [name, type]
  end
  [columns.freeze, pkey]
end
extract_sq_assocs(model, any = false) click to toggle source
# File lib/rear/utils.rb, line 126
def extract_sq_assocs model, any = false
  model.associations.inject(ASSOCS__STRUCT.call) do |map,an|
    a = model.association_reflection(an)
    
    target_model = extract_constant(a[:class_name])
    _, target_pkey = extract_sq_columns(target_model)
    
    if any || target_pkey # only models with a primary key are handled by default
      readonly = nil
      belongs_to_keys = {source: nil, target: nil}

      assoc_type = case a[:type]
      when :many_to_one
        belongs_to_keys[:source] = a[:key]
        belongs_to_keys[:target] = a[:primary_key] || target_pkey
        :belongs_to
      when :one_to_one
        readonly = true if a[:through]
        :has_one
      else
        :has_many
      end

      map[assoc_type].update a[:name] => {
                type: assoc_type,
                name: a[:name],
        remote_model: target_model,
         remote_pkey: target_pkey,
            readonly: readonly,
              dom_id: dom_id_generator(model, assoc_type, a[:name]),
          belongs_to_keys: belongs_to_keys
      }.freeze
    end
    map
  end.freeze
end
extract_sq_columns(model) click to toggle source
# File lib/rear/utils.rb, line 196
def extract_sq_columns model
  pkey = nil
  columns = model.db_schema.inject([]) do |map,(n,s)|
    if s[:primary_key]
      pkey = n
      map
    else
      type = s[:db_type].to_s.split(/\W/).first.to_s.downcase.to_sym
      unless COLUMNS__HANDLED_TYPES.include?(type)
        type = s[:type].to_s.downcase.to_sym
        unless COLUMNS__HANDLED_TYPES.include?(type)
          type = COLUMNS__DEFAULT_TYPE
        end
      end
      map << [n, type]
    end
  end
  [columns.freeze, pkey]
end
initialize_model_controller(model) click to toggle source

just define controller, do not set model

# File lib/rear/utils.rb, line 5
def initialize_model_controller model
  return model.const_get(:RearController) if model.const_defined?(:RearController)
  ctrl = model.const_set(:RearController, Class.new(E))
  RearControllerSetup.init(ctrl)
  ctrl.map EUtils.class_to_route(model)
  ctrl.model model
  ctrl
end
is_orm?(model)
Alias for: orm
normalize_html_attrs(attrs) click to toggle source
# File lib/rear/utils.rb, line 271
def normalize_html_attrs attrs
  (attrs||{}).inject({}) {|h,(k,v)| h.merge k.to_s.downcase => v}
end
number_with_delimiter(n) click to toggle source
# File lib/rear/utils.rb, line 266
def number_with_delimiter n
  n.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, '\1,')
end
orm(model) click to toggle source
# File lib/rear/utils.rb, line 259
def orm model
  [:ar, :dm, :sq].find {|o| send('%s?' % o, model)}
end
Also aliased as: is_orm?
quote_ar_column(model, column) click to toggle source
# File lib/rear/utils.rb, line 222
def quote_ar_column model, column
  model.connection.quote_column_name(column)
end
quote_column(model, column) click to toggle source
# File lib/rear/utils.rb, line 217
def quote_column model, column
  send('quote_%s_column' % orm(model), model, column)
end
quote_dm_column(model, column) click to toggle source
# File lib/rear/utils.rb, line 227
def quote_dm_column model, column
  property = model.properties.find {|p| p.name == column}
  model.repository(model.repository_name).adapter.property_to_column_name(property, false)
end
quote_sq_column(model, column) click to toggle source
# File lib/rear/utils.rb, line 233
def quote_sq_column model, column
  model.db.quote_identifier(column)
end
sq?(model) click to toggle source
# File lib/rear/utils.rb, line 252
def sq? model
  [:db_schema, :columns, :dataset, :associations].all? do |m|
    model.respond_to?(m)
  end
end