Class: SmartTuple
- Inherits:
-
Object
- Object
- SmartTuple
- Defined in:
- lib/smart_tuple.rb
Overview
SQL condition builder.
tup = SmartTuple.new(" AND ")
tup << {:brand => "Nokia"}
tup << ["min_price >= ?", 75]
tup.compile # => ["brand = ? AND min_price >= ?", "Nokia", 75]
Instance Attribute Summary (collapse)
-
- (Object) args
readonly
Array of SQL argument parts.
-
- (Object) brackets
Put brackets around statements.
-
- (Object) glue
String to glue statements together.
-
- (Object) statements
readonly
Array of SQL statement parts.
Instance Method Summary (collapse)
-
- (Object) +(arg)
Add a statement, return new object.
-
- (Object) <<(arg)
Add a statement, return self.
-
- (Object) add_each(collection, &block)
Iterate over collection and add block's result to self once per each record.
-
- (Object) clear
Clear self.
-
- (Object) compile
(also: #to_a)
Compile self into an array.
-
- (Boolean) empty?
Return true if self is empty.
-
- (SmartTuple) initialize(glue, attrs = {})
constructor
Initializer.
-
- (Object) initialize_copy(src)
Service initializer for dup.
-
- (Object) size
Get number of sub-statements.
Constructor Details
- (SmartTuple) initialize(glue, attrs = {})
Initializer.
new(" AND ")
new(" OR ", :brackets => true)
26 27 28 29 30 |
# File 'lib/smart_tuple.rb', line 26 def initialize(glue, attrs = {}) @glue = glue clear attrs.each {|k, v| send("#{k}=", v)} end |
Instance Attribute Details
- (Object) args (readonly)
Array of SQL argument parts.
9 10 11 |
# File 'lib/smart_tuple.rb', line 9 def args @args end |
- (Object) brackets
Put brackets around statements. true, false or :auto. Default:
:auto
14 15 16 |
# File 'lib/smart_tuple.rb', line 14 def brackets @brackets end |
- (Object) glue
String to glue statements together.
17 18 19 |
# File 'lib/smart_tuple.rb', line 17 def glue @glue end |
- (Object) statements (readonly)
Array of SQL statement parts.
20 21 22 |
# File 'lib/smart_tuple.rb', line 20 def statements @statements end |
Instance Method Details
- (Object) +(arg)
Add a statement, return new object. See #<<.
SmartTuple.new(" AND ") + {:brand => "Nokia"} + ["max_price <= ?", 300]
41 42 43 44 |
# File 'lib/smart_tuple.rb', line 41 def +(arg) # Since #<< supports chaining, it boils down to this. dup << arg end |
- (Object) <<(arg)
Add a statement, return self.
# Array.
tup << ["brand = ?", "Nokia"]
tup << ["brand = ? AND color = ?", "Nokia", "Black"]
# Hash.
tup << {:brand => "Nokia"}
tup << {:brand => "Nokia", :color => "Black"}
# Another SmartTuple.
tup << other_tuple
# String. Generally NOT recommended.
tup << "min_price >= 75"
Adding anything empty or blank (where appropriate) has no effect on the receiver:
tup << nil
tup << []
tup << {}
tup << another_empty_tuple
tup << ""
tup << " " # Will be treated as blank if ActiveSupport is on.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 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/smart_tuple.rb', line 70 def <<(arg) # NOTE: Autobracketing is placing `[value]` instead of `value` into `@statements`. #compile understands it. # Chop off everything empty first time. if arg.nil? or (arg.empty? rescue false) or (arg.blank? rescue false) elsif arg.is_a? String or (arg.acts_like? :string rescue false) @statements << arg.to_s elsif arg.is_a? Array # NOTE: If arg == [], the execution won't get here. # So, we've got at least one element. Therefore stmt will be scalar, and args -- DEFINITELY an array. stmt, args = arg[0], arg[1..-1] if not (stmt.nil? or (stmt.empty? rescue false) or (stmt.blank? rescue false)) # Help do autobracketing later. Here we can ONLY judge by number of passed arguments. @statements << (args.size > 1 ? [stmt] : stmt) @args += args end elsif arg.is_a? Hash arg.each do |k, v| if v.nil? # NOTE: AR supports it for Hashes only. ["kk = ?", nil] will not be converted. @statements << "#{k} IS NULL" else @statements << "#{k} = ?" @args << v end end elsif arg.is_a? self.class # NOTE: If arg is empty, the execution won't get here. # Autobrackets here are smarter, than in Array processing case. stmt = arg.compile[0] @statements << ((arg.size > 1 or arg.args.size > 1) ? [stmt] : stmt) @args += arg.args else raise ArgumentError, "Invalid statement #{arg.inspect}" end # Return self, it's IMPORTANT to make chaining possible. self end |
- (Object) add_each(collection, &block)
Iterate over collection and add block's result to self once per each record.
add_each(brands) do |v|
["brand = ?", v]
end
Can be conditional:
tup.add_each(["Nokia", "Motorola"]) do |v|
["brand = ?", v] if v =~ /^Moto/
end
122 123 124 125 126 127 128 129 130 131 |
# File 'lib/smart_tuple.rb', line 122 def add_each(collection, &block) raise ArgumentError, "Code block expected" if not block collection.each do |v| self << yield(v) end # This is IMPORTANT. self end |
- (Object) clear
Clear self.
144 145 146 147 148 149 150 151 |
# File 'lib/smart_tuple.rb', line 144 def clear @statements = [] @args = [] @brackets = :auto # `Array` does it like this. We do either. self end |
- (Object) compile Also known as: to_a
Compile self into an array. Empty self yields empty array.
compile # => []
compile # => ["brand = ? AND min_price >= ?", "Nokia", 75]
157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/smart_tuple.rb', line 157 def compile return [] if empty? # Build "bracketed" statements. bsta = @statements.map do |s| auto_brackets, scalar_s = s.is_a?(Array) ? [true, s[0]] : [false, s] # Logic: # brackets | auto | result # ----------|-------|------- # true | * | true # false | * | false # :auto | true | true # :auto | false | false brackets = if @statements.size < 2 # If there are no neighboring statements, there WILL BE NO brackets in any case. false elsif @brackets == true or @brackets == false @brackets elsif @brackets == :auto auto_brackets else raise "Unknown @brackets value #{@brackets.inspect}, SE" end if brackets ["(", scalar_s, ")"].join else scalar_s end end [bsta.join(glue)] + @args end |
- (Boolean) empty?
Return true if self is empty.
tup = SmartTuple.new(" AND ")
tup.empty? # => true
198 199 200 |
# File 'lib/smart_tuple.rb', line 198 def empty? @statements.empty? end |
- (Object) initialize_copy(src)
Service initializer for dup.
33 34 35 36 |
# File 'lib/smart_tuple.rb', line 33 def initialize_copy(src) #:nodoc: @statements = src.statements.dup @args = src.args.dup end |
- (Object) size
Get number of sub-statements.
203 204 205 |
# File 'lib/smart_tuple.rb', line 203 def size @statements.size end |