Class: Epoxy
- Inherits:
-
Object
- Object
- Epoxy
- Defined in:
- lib/epoxy.rb
Overview
Epoxy - bind data to queries for any query language.
Let me hit ya with some science!
# numbered binds
ep = Epoxy.new("select * from foo where bar=?")
binds = %W[foo]
bound_query = ep.quote { |x| "'" + binds[x] + "'" }
"select * from foo where bar='foo'"
# named binds
binds = { :name => 'Lee', :age => 132 }
ep = Epoxy.new("select * from people where name=?name and age=?age")
bound_query = ep.quote(binds) { |x| "'#{binds[x]}'" }
"select * from people where name='Lee' and age='132'"
# mix them!
binds = { 0 => "Age", :name => 'Lee' }
ep = Epoxy.new("select * from people where name=?name and age=?")
bound_query = ep.quote(binds) { |x| "'#{binds[x]}'" }
"select * from people where name='Lee' and age='Age'"
Epoxy handles:
-
?<name> for named binds
-
? for numbered binds
-
?? for a real question mark
-
‘?’ for a real question mark
-
comments, weird quoting styles (look at the “holy shit” test for examples)
-
not telling you how to quote your data. This solution works for any query language and any database.
Instance Attribute Summary collapse
-
#comment_chars ⇒ Object
readonly
leader comment characters - defaults to SQL “–”.
-
#query ⇒ Object
readonly
the original query, before quoting.
-
#tokens ⇒ Object
readonly
tokens generated by Epoxy.parse_tokens.
Class Method Summary collapse
-
.parse_tokens(query, comment_chars) ⇒ Object
Token parser, isolates components of the query into parts to where they can be managed indepdently.
Instance Method Summary collapse
-
#initialize(query, comment_chars = %r{--|//}) ⇒ Epoxy
constructor
Takes a query as a string and an optional regexp defining beginning-of-line comments.
-
#quote(binds = {}, &block) ⇒ Object
Processes your query for quoting.
Constructor Details
#initialize(query, comment_chars = %r{--|//}) ⇒ Epoxy
Takes a query as a string and an optional regexp defining beginning-of-line comments. The binding rules are as follows:
-
?<name> for named binds
-
? for numbered binds
-
?? for a real question mark
-
‘?’ for a real question mark
-
comments, weird quoting styles are unaffected.
76 77 78 79 80 |
# File 'lib/epoxy.rb', line 76 def initialize(query, comment_chars=%r{--|//}) @comment_chars = comment_chars @query = query @tokens = self.class.parse_tokens(query, @comment_chars) end |
Instance Attribute Details
#comment_chars ⇒ Object (readonly)
leader comment characters - defaults to SQL “–”
64 65 66 |
# File 'lib/epoxy.rb', line 64 def comment_chars @comment_chars end |
#query ⇒ Object (readonly)
the original query, before quoting.
62 63 64 |
# File 'lib/epoxy.rb', line 62 def query @query end |
#tokens ⇒ Object (readonly)
tokens generated by Epoxy.parse_tokens. Just use Epoxy#quote for now.
60 61 62 |
# File 'lib/epoxy.rb', line 60 def tokens @tokens end |
Class Method Details
.parse_tokens(query, comment_chars) ⇒ Object
Token parser, isolates components of the query into parts to where they can be managed indepdently.
Probably not the easiest thing to deal with by itself. Use the standard methods plox.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/epoxy.rb', line 39 def self.parse_tokens(query, comment_chars) a = query.scan(%r{ ( #{comment_chars}.* (?# matches "--" style comments to the end of line or string ) | ' ( [^'\\] | '' | \\. )* ' (?# match strings surrounded by apostophes ) | " ( [^"\\] | "" | \\. )* " (?# match strings surrounded by " ) | ['"] (?# match a loose quote ) | \?[a-zA-Z]+ (?# match a named bind ) | \?\?? (?# match one or two question marks ) | [^-/'"?:]+ (?# match all characters except ' " ? - : and / ) ) }x).collect(&:first) end |
Instance Method Details
#quote(binds = {}, &block) ⇒ Object
Processes your query for quoting. Provide a block that emulates how your data should be quoted. This method accepts a Hash to process named bindings, which when provided will yield each successive Hash key which has a match in the named binds. Keys are coerced to symbols before being yielded.
Without a Hash it will yield on each successive bound element with the index of that element passed.
You are responsible for quoting your data properly. Epoxy just makes it easier to get the places you need to quote out of the query.
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/epoxy.rb', line 94 def quote(binds = {}, &block) result = "" bind_pos = 0 unless binds.empty? tokens.each do |token| binds.each do |key, rep| if token == "?#{key}" token.replace block.call(key.to_sym) end end end end tokens.each do |part| case part when '?' result << block.call(bind_pos) bind_pos += 1 when '??' result << "?" else result << part end end return result end |