-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Issei Naruta
committed
Apr 29, 2012
1 parent
c1c9139
commit 3bf7624
Showing
12 changed files
with
274 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
*.swp | ||
*.gem |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
GEM | ||
remote: http://rubygems.org/ | ||
specs: | ||
diff-lcs (1.1.3) | ||
rspec (2.9.0) | ||
rspec-core (~> 2.9.0) | ||
rspec-expectations (~> 2.9.0) | ||
rspec-mocks (~> 2.9.0) | ||
rspec-core (2.9.0) | ||
rspec-expectations (2.9.1) | ||
diff-lcs (~> 1.1.3) | ||
rspec-mocks (2.9.0) | ||
|
||
PLATFORMS | ||
ruby | ||
|
||
DEPENDENCIES | ||
rspec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
## Welcome to Arproxy | ||
Arproxy is a proxy between ActiveRecord and Database adapters. You can make a custom proxy what analyze and/or modify the SQLs before DB adapter executes them. | ||
This comment has been minimized.
Sorry, something went wrong. |
||
|
||
## Getting Started | ||
Write your proxy like this: | ||
|
||
```ruby | ||
class QueryTracer < Arproxy::Base | ||
def execute(sql, name=nil) | ||
Rails.logger.debug sql | ||
Rails.logger.debug caller(1).join("\n") | ||
super(sql, name) | ||
end | ||
end | ||
``` | ||
|
||
This comment has been minimized.
Sorry, something went wrong. |
||
And write Arproxy configuration in Rails' config/initializers: | ||
|
||
```ruby | ||
Arproxy.configure do |config| | ||
config.adapter = "mysql2" # A DB Apdapter name which is used in your database.yml | ||
config.use QueryTracer | ||
end | ||
Arproxy.enable! | ||
``` | ||
|
||
So you can see the backtrace of SQLs in the Rails' log. | ||
This comment has been minimized.
Sorry, something went wrong. |
||
|
||
```ruby | ||
# In your Rails code | ||
MyTable.where(:id => id).limit(1) # => The SQL and the backtrace appear in the log | ||
``` | ||
|
||
## Architecture | ||
Without Arproxy: | ||
|
||
``` | ||
+-------------------------+ +------------------+ | ||
| ActiveRecord::Base#find |--execute(sql, name)-->| Database Adapter | | ||
+-------------------------+ +------------------+ | ||
``` | ||
|
||
With Arproxy: | ||
|
||
```ruby | ||
Arproxy.configure do |config| | ||
config.adapter = "mysql2" | ||
config.use MyProxy1 | ||
config.use MyProxy2 | ||
end | ||
``` | ||
|
||
``` | ||
+-------------------------+ +----------+ +----------+ +------------------+ | ||
| ActiveRecord::Base#find |--execute(sql, name)-->| MyProxy1 |-->| MyProxy2 |-->| Database Adapter | | ||
+-------------------------+ +----------+ +----------+ +------------------+ | ||
``` | ||
|
||
## Examples | ||
### Slow Query Logger | ||
```ruby | ||
class SlowQueryLogger < Arproxy::Base | ||
def initialize(slow_ms) | ||
@slow_ms = slow_ms | ||
end | ||
|
||
def execute(sql, name=nil) | ||
result = nil | ||
ms = Benchmark.ms { result = super(sql, name) } | ||
if ms >= @slow_ms | ||
Rails.logger.info "Slow(#{ms.to_i}ms): #{sql}" | ||
end | ||
result | ||
end | ||
end | ||
|
||
Arproxy.configure do |config| | ||
config.use SlowQueryLogger, 1000 | ||
end | ||
``` | ||
|
||
### Adding Comments to SQLs | ||
```ruby | ||
class CommentAdder < Arproxy::Base | ||
def execute(sql, name=nil) | ||
sql += " /*this_is_comment*/" | ||
super(sql, name) | ||
end | ||
end | ||
``` | ||
|
||
## Appendix | ||
### What the `name' argument is | ||
In the Rails' log you may see queries like this: | ||
``` | ||
User Load (22.6ms) SELECT `users`.* FROM `users` WHERE `users`.`name` = 'Issei Naruta' | ||
``` | ||
Then `"User Load"` is the `name`. | ||
|
||
## License | ||
Arproxy is released under the MIT license: | ||
* www.opensource.org/licenses/MIT | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
Gem::Specification.new do |spec| | ||
spec.name = 'arproxy' | ||
spec.version = '0.1.0' | ||
spec.summary = 'Proxy between ActiveRecord and DB adapter' | ||
spec.description = 'Arproxy is a proxy between ActiveRecord and database adapter' | ||
spec.files = Dir.glob("lib/**/*.rb") | ||
spec.author = 'Issei Naruta' | ||
spec.email = 'naruta@cookpad.com' | ||
spec.homepage = 'https://github.com/cookpad/arproxy' | ||
spec.has_rdoc = false | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
module Arproxy | ||
class Base | ||
attr_accessor :proxy_chain, :next_proxy | ||
|
||
def execute(sql, name=nil) | ||
next_proxy.execute sql, name | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,11 @@ | ||
module Arproxy | ||
class ChainTail | ||
def execute(connection, sql, name=nil) | ||
connection.execute_without_arproxy(sql, name) | ||
class ChainTail < Base | ||
def initialize(proxy_chain) | ||
self.proxy_chain = proxy_chain | ||
end | ||
|
||
def execute(sql, name=nil) | ||
self.proxy_chain.connection.execute_without_arproxy sql, name | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
module Arproxy | ||
autoload :ChainTail, "arproxy/chain_tail" | ||
|
||
class ProxyChain | ||
attr_reader :head, :tail | ||
attr_accessor :connection | ||
|
||
def initialize(config) | ||
@config = config | ||
setup_proxy_chain(@config) | ||
end | ||
|
||
def setup_proxy_chain(config) | ||
@tail = ChainTail.new self | ||
@head = config.proxies.reverse.inject(@tail) do |next_proxy, proxy_config| | ||
cls, options = proxy_config | ||
proxy = cls.new *options | ||
proxy.proxy_chain = self | ||
proxy.next_proxy = next_proxy | ||
proxy | ||
end | ||
end | ||
private :setup_proxy_chain | ||
|
||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
require "spec_helper" | ||
|
||
describe Arproxy do | ||
class ProxyA < Arproxy::Base | ||
def execute(sql, name) | ||
super "#{sql}_A", "#{name}_A" | ||
end | ||
end | ||
|
||
class ProxyB < Arproxy::Base | ||
def initialize(opt=nil) | ||
@opt = opt | ||
end | ||
|
||
def execute(sql, name) | ||
super "#{sql}_B#{@opt}", "#{name}_B#{@opt}" | ||
end | ||
end | ||
|
||
module ::ActiveRecord | ||
module ConnectionAdapters | ||
class DummyAdapter | ||
def execute(sql, name = nil) | ||
{:sql => sql, :name => name} | ||
end | ||
end | ||
end | ||
end | ||
|
||
let(:connection) { ::ActiveRecord::ConnectionAdapters::DummyAdapter.new } | ||
subject { connection.execute "SQL", "NAME" } | ||
after(:each) do | ||
Arproxy.disable! | ||
end | ||
|
||
context "with 2 proxies" do | ||
before do | ||
Arproxy.configure do |config| | ||
config.adapter = "dummy" | ||
config.use ProxyA | ||
config.use ProxyB | ||
end | ||
Arproxy.enable! | ||
end | ||
|
||
it { should == {:sql => "SQL_A_B", :name => "NAME_A_B"} } | ||
end | ||
|
||
context "with 2 proxies which have an option" do | ||
before do | ||
Arproxy.configure do |config| | ||
config.adapter = "dummy" | ||
config.use ProxyA | ||
config.use ProxyB, 1 | ||
end | ||
Arproxy.enable! | ||
end | ||
|
||
it { should == {:sql => "SQL_A_B1", :name => "NAME_A_B1"} } | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
require File.expand_path("../../lib/arproxy", __FILE__) | ||
|
<p>
になるので問題はない)