Class: Armada::Relation

Inherits:
Object
  • Object
show all
Defined in:
lib/armada/relation.rb

Constant Summary collapse

FIND_OPTIONS_KEYS =
%w(where offset order limit only distinct)

Instance Method Summary collapse

Constructor Details

#initialize(superclass) ⇒ Relation

Returns a new instance of Relation.



29
30
31
32
# File 'lib/armada/relation.rb', line 29

def initialize(superclass)
  @superclass = superclass
  @join = "and"
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

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



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/armada/relation.rb', line 147

def method_missing(method, *args, &block)
  method = method.to_s
  if %w(create_index drop_index).include?(method)
    singleton_class.send(:define_method, method) do
      raise(ArgumentError, "Missing 'order' condition") unless option_defined?(:order)
      query(to_query(method, @order)) == 1
    end.call
  elsif %w(delete count update insert select checked_write multi_read multi_write list_indexes).include?(method)
    singleton_class.send(:define_method, method) do |*args, &block|
      query(to_query(method, *args, &block))
    end.call(*args, &block)
  else
    super
  end
end

Instance Method Details

#allObject



130
131
132
133
134
# File 'lib/armada/relation.rb', line 130

def all
  results = self.select
  return results if option_defined?(:only) || @superclass.is_a?(String)
  results.map { |record| @superclass.send(:instantiate, record) }
end

#distinctObject



122
123
124
# File 'lib/armada/relation.rb', line 122

def distinct
  self.dup.tap { |r| r.set_option(:distinct, true) }
end

#get_option(option) ⇒ Object



141
142
143
# File 'lib/armada/relation.rb', line 141

def get_option(option)
  instance_variable_get("@#{option}")
end

#limit(value) ⇒ Object



83
84
85
# File 'lib/armada/relation.rb', line 83

def limit(value)
  self.dup.tap { |r| r.set_option(:limit, value) }
end

#offset(value) ⇒ Object



79
80
81
# File 'lib/armada/relation.rb', line 79

def offset(value)
  self.dup.tap { |r| r.set_option(:offset, value) }
end

#only(*attributes) ⇒ Object



111
112
113
114
115
116
117
118
119
120
# File 'lib/armada/relation.rb', line 111

def only(*attributes)
  attributes.flatten!
  only = if option_defined?(:only)
    Array.wrap(@only).concat(attributes)
  else
    attributes.size == 1 ? attributes.first : attributes
  end
  
  self.dup.tap { |r| r.set_option(:only, only) }
end

#orObject

Raises:

  • (ArgumentError)


74
75
76
77
# File 'lib/armada/relation.rb', line 74

def or
  raise(ArgumentError, "Missing 'where' condition") unless option_defined?(:where)
  self.dup.tap { |r| r.set_option(:join, "or") }
end

#order(*attributes) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/armada/relation.rb', line 87

def order(*attributes)
  options = attributes.extract_options!
  
  attributes.flatten!
  attributes.map! do |attribute|
    attribute.is_a?(Array) ? attribute : [attribute, :asc]
  end
  
  order = attributes.concat(options.to_a).tap do |order|
    order.flatten! if order.size == 1
  end
  
  old_order = @order
  
  new_order = if option_defined?(:order)
    old_order = [old_order] unless old_order.first.is_a?(Array)
    order.first.is_a?(Array) ? old_order.concat(order) : old_order << order
  else
    order
  end
  
  self.dup.tap { |r| r.set_option(:order, new_order) }
end

#set_option(option, value) ⇒ Object



137
138
139
# File 'lib/armada/relation.rb', line 137

def set_option(option, value)
  instance_variable_set("@#{option}", value)
end

#to_query(method = nil, *args, &block) ⇒ Object



126
127
128
# File 'lib/armada/relation.rb', line 126

def to_query(method = nil, *args, &block)
  method ? send("generate_#{method}_query", *args, &block) : find_options
end

#where(conditions) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/armada/relation.rb', line 34

def where(conditions)
  where = []
  conditions.each_pair do |attribute, value|
    if value.is_a?(Hash)
       value.each_pair do |operator, val|
         where << [operator, attribute, build_condition_value(val)]
       end
    else
      where << build_condition(attribute, value)  
    end
  end
  where = where.size > 1 ? where.unshift("and") : where.first
  
  join, old_where = [@join, @where]
  
  new_where = if option_defined?(:where)
    if join == old_where.first && old_where.first == where.first
      old_where.concat(where.from(1))
    elsif join == old_where.first && !is_conjunction?(where.first)
      old_where << where
    elsif join == where.first && is_conjunction?(old_where.first)
      old_where.tap { |w| w[-1] = ([join] << w.last).concat(where.from(1)) }
    elsif join == where.first && !is_conjunction?(old_where.first)
      where.insert(1,old_where)
    elsif join == "and" && old_where.first == "or" && !is_conjunction?(where.first) && !is_conjunction?(old_where.last.first)
      old_where.tap { |w| w[-1] = [join] << w.last << where }
    elsif join == "and" && old_where.first == "or" && !is_conjunction?(where.first) && is_conjunction?(old_where.last.first)
      old_where.tap { |w| w[-1] << where }
    else
      [join] << old_where << where
    end
  else
    where
  end
  self.dup.tap do |r|
    r.set_option(:where, new_where)
    r.set_option(:join, "and")
  end
end