Class: RPCMapper::Relation

Inherits:
Object
  • Object
show all
Includes:
FinderMethods, QueryMethods
Defined in:
lib/rpc_mapper/relation.rb

Overview

TRP: The concepts behind this class are heavily influenced by ActiveRecord::Relation v.3.0.0RC1

> github.com/rails/rails

Used to achieve the chainability of scopes – methods are delegated back and forth from BM::Base and BM::Relation

Constant Summary collapse

SINGLE_VALUE_METHODS =
[:limit, :offset, :from, :fresh]
MULTI_VALUE_METHODS =
[:select, :group, :order, :joins, :includes, :where, :having]
FINDER_OPTIONS =
SINGLE_VALUE_METHODS + MULTI_VALUE_METHODS + [:conditions, :search, :sql]

Instance Attribute Summary collapse

Attributes included from QueryMethods

#fresh_value, #from_value, #group_values, #having_values, #includes_values, #joins_values, #limit_value, #offset_value, #order_values, #raw_sql_value, #select_values, #where_values

Instance Method Summary collapse

Methods included from FinderMethods

#all, #apply_finder_options, #find, #first, #search

Methods included from QueryMethods

#fresh, #from, #group, #having, #includes, #joins, #limit, #offset, #order, #select, #sql, #where

Constructor Details

#initialize(klass) ⇒ Relation

Returns a new instance of Relation.



17
18
19
20
21
22
# File 'lib/rpc_mapper/relation.rb', line 17

def initialize(klass)
  @klass = klass

  SINGLE_VALUE_METHODS.each {|v| instance_variable_set(:"@#{v}_value", nil)}
  MULTI_VALUE_METHODS.each {|v| instance_variable_set(:"@#{v}_values", [])}
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object (protected)



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/rpc_mapper/relation.rb', line 104

def method_missing(method, *args, &block)
  if Array.method_defined?(method)
    to_a.send(method, *args, &block)
  elsif result = dynamic_finder_method(method)
    method, attribute = result
    options = { :conditions => { attribute => args[0] } }
    options.merge!(args[1]) if args[1] && args[1].is_a?(Hash)
    case method.to_sym
    when :find_by
      self.first(options)
    when :find_all_by
      self.all(options)
    end
  elsif @klass.scopes[method]
    merge(@klass.send(method, *args, &block))
  elsif @klass.respond_to?(method, false)
    scoping { @klass.send(method, *args, &block) }
  else
    super
  end
end

Instance Attribute Details

#klassObject (readonly)

Returns the value of attribute klass.



8
9
10
# File 'lib/rpc_mapper/relation.rb', line 8

def klass
  @klass
end

Instance Method Details

#dynamic_finder_method(method) ⇒ Object



93
94
95
96
97
98
99
100
# File 'lib/rpc_mapper/relation.rb', line 93

def dynamic_finder_method(method)
  defined_attributes = (@klass.defined_attributes || []).join('|')
  if method.to_s =~ /^(find_by|find_all_by)_(#{defined_attributes})/
    [$1, $2]
  else
    nil
  end
end

#eager_load?Boolean

Returns:

  • (Boolean)


68
69
70
# File 'lib/rpc_mapper/relation.rb', line 68

def eager_load?
  @includes_values && !@includes_values.empty?
end

#inspectObject



72
73
74
# File 'lib/rpc_mapper/relation.rb', line 72

def inspect
 to_a.inspect
end

#merge(r) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/rpc_mapper/relation.rb', line 24

def merge(r)
  merged_relation = clone
  return merged_relation unless r

  SINGLE_VALUE_METHODS.each do |option|
    new_value = r.send("#{option}_value")
    merged_relation = merged_relation.send(option, new_value) if new_value
  end

  MULTI_VALUE_METHODS.each do |option|
    merged_relation = merged_relation.send(option, *r.send("#{option}_values"))
  end

  merged_relation
end

#respond_to?(method, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


85
86
87
88
89
90
91
# File 'lib/rpc_mapper/relation.rb', line 85

def respond_to?(method, include_private=false)
  super ||
  Array.method_defined?(method) ||
  @klass.scopes[method] ||
  dynamic_finder_method(method) ||
  @klass.respond_to?(method, false)
end

#scopingObject



76
77
78
79
80
81
82
83
# File 'lib/rpc_mapper/relation.rb', line 76

def scoping
  @klass.scoped_methods << self
  begin
    yield
  ensure
    @klass.scoped_methods.pop
  end
end

#to_aObject



64
65
66
# File 'lib/rpc_mapper/relation.rb', line 64

def to_a
  @records ||= fetch_records
end

#to_hashObject



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/rpc_mapper/relation.rb', line 40

def to_hash
  # TRP: If present pass :sql option alone as it trumps all other options
  @hash ||= if self.raw_sql_value
    { :sql => raw_sql_value }
  else
    hash = SINGLE_VALUE_METHODS.inject({}) do |h, option|
      value = self.send("#{option}_value")
      value ? h.merge(option => value) : h
    end

    hash.merge!((MULTI_VALUE_METHODS - [:select]).inject({}) do |h, option|
      value = self.send("#{option}_values")
      value && !value.empty? ? h.merge(option => value.uniq) : h
    end)

    # TRP: If one of the select options contains a * than select options are ignored
    if select_values && !select_values.empty? && !select_values.any? { |val| val.to_s.match(/\*$/) }
      hash.merge!(:select => select_values.uniq)
    end

    hash
  end
end