Class: SqlMunger::FieldSet
- Inherits:
-
Object
- Object
- SqlMunger::FieldSet
- Includes:
- Enumerable, Quoter
- Defined in:
- lib/sql_munger/field_set.rb
Overview
This is a class encapsulating a set of fields and providing various methods for producing SQL strings from them.
You can also call operators on fieldset (+ - | & ), or with an array as the right-hand parameter.
Fields can be either plain strings, or objects responding to name, sql_type, null, default. If they’re plain strings, they’re converted to FieldSet::Field objects, which have a name attribute. Mixing different classes in the same FieldSet won’t work.
Defined Under Namespace
Classes: Field
Instance Attribute Summary collapse
-
#fields ⇒ Object
the field objects, which may be objects or Strings.
-
#qualifier ⇒ Object
whatever is in front of the fields, usually a table name It’s stored as an array of parts, to be quoted and joined with ‘.’ when generating SQL.
Attributes included from Quoter
Class Method Summary collapse
-
.[](fieldset_or_array) ⇒ Object
Create from either a Array of field names (NOTE not field objects) or from another FieldSet.
-
.check_strings(ary, msg = nil) ⇒ Object
raise an exception with msg appended if any element of ary is not a String.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#comparison(arg, operator = '=') ⇒ Object
return an SQL set of comparison expressions, joined with ‘and’ suitable for a where clause.
-
#definitions(options = {:joiner => ', '}) ⇒ Object
probably only works with column definitions from ActiveRecord.
-
#each(&block) ⇒ Object
enumerate through field_names.
- #empty? ⇒ Boolean
-
#express(arg, level = 0, options = { :operator => '=', :joiner => ',' }) ⇒ Object
return a string of the fields with some operator and value can be used for where clauses and update statements.
-
#field_names ⇒ Object
the names of the fields.
-
#find_field(name) ⇒ Object
return the field object for name, or nil if it doesn’t exist.
-
#hash_values(hash_values, &block) ⇒ Object
return a hash of field names to their corresponding transformed values from hash_values.
-
#initialize(collection_or_enum, options = {}, &block) ⇒ FieldSet
constructor
collection_or_enum is a collection of field names.
-
#list(qualifier = nil) ⇒ Object
return the set of field names, separated by ‘, ’.
-
#method_missing(meth, *args, &block) ⇒ Object
passes - + & | to operate, otherwise calls method_missing.
-
#operate(operation, other) ⇒ Object
+ - & | (append, difference, intersection union) same as array.
-
#qualified_list ⇒ Object
(also: #qlist)
prepend the qualifier to each field name.
-
#qualify(*args) ⇒ Object
one arg is a field, qualified by qualifier many args is qualifier, field.
-
#quoted_values(hash_values) ⇒ Object
return a comma-separated list of the quoted values for this fieldset.
-
#reconstruct(&block) ⇒ Object
Return a new instance of FieldSet.
- #size ⇒ Object
-
#update(arg) ⇒ Object
return something suitable for an update statement.
-
#values(hash_values, &block) ⇒ Object
extract the values for these fields from hash_values block will be applied to each value.
Methods included from Quoter
#identifier_quoter, included, #value_quoter
Constructor Details
#initialize(collection_or_enum, options = {}, &block) ⇒ FieldSet
collection_or_enum is a collection of field names.
If block is supplied, collection_or_enum is a collection of objects that when map( &block ) is applied returns a collection of field names.
options is intended to easily pass a :qualifier and a :quoter.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/sql_munger/field_set.rb', line 41 def initialize( collection_or_enum, = {}, &block ) @fields = if collection_or_enum.all?{|x| x.is_a?( String ) || x.is_a?( Symbol ) } collection_or_enum.to_a.map{|x| Field.new(x.to_s)} else first = collection_or_enum.first first.name rescue raise( "Can't use default method :name on #{first}" ) collection_or_enum.to_a.dup end @field_name_block = block || lambda {|x| x.name} # set options .each do |key,value| send( "#{key}=", value ) end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(meth, *args, &block) ⇒ Object
passes - + & | to operate, otherwise calls method_missing
159 160 161 162 163 164 165 166 |
# File 'lib/sql_munger/field_set.rb', line 159 def method_missing( meth, *args, &block ) @operations ||= %w{ - + & | }.map{|x| x.to_sym} if @operations.include?( meth ) operate( meth, args.first ) else super end end |
Instance Attribute Details
#fields ⇒ Object
the field objects, which may be objects or Strings. See field_names if you definitely always want either Strings or Symbols
92 93 94 |
# File 'lib/sql_munger/field_set.rb', line 92 def fields @fields end |
#qualifier ⇒ Object
whatever is in front of the fields, usually a table name It’s stored as an array of parts, to be quoted and joined with ‘.’ when generating SQL
171 172 173 |
# File 'lib/sql_munger/field_set.rb', line 171 def qualifier @qualifier end |
Class Method Details
.[](fieldset_or_array) ⇒ Object
Create from either a Array of field names (NOTE not field objects) or from another FieldSet
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/sql_munger/field_set.rb', line 72 def self.[]( fieldset_or_array ) case fieldset_or_array when Array check_strings( fieldset_or_array, "Use #{self.class.name}.new" ) FieldSet.new( fieldset_or_array ) when FieldSet field_set = fieldset_or_array field_set.dup when NilClass nil else raise "dunno what to do with #{fieldset_or_array.inspect}" end end |
.check_strings(ary, msg = nil) ⇒ Object
raise an exception with msg appended if any element of ary is not a String. Otherwise return true
61 62 63 64 65 66 67 68 |
# File 'lib/sql_munger/field_set.rb', line 61 def self.check_strings( ary, msg = nil ) ary.each do |elt| unless elt.is_a?( String ) || elt.is_a?( Symbol ) raise [ "#{elt.inspect} is neither String nor Symbol", msg ].compact.join(' ') end end true end |
Instance Method Details
#==(other) ⇒ Object
340 341 342 343 344 345 |
# File 'lib/sql_munger/field_set.rb', line 340 def ==( other ) return false unless other.is_a?( self.class ) qualifier == other.qualifier and fields == other.fields and @field_name_block == other.instance_variable_get( '@field_name_block' ) end |
#comparison(arg, operator = '=') ⇒ Object
return an SQL set of comparison expressions, joined with ‘and’ suitable for a where clause
304 305 306 307 308 309 310 311 |
# File 'lib/sql_munger/field_set.rb', line 304 def comparison( arg, operator = '=' ) if arg.is_a?( String ) && qualifier.nil? raise "no local qualifier" end st = express( arg, 0, :operator => operator, :joiner => ' and ' ) "( #{st} )" end |
#definitions(options = {:joiner => ', '}) ⇒ Object
probably only works with column definitions from ActiveRecord
325 326 327 328 329 330 |
# File 'lib/sql_munger/field_set.rb', line 325 def definitions( = {:joiner => ', '} ) fields.map do |field| raise "sql_type has no value" if field.sql_type.nil? || field.sql_type == '' "#{field.name} #{field.sql_type}" end.join( [:joiner] ) end |
#each(&block) ⇒ Object
enumerate through field_names
115 116 117 |
# File 'lib/sql_munger/field_set.rb', line 115 def each( &block ) field_names.each( &block ) end |
#empty? ⇒ Boolean
336 337 338 |
# File 'lib/sql_munger/field_set.rb', line 336 def empty? fields.empty? end |
#express(arg, level = 0, options = { :operator => '=', :joiner => ',' }) ⇒ Object
return a string of the fields with some operator and value can be used for where clauses and update statements. arg is either a String, which is treated passed to TableName.new or a TableName, which qualifies the rhs or an Array (actually something with a zip method) which is used as a set of values or a Hash (or something with to_hash) from which the values corresponding to the fields in this object are extracted, and used to compare with
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
# File 'lib/sql_munger/field_set.rb', line 261 def express( arg, level = 0, = { :operator => '=', :joiner => ',' } ) expressions = case when arg.is_a?( String ) express( TableName.new( arg ), level+1, ) when arg.is_a?( TableName ) other_table = arg field_names.map do |field| "#{qualify( field )} #{[:operator]} #{qualify( other_table, field )}" end when arg.is_a?( Hash ) field_names.map do |field| "#{qualify( field )} #{[:operator]} #{value_quoter.quote( arg[field] )}" end when arg.respond_to?( :to_hash ) express( arg.to_hash, level+1, ) when arg.respond_to?( :zip ) raise "#{arg.inspect} doesn't match number of fields in #{field_names}" unless size == arg.size field_names.zip( [ *arg ] ).map do |field,value| "#{qualify( field )} #{[:operator]} #{value_quoter.quote( value )}" end else raise "Don't know what to do with #{arg.inspect}" end if level == 0 if [:joiner].nil? expressions else expressions.join( [:joiner] ) end else expressions end end |
#field_names ⇒ Object
the names of the fields
110 111 112 |
# File 'lib/sql_munger/field_set.rb', line 110 def field_names @field_names ||= sanity_check_fields end |
#find_field(name) ⇒ Object
return the field object for name, or nil if it doesn’t exist
121 122 123 |
# File 'lib/sql_munger/field_set.rb', line 121 def find_field( name ) fields.find{|x| name == @field_name_block.call(x) } end |
#hash_values(hash_values, &block) ⇒ Object
return a hash of field names to their corresponding transformed values from hash_values. block will be used to transform each value.
222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/sql_munger/field_set.rb', line 222 def hash_values( hash_values, &block ) inject({}) do |hash,field| hash[field] = if block.nil? hash_values[field] else block.call( hash_values[field] ) end hash end end |
#list(qualifier = nil) ⇒ Object
return the set of field names, separated by ‘, ’
194 195 196 197 198 |
# File 'lib/sql_munger/field_set.rb', line 194 def list( qualifier = nil ) field_names.map do |field| qualify( qualifier, field ) end.join(', ') end |
#operate(operation, other) ⇒ Object
+ - & | (append, difference, intersection union) same as array. other can be another FieldSet, or an Array Called from method_missing
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/sql_munger/field_set.rb', line 128 def operate( operation, other ) case other when FieldSet # fetch new fields using the operated set of field_names new_field_objects = field_names.send( operation, other.field_names ).map do |name| # first try self's fields, then try other's fields find_field( name ) || other.find_field( name ) end # create the new FieldSet FieldSet.new( new_field_objects, :quoter => quoter, :qualifier => qualifier ) when Array case other.first when String operate( operation, FieldSet.new( other ) ) when Symbol operate( operation, FieldSet.new( other ) ) else # assume it's a field object FieldSet.new( fields.send( operation, other ), :quoter => quoter, :qualifier => qualifier ) end else raise "don't know what to do with #{other.inspect}" end end |
#qualified_list ⇒ Object Also known as: qlist
prepend the qualifier to each field name
201 202 203 |
# File 'lib/sql_munger/field_set.rb', line 201 def qualified_list list( qualifier ) end |
#qualify(*args) ⇒ Object
one arg is a field, qualified by qualifier many args is qualifier, field
209 210 211 212 213 214 215 216 217 218 |
# File 'lib/sql_munger/field_set.rb', line 209 def qualify( *args ) case args.flatten.size when 1 [ qualifier, args.first ] else args end.flatten.compact.map{|x| identifier_quoter.quote_ident(x)}.join('.') end |
#quoted_values(hash_values) ⇒ Object
return a comma-separated list of the quoted values for this fieldset
236 237 238 239 240 |
# File 'lib/sql_munger/field_set.rb', line 236 def quoted_values( hash_values ) map do |field| value_quoter.quote( hash_values[field] ) end end |
#reconstruct(&block) ⇒ Object
Return a new instance of FieldSet. The result of fields is passed to block, and the result of that is passed to FieldSet.new. Useful for doing set operations that aren’t covered by + - & |
105 106 107 |
# File 'lib/sql_munger/field_set.rb', line 105 def reconstruct( &block ) FieldSet.new( block.call( fields ) ) end |
#size ⇒ Object
332 333 334 |
# File 'lib/sql_munger/field_set.rb', line 332 def size fields.size end |
#update(arg) ⇒ Object
return something suitable for an update statement
314 315 316 317 318 319 320 321 322 |
# File 'lib/sql_munger/field_set.rb', line 314 def update( arg ) save_qualifier = qualifier begin self.qualifier = nil express( arg, 0, :operator => '=', :joiner => ', ' ) ensure self.qualifier = save_qualifier end end |
#values(hash_values, &block) ⇒ Object
extract the values for these fields from hash_values block will be applied to each value
244 245 246 247 248 249 250 251 252 |
# File 'lib/sql_munger/field_set.rb', line 244 def values( hash_values, &block ) map do |field| if block.nil? hash_values[field] else block.call( hash_values[field] ) end end end |