switch_point 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +10 -0
- data/Appraisals +5 -0
- data/CHANGELOG.md +7 -0
- data/README.md +19 -3
- data/Rakefile +5 -0
- data/assets/switch_point.svg +1 -1
- data/benchmark/proxy.rb +61 -0
- data/gemfiles/rails_4.2.gemfile +7 -0
- data/gemfiles/rails_edge.gemfile +1 -0
- data/lib/switch_point.rb +11 -1
- data/lib/switch_point/config.rb +2 -2
- data/lib/switch_point/model.rb +18 -0
- data/lib/switch_point/proxy.rb +12 -0
- data/lib/switch_point/query_cache.rb +20 -0
- data/lib/switch_point/version.rb +1 -1
- data/spec/switch_point/model_spec.rb +30 -1
- data/spec/switch_point/query_cache_spec.rb +66 -0
- data/spec/switch_point_spec.rb +23 -0
- data/switch_point.gemspec +2 -0
- metadata +36 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f01102cca54c7b028bddcf7663ae5ec5de4fd28
|
4
|
+
data.tar.gz: 0b2d26c5a70f7dbe7341f6b7a81ebed58219bf2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e293b56dd3daa2873beb81602d02ee2959597c5a8d73a7e986ad4d274074e9bff0955919ccd417235e30ed5a688c33b08c1a0df1b1c09fe0ce292d4de594da20
|
7
|
+
data.tar.gz: a4bab4cf2b8c799310880756afae5a55505aaaccd9a2a56c512afde07786954326fa44c35243614b68d96d0a42fdcbe86cca5a068e3657400044b215806d78c6
|
data/.travis.yml
CHANGED
@@ -8,8 +8,18 @@ gemfile:
|
|
8
8
|
- gemfiles/rails_3.2.gemfile
|
9
9
|
- gemfiles/rails_4.0.gemfile
|
10
10
|
- gemfiles/rails_4.1.gemfile
|
11
|
+
- gemfiles/rails_4.2.gemfile
|
11
12
|
- gemfiles/rails_edge.gemfile
|
13
|
+
sudo: false
|
14
|
+
after_script:
|
15
|
+
- bundle exec rake benchmark
|
12
16
|
matrix:
|
13
17
|
allow_failures:
|
14
18
|
- rvm: ruby-head
|
15
19
|
- gemfile: gemfiles/rails_edge.gemfile
|
20
|
+
exclude:
|
21
|
+
# Rails 5 requires to run on Ruby 2.2.0 or newer.
|
22
|
+
- rvm: 2.0.0
|
23
|
+
gemfile: gemfiles/rails_edge.gemfile
|
24
|
+
- rvm: 2.1
|
25
|
+
gemfile: gemfiles/rails_edge.gemfile
|
data/Appraisals
CHANGED
@@ -10,8 +10,13 @@ appraise 'rails-4.1' do
|
|
10
10
|
gem 'activerecord', '~> 4.1'
|
11
11
|
end
|
12
12
|
|
13
|
+
appraise 'rails-4.2' do
|
14
|
+
gem 'activerecord', '~> 4.2'
|
15
|
+
end
|
16
|
+
|
13
17
|
appraise 'rails-edge' do
|
14
18
|
gem 'activerecord', git: 'https://github.com/rails/rails'
|
19
|
+
gem 'arel', git: 'https://github.com/rails/arel'
|
15
20
|
end
|
16
21
|
|
17
22
|
# vim: set ft=ruby:
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## 0.6.0 (2015-04-14)
|
2
|
+
- Add `SwitchPoint::QueryCache` middleware
|
3
|
+
- `Model.cache` and `Model.uncached` is now hooked by switch_point
|
4
|
+
- `Model.cache` enables query cache for both readonly and writable.
|
5
|
+
- `Model.uncached` disables query cache for both readonly and writable.
|
6
|
+
- Add `SwitchPoint.with_readonly_all` and `SwitchPoint.with_writable_all` as shorthand
|
7
|
+
|
1
8
|
## 0.5.0 (2014-11-05)
|
2
9
|
- Rename `SwitchPoint.with_connection` to `SwitchPoint.with_mode`
|
3
10
|
- To avoid confusion with `ActiveRecord::ConnectionPool#with_connection`
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# SwitchPoint
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/switch_point.svg)](http://badge.fury.io/rb/switch_point)
|
3
3
|
[![Build Status](https://travis-ci.org/eagletmt/switch_point.svg?branch=master)](https://travis-ci.org/eagletmt/switch_point)
|
4
|
-
[![Coverage Status](https://
|
5
|
-
[![Code Climate](https://codeclimate.com/github/eagletmt/switch_point.
|
4
|
+
[![Coverage Status](https://img.shields.io/coveralls/eagletmt/switch_point.svg?branch=master)](https://coveralls.io/r/eagletmt/switch_point?branch=master)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/eagletmt/switch_point/badges/gpa.svg)](https://codeclimate.com/github/eagletmt/switch_point)
|
6
6
|
|
7
7
|
Switching database connection between readonly one and writable one.
|
8
8
|
|
@@ -89,6 +89,22 @@ end
|
|
89
89
|
|
90
90
|
Note that Article and Category shares their connections.
|
91
91
|
|
92
|
+
### Query cache
|
93
|
+
`Model.cache` and `Model.uncached` enables/disables query cache for both
|
94
|
+
readonly connection and writable connection.
|
95
|
+
|
96
|
+
switch_point also provide a rack middleware `SwitchPoint::QueryCache` similar
|
97
|
+
to `ActiveRecord::QueryCache`. It enables query cache for all models using
|
98
|
+
switch_point.
|
99
|
+
|
100
|
+
```ruby
|
101
|
+
# Replace ActiveRecord::QueryCache with SwitchPoint::QueryCache
|
102
|
+
config.middleware.swap ActiveRecord::QueryCache, SwitchPoint::QueryCache
|
103
|
+
|
104
|
+
# Enable query cache for :nanika1 only.
|
105
|
+
config.middleware.swap ActiveRecord::QueryCache, SwitchPoint::QueryCache, [:nanika1]
|
106
|
+
```
|
107
|
+
|
92
108
|
## Notes
|
93
109
|
|
94
110
|
### auto_writable
|
@@ -121,7 +137,7 @@ Each ActiveRecord model refers to a proxy.
|
|
121
137
|
|
122
138
|
When the writable connection is requested to execute destructive query, the readonly connection clears its query cache.
|
123
139
|
|
124
|
-
![switch_point](
|
140
|
+
![switch_point](https://gyazo.wanko.cc/switch_point.svg)
|
125
141
|
|
126
142
|
### Special case: ActiveRecord::Base.connection
|
127
143
|
Basically, each connection managed by a proxy isn't shared between proxies.
|
data/Rakefile
CHANGED
data/assets/switch_point.svg
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
<?xml version="1.0" encoding="utf-8"?>
|
2
|
-
<svg contentScriptType="text/ecmascript" xmlns:xlink="http://www.w3.org/1999/xlink" zoomAndPan="magnify" contentStyleType="text/css" viewBox="74.0 85.0 534.0 434.1035" xmlns:cacoo="http://cacoo.com/" preserveAspectRatio="xMidYMin meet" xmlns="http://www.w3.org/2000/svg" version="1.1"><defs><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id4" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#e33933"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id5" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#e33933"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id6" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#97d077"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id7" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#97d077"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id15" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#000000"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id16" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#000000"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id17" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#000000"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id26" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#000000"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id27" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#e33933"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id28" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#74c14a"/></marker></defs><g><g transform="translate(529.0 140.8965)"><path fill="#ffffff" fill-opacity="1.0" d="M0.0 6.0 L64.00000000000006 6.0 L64.00000000000006 52.5 Q64.00000000000006 54.98528137423857 54.62741699796954 56.742640687119284 Q45.25483399593911 58.5 32.00000000000002 58.5 Q18.745166004060973 58.5 9.372583002030485 56.742640687119284 Q0.0 54.98528137423857 0.0 52.5 L0.0 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><path fill="#ffffff" fill-opacity="1.0" d="M64.00000000000006 6.0 Q64.00000000000006 8.485281374238571 54.62741699796954 10.242640687119284 Q45.25483399593911 11.999999999999998 32.00000000000003 12.0 Q18.745166004060973 12.0 9.372583002030488 10.242640687119286 Q0.0 8.485281374238571 0.0 6.000000000000001 Q0.0 3.5147186257614313 9.372583002030485 1.7573593128807152 Q18.745166004060973 8.881784197001252E-16 32.00000000000002 0.0 Q45.25483399593911 -8.881784197001252E-16 54.62741699796954 1.7573593128807143 Q64.00000000000006 3.5147186257614287 64.00000000000006 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(0.0 12.0)"><clipPath id="id0"><path d="M0 0 L64.0 0 L64.0 46.5 L0 46.5z"/></clipPath><text font-size="12" clip-path="url(#id0)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="18.0" xml:space="preserve" y="19.25" textLength="28.0">main</tspan><tspan x="11.0" xml:space="preserve" y="36.25" textLength="41.0">master</tspan></text></g></g><g transform="translate(529.0 376.8965)"><path fill="#ffffff" fill-opacity="1.0" d="M0.0 6.0 L63.99999999999992 6.0 L63.99999999999992 52.5 Q63.99999999999992 54.98528137423857 54.62741699796942 56.742640687119284 Q45.25483399593904 58.5 31.999999999999932 58.5 Q18.745166004060934 58.5 9.372583002030463 56.742640687119284 Q0.0 54.98528137423857 0.0 52.5 L0.0 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><path fill="#ffffff" fill-opacity="1.0" d="M63.99999999999992 6.0 Q63.99999999999992 8.485281374238571 54.62741699796942 10.242640687119284 Q45.25483399593904 11.999999999999998 31.99999999999996 12.0 Q18.74516600406094 12.0 9.37258300203047 10.242640687119286 Q0.0 8.485281374238571 0.0 6.000000000000001 Q0.0 3.5147186257614313 9.372583002030463 1.7573593128807152 Q18.745166004060934 8.881784197001252E-16 31.999999999999932 0.0 Q45.25483399593904 -8.881784197001252E-16 54.62741699796942 1.7573593128807143 Q63.99999999999992 3.5147186257614287 63.99999999999992 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(0.0 12.0)"><clipPath id="id1"><path d="M0 0 L64.0 0 L64.0 46.5 L0 46.5z"/></clipPath><text font-size="12" clip-path="url(#id1)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="9.0" xml:space="preserve" y="19.25" textLength="46.0">commet</tspan><tspan x="11.0" xml:space="preserve" y="36.25" textLength="41.0">master</tspan></text></g></g><g transform="translate(293.5289580126552 170.1465)"><path fill="#ffffff" fill-opacity="1.0" d="M51.74956447969533 68.4248898947933 L0.424969148024419 34.35350099488455 L51.74956447969533 0.28211209497580036 L103.07415981136624 34.35350099488455 L51.74956447969533 68.4248898947933 L51.74956447969533 68.4248898947933z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(20.199307221852635 21.163783014064215)"><clipPath id="id2"><path d="M0 0 L62.58726465655704 0 L62.58726465655704 26.463928188151897 L0 26.463928188151897z"/></clipPath><text font-size="12" clip-path="url(#id2)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="17.0" xml:space="preserve" y="17.73196409407595" textLength="28.0">main</tspan></text></g></g><g transform="translate(293.5289580126552 406.1465)"><path fill="#ffffff" fill-opacity="1.0" d="M51.381583974689526 68.70699999999998 L7.148564543362447E-16 34.35349999999998 L51.381583974689526 -5.911707234851347E-15 L102.76316794937905 34.35349999999998 L51.381583974689526 68.70699999999998 L51.381583974689526 68.70699999999998z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(19.79629465597243 21.054571154298447)"><clipPath id="id3"><path d="M0 0 L62.65675888753867 0 L62.65675888753867 26.683049513549793 L0 26.683049513549793z"/></clipPath><text font-size="12" clip-path="url(#id3)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="5.0" xml:space="preserve" y="17.841524756774895" textLength="53.0">comment</tspan></text></g></g><path fill="none" marker-end="url(#id4)" d="M370.94082015818594 187.46430654493017 L529.0 170.1465" stroke-width="2.0" stroke-linejoin="round" stroke="#e33933"/><path fill="none" marker-end="url(#id5)" d="M370.6013339746895 423.32325 L529.0 406.1465" stroke-width="2.0" stroke-linejoin="round" stroke="#e33933"/><path fill="none" marker-end="url(#id6)" d="M370.6013339746895 457.67674999999997 L529.0 474.8535" stroke-width="2.0" stroke-linejoin="round" stroke="#97d077"/><path fill="none" marker-end="url(#id7)" d="M370.94082015818594 221.53569544483895 L529.0 233.75752170027454" stroke-width="2.0" stroke-linejoin="round" stroke="#97d077"/><g transform="translate(389.0 160.1465)"><clipPath id="id8"><path d="M0 0 L58.0 0 L58.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id8)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="50.0">writable</tspan></text></g><g transform="translate(389.0 225.3535)"><clipPath id="id9"><path d="M0 0 L58.0 0 L58.0 27.0 L0 27.0z"/></clipPath><text font-size="12" clip-path="url(#id9)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="51.0">readonly</tspan></text></g><g transform="translate(389.0 396.1465)"><clipPath id="id10"><path d="M0 0 L58.0 0 L58.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id10)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="50.0">writable</tspan></text></g><g transform="translate(389.0 461.3535)"><clipPath id="id11"><path d="M0 0 L58.0 0 L58.0 27.0 L0 27.0z"/></clipPath><text font-size="12" clip-path="url(#id11)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="51.0">readonly</tspan></text></g><g transform="translate(116.5 213.8535)"><path fill="#ffffff" fill-opacity="1.0" d="M115.00000000000001 25.0 Q115.00000000000001 35.354843 98.15939999999996 42.67725 Q81.31799499999998 50.0 57.50000000000001 50.0 Q33.68292499999999 50.0 16.841465489999997 42.677624 Q0.0 35.35525 0.0 25.0 Q0.0 14.64475 16.841463189999995 7.3223763 Q33.68292499999999 0.0 57.50000000000001 0.0 Q81.31840209999994 0.0 98.15939999999996 7.3223753 Q115.00000000000001 14.644578 115.00000000000001 25.0 L115.00000000000001 25.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(15.920599842071528 7.961000442504883)"><clipPath id="id12"><path d="M0 0 L83.16799964904784 0 L83.16799964904784 33.847999572753906 L0 33.847999572753906z"/></clipPath><text font-size="12" clip-path="url(#id12)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="14.0" xml:space="preserve" y="21.423999786376953" textLength="54.0">Publisher</tspan></text></g></g><g transform="translate(116.5 145.1465)"><path fill="#ffffff" fill-opacity="1.0" d="M115.00000000000001 25.0 Q115.00000000000001 35.354843 98.15939999999996 42.67725 Q81.31799499999998 50.0 57.50000000000001 50.0 Q33.68292499999999 50.0 16.841465489999997 42.677624 Q0.0 35.35525 0.0 25.0 Q0.0 14.64475 16.841463189999995 7.3223763 Q33.68292499999999 0.0 57.50000000000001 0.0 Q81.31840209999994 0.0 98.15939999999996 7.3223753 Q115.00000000000001 14.644578 115.00000000000001 25.0 L115.00000000000001 25.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(15.920599842071528 7.961000442504883)"><clipPath id="id13"><path d="M0 0 L83.16799964904784 0 L83.16799964904784 33.847999572753906 L0 33.847999572753906z"/></clipPath><text font-size="12" clip-path="url(#id13)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="27.0" xml:space="preserve" y="21.423999786376953" textLength="28.0">Book</tspan></text></g></g><g transform="translate(116.5 415.5)"><path fill="#ffffff" fill-opacity="1.0" d="M115.00000000000001 25.0 Q115.00000000000001 35.354843 98.15939999999996 42.67725 Q81.31799499999998 50.0 57.50000000000001 50.0 Q33.68292499999999 50.0 16.841465489999997 42.677624 Q0.0 35.35525 0.0 25.0 Q0.0 14.64475 16.841463189999995 7.3223763 Q33.68292499999999 0.0 57.50000000000001 0.0 Q81.31840209999994 0.0 98.15939999999996 7.3223753 Q115.00000000000001 14.644578 115.00000000000001 25.0 L115.00000000000001 25.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(14.920599842071528 7.961000442504883)"><clipPath id="id14"><path d="M0 0 L83.16799964904784 0 L83.16799964904784 33.847999572753906 L0 33.847999572753906z"/></clipPath><text font-size="12" clip-path="url(#id14)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="14.0" xml:space="preserve" y="21.423999786376953" textLength="55.0">Comment</tspan></text></g></g><path fill="none" stroke-linejoin="round" stroke-dasharray="6.0 2.0" d="M231.5 170.1465 L319.61622482651507 187.46430654493017" stroke="#000000" stroke-width="2.0" marker-end="url(#id15)"/><path fill="none" stroke-linejoin="round" stroke-dasharray="6.0 2.0" d="M231.5 238.8535 L319.61622482651507 221.53569544483895" stroke="#000000" stroke-width="2.0" marker-end="url(#id16)"/><path fill="none" stroke-linejoin="round" stroke-dasharray="6.0 2.0" d="M231.5 440.5 L293.5289580126552 440.5" stroke="#000000" stroke-width="2.0" marker-end="url(#id17)"/><g transform="translate(89.0 100.0)"><clipPath id="id18"><path d="M0 0 L176.0 0 L176.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id18)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="bold"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="169.0">Model < ActiveRecord::Base</tspan></text></g><g transform="translate(322.91054198734474 100.0)"><clipPath id="id19"><path d="M0 0 L44.0 0 L44.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id19)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="bold"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="35.0">Proxy</tspan></text></g><g transform="translate(116.5 299.1465)"><path fill="#ffffff" fill-opacity="1.0" d="M115.00000000000001 25.0 Q115.00000000000001 35.354843 98.15940000000002 42.67725 Q81.31799500000004 50.0 57.50000000000001 50.0 Q33.68292500000001 50.0 16.84146549 42.677624 Q0.0 35.35525 0.0 25.0 Q0.0 14.64475 16.84146319000001 7.3223763 Q33.68292500000001 0.0 57.50000000000001 0.0 Q81.31840210000003 0.0 98.15940000000002 7.3223753 Q115.00000000000001 14.644578 115.00000000000001 25.0 L115.00000000000001 25.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(14.92059984207154 7.961000442504883)"><clipPath id="id20"><path d="M0 0 L83.16799964904786 0 L83.16799964904786 33.847999572753906 L0 33.847999572753906z"/></clipPath><text font-size="12" clip-path="url(#id20)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="18.0" xml:space="preserve" y="21.423999786376953" textLength="46.0">BigData</tspan></text></g></g><g transform="translate(293.95090530472953 290.0751120949758)"><path fill="#ffffff" fill-opacity="1.0" d="M50.95963817063662 68.14277779981754 L-1.5432100042289676E-14 34.071388899908776 L50.95963817063662 1.3489209749195652E-14 L101.91927634127326 34.071388899908776 L50.95963817063662 68.14277779981754 L50.95963817063662 68.14277779981754z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(19.633727393157077 20.881670919088414)"><clipPath id="id21"><path d="M0 0 L62.14222129521437 0 L62.14222129521437 26.463928188151918 L0 26.463928188151918z"/></clipPath><text font-size="12" clip-path="url(#id21)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="10.0" xml:space="preserve" y="17.73196409407596" textLength="41.0">special</tspan></text></g></g><g transform="translate(529.0 294.89650099488455)"><path fill="#ffffff" fill-opacity="1.0" d="M0.0 6.0 L63.99999999999999 6.0 L63.99999999999999 52.5 Q63.99999999999999 54.98528137423857 54.6274169979695 56.742640687119284 Q45.254833995939045 58.5 31.999999999999975 58.5 Q18.74516600406095 58.5 9.37258300203047 56.742640687119284 Q0.0 54.98528137423857 0.0 52.5 L0.0 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><path fill="#ffffff" fill-opacity="1.0" d="M63.99999999999999 6.0 Q63.99999999999999 8.485281374238571 54.6274169979695 10.242640687119284 Q45.254833995939045 11.999999999999998 31.999999999999996 12.0 Q18.745166004060952 12.0 9.37258300203048 10.242640687119286 Q0.0 8.485281374238571 0.0 6.000000000000001 Q0.0 3.5147186257614313 9.37258300203047 1.7573593128807152 Q18.74516600406095 8.881784197001252E-16 31.999999999999975 0.0 Q45.254833995939045 -8.881784197001252E-16 54.6274169979695 1.7573593128807143 Q63.99999999999999 3.5147186257614287 63.99999999999999 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(0.0 12.0)"><clipPath id="id22"><path d="M0 0 L64.0 0 L64.0 46.5 L0 46.5z"/></clipPath><text font-size="12" clip-path="url(#id22)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="18.0" xml:space="preserve" y="10.75" textLength="28.0">main</tspan><tspan x="11.0" xml:space="preserve" y="27.75" textLength="41.0">special</tspan><tspan x="16.0" xml:space="preserve" y="44.75" textLength="31.0">slave</tspan></text></g></g><g transform="translate(529.0 209.6035)"><path fill="#ffffff" fill-opacity="1.0" d="M0.0 6.0 L64.00000000000006 6.0 L64.00000000000006 52.5 Q64.00000000000006 54.98528137423857 54.62741699796954 56.742640687119284 Q45.25483399593911 58.5 32.00000000000002 58.5 Q18.745166004060973 58.5 9.372583002030485 56.742640687119284 Q0.0 54.98528137423857 0.0 52.5 L0.0 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><path fill="#ffffff" fill-opacity="1.0" d="M64.00000000000006 6.0 Q64.00000000000006 8.485281374238571 54.62741699796954 10.242640687119284 Q45.25483399593911 11.999999999999998 32.00000000000003 12.0 Q18.745166004060973 12.0 9.372583002030488 10.242640687119286 Q0.0 8.485281374238571 0.0 6.000000000000001 Q0.0 3.5147186257614313 9.372583002030485 1.7573593128807152 Q18.745166004060973 8.881784197001252E-16 32.00000000000002 0.0 Q45.25483399593911 -8.881784197001252E-16 54.62741699796954 1.7573593128807143 Q64.00000000000006 3.5147186257614287 64.00000000000006 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(0.0 12.0)"><clipPath id="id23"><path d="M0 0 L64.0 0 L64.0 46.5 L0 46.5z"/></clipPath><text font-size="12" clip-path="url(#id23)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="18.0" xml:space="preserve" y="19.25" textLength="28.0">main</tspan><tspan x="16.0" xml:space="preserve" y="36.25" textLength="31.0">slave</tspan></text></g></g><g transform="translate(529.0 445.6035)"><path fill="#ffffff" fill-opacity="1.0" d="M0.0 6.0 L64.00000000000006 6.0 L64.00000000000006 52.5 Q64.00000000000006 54.98528137423857 54.62741699796954 56.742640687119284 Q45.25483399593911 58.5 32.00000000000002 58.5 Q18.745166004060973 58.5 9.372583002030485 56.742640687119284 Q0.0 54.98528137423857 0.0 52.5 L0.0 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><path fill="#ffffff" fill-opacity="1.0" d="M64.00000000000006 6.0 Q64.00000000000006 8.485281374238571 54.62741699796954 10.242640687119284 Q45.25483399593911 11.999999999999998 32.00000000000003 12.0 Q18.745166004060973 12.0 9.372583002030488 10.242640687119286 Q0.0 8.485281374238571 0.0 6.000000000000001 Q0.0 3.5147186257614313 9.372583002030485 1.7573593128807152 Q18.745166004060973 8.881784197001252E-16 32.00000000000002 0.0 Q45.25483399593911 -8.881784197001252E-16 54.62741699796954 1.7573593128807143 Q64.00000000000006 3.5147186257614287 64.00000000000006 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(0.0 12.0)"><clipPath id="id24"><path d="M0 0 L64.0 0 L64.0 46.5 L0 46.5z"/></clipPath><text font-size="12" clip-path="url(#id24)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="5.0" xml:space="preserve" y="19.25" textLength="53.0">comment</tspan><tspan x="16.0" xml:space="preserve" y="36.25" textLength="31.0">slave</tspan></text></g></g><g transform="translate(529.0 100.0)"><clipPath id="id25"><path d="M0 0 L64.0 0 L64.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id25)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="bold"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="55.0">Database</tspan></text></g><path fill="none" stroke-linejoin="round" stroke-dasharray="6.0 2.0" d="M231.5 324.1465 L293.95090530472953 324.14650099488455" stroke="#000000" stroke-width="2.0" marker-end="url(#id26)"/><path fill="none" marker-end="url(#id27)" d="M370.3903625606845 307.1108065449302 L529.0 184.77149999999997" stroke-width="2.0" stroke-linejoin="round" stroke="#e33933"/><path fill="none" marker-end="url(#id28)" d="M370.3903625606845 341.18219544483895 L529.0 324.14650099488455" stroke-width="2.0" stroke-linejoin="round" stroke="#74c14a"/><g transform="translate(389.0 344.7178898947933)"><clipPath id="id29"><path d="M0 0 L58.0 0 L58.0 27.0 L0 27.0z"/></clipPath><text font-size="12" clip-path="url(#id29)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="51.0">readonly</tspan></text></g><g transform="translate(395.87018164600283 280.0751120949758)"><clipPath id="id30"><path d="M0 0 L58.0 0 L58.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id30)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="50.0">writable</tspan></text></g></g></svg>
|
2
|
+
<svg contentScriptType="text/ecmascript" xmlns:xlink="http://www.w3.org/1999/xlink" zoomAndPan="magnify" contentStyleType="text/css" viewBox="74.0 85.0 534.0 434.1035" xmlns:cacoo="http://cacoo.com/" preserveAspectRatio="xMidYMin meet" xmlns="http://www.w3.org/2000/svg" version="1.1"><defs><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id4" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#e33933"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id5" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#e33933"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id6" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#97d077"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id7" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#97d077"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id15" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#000000"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id16" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#000000"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id17" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#000000"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id26" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#000000"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id27" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#e33933"/></marker><marker refX="14.0" refY="7.0" markerUnits="userSpaceOnUse" orient="auto" id="id28" markerHeight="14.0" viewBox="0 0 14.0 14.0" preserveAspectRatio="xMidYMid meet" markerWidth="14.0" overflow="visible"><path fill="none" d="M0 0 L14.0 7.0 L0 14.0" stroke-width="2.0" stroke-linejoin="round" stroke-linecap="round" stroke="#74c14a"/></marker></defs><g><g transform="translate(529.0 140.8965)"><path fill="#ffffff" fill-opacity="1.0" d="M0.0 6.0 L64.00000000000006 6.0 L64.00000000000006 52.5 Q64.00000000000006 54.98528137423857 54.62741699796954 56.742640687119284 Q45.25483399593911 58.5 32.00000000000002 58.5 Q18.745166004060973 58.5 9.372583002030485 56.742640687119284 Q0.0 54.98528137423857 0.0 52.5 L0.0 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><path fill="#ffffff" fill-opacity="1.0" d="M64.00000000000006 6.0 Q64.00000000000006 8.485281374238571 54.62741699796954 10.242640687119284 Q45.25483399593911 11.999999999999998 32.00000000000003 12.0 Q18.745166004060973 12.0 9.372583002030488 10.242640687119286 Q0.0 8.485281374238571 0.0 6.000000000000001 Q0.0 3.5147186257614313 9.372583002030485 1.7573593128807152 Q18.745166004060973 8.881784197001252E-16 32.00000000000002 0.0 Q45.25483399593911 -8.881784197001252E-16 54.62741699796954 1.7573593128807143 Q64.00000000000006 3.5147186257614287 64.00000000000006 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(0.0 12.0)"><clipPath id="id0"><path d="M0 0 L64.0 0 L64.0 46.5 L0 46.5z"/></clipPath><text font-size="12" clip-path="url(#id0)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="18.0" xml:space="preserve" y="19.25" textLength="28.0">main</tspan><tspan x="11.0" xml:space="preserve" y="36.25" textLength="41.0">master</tspan></text></g></g><g transform="translate(529.0 376.8965)"><path fill="#ffffff" fill-opacity="1.0" d="M0.0 6.0 L63.99999999999992 6.0 L63.99999999999992 52.5 Q63.99999999999992 54.98528137423857 54.62741699796942 56.742640687119284 Q45.25483399593904 58.5 31.999999999999932 58.5 Q18.745166004060934 58.5 9.372583002030463 56.742640687119284 Q0.0 54.98528137423857 0.0 52.5 L0.0 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><path fill="#ffffff" fill-opacity="1.0" d="M63.99999999999992 6.0 Q63.99999999999992 8.485281374238571 54.62741699796942 10.242640687119284 Q45.25483399593904 11.999999999999998 31.99999999999996 12.0 Q18.74516600406094 12.0 9.37258300203047 10.242640687119286 Q0.0 8.485281374238571 0.0 6.000000000000001 Q0.0 3.5147186257614313 9.372583002030463 1.7573593128807152 Q18.745166004060934 8.881784197001252E-16 31.999999999999932 0.0 Q45.25483399593904 -8.881784197001252E-16 54.62741699796942 1.7573593128807143 Q63.99999999999992 3.5147186257614287 63.99999999999992 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(0.0 12.0)"><clipPath id="id1"><path d="M0 0 L64.0 0 L64.0 46.5 L0 46.5z"/></clipPath><text font-size="12" clip-path="url(#id1)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="5.0" xml:space="preserve" y="19.25" textLength="46.0">comment</tspan><tspan x="11.0" xml:space="preserve" y="36.25" textLength="41.0">master</tspan></text></g></g><g transform="translate(293.5289580126552 170.1465)"><path fill="#ffffff" fill-opacity="1.0" d="M51.74956447969533 68.4248898947933 L0.424969148024419 34.35350099488455 L51.74956447969533 0.28211209497580036 L103.07415981136624 34.35350099488455 L51.74956447969533 68.4248898947933 L51.74956447969533 68.4248898947933z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(20.199307221852635 21.163783014064215)"><clipPath id="id2"><path d="M0 0 L62.58726465655704 0 L62.58726465655704 26.463928188151897 L0 26.463928188151897z"/></clipPath><text font-size="12" clip-path="url(#id2)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="17.0" xml:space="preserve" y="17.73196409407595" textLength="28.0">main</tspan></text></g></g><g transform="translate(293.5289580126552 406.1465)"><path fill="#ffffff" fill-opacity="1.0" d="M51.381583974689526 68.70699999999998 L7.148564543362447E-16 34.35349999999998 L51.381583974689526 -5.911707234851347E-15 L102.76316794937905 34.35349999999998 L51.381583974689526 68.70699999999998 L51.381583974689526 68.70699999999998z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(19.79629465597243 21.054571154298447)"><clipPath id="id3"><path d="M0 0 L62.65675888753867 0 L62.65675888753867 26.683049513549793 L0 26.683049513549793z"/></clipPath><text font-size="12" clip-path="url(#id3)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="5.0" xml:space="preserve" y="17.841524756774895" textLength="53.0">comment</tspan></text></g></g><path fill="none" marker-end="url(#id4)" d="M370.94082015818594 187.46430654493017 L529.0 170.1465" stroke-width="2.0" stroke-linejoin="round" stroke="#e33933"/><path fill="none" marker-end="url(#id5)" d="M370.6013339746895 423.32325 L529.0 406.1465" stroke-width="2.0" stroke-linejoin="round" stroke="#e33933"/><path fill="none" marker-end="url(#id6)" d="M370.6013339746895 457.67674999999997 L529.0 474.8535" stroke-width="2.0" stroke-linejoin="round" stroke="#97d077"/><path fill="none" marker-end="url(#id7)" d="M370.94082015818594 221.53569544483895 L529.0 233.75752170027454" stroke-width="2.0" stroke-linejoin="round" stroke="#97d077"/><g transform="translate(389.0 160.1465)"><clipPath id="id8"><path d="M0 0 L58.0 0 L58.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id8)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="50.0">writable</tspan></text></g><g transform="translate(389.0 225.3535)"><clipPath id="id9"><path d="M0 0 L58.0 0 L58.0 27.0 L0 27.0z"/></clipPath><text font-size="12" clip-path="url(#id9)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="51.0">readonly</tspan></text></g><g transform="translate(389.0 396.1465)"><clipPath id="id10"><path d="M0 0 L58.0 0 L58.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id10)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="50.0">writable</tspan></text></g><g transform="translate(389.0 461.3535)"><clipPath id="id11"><path d="M0 0 L58.0 0 L58.0 27.0 L0 27.0z"/></clipPath><text font-size="12" clip-path="url(#id11)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="51.0">readonly</tspan></text></g><g transform="translate(116.5 213.8535)"><path fill="#ffffff" fill-opacity="1.0" d="M115.00000000000001 25.0 Q115.00000000000001 35.354843 98.15939999999996 42.67725 Q81.31799499999998 50.0 57.50000000000001 50.0 Q33.68292499999999 50.0 16.841465489999997 42.677624 Q0.0 35.35525 0.0 25.0 Q0.0 14.64475 16.841463189999995 7.3223763 Q33.68292499999999 0.0 57.50000000000001 0.0 Q81.31840209999994 0.0 98.15939999999996 7.3223753 Q115.00000000000001 14.644578 115.00000000000001 25.0 L115.00000000000001 25.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(15.920599842071528 7.961000442504883)"><clipPath id="id12"><path d="M0 0 L83.16799964904784 0 L83.16799964904784 33.847999572753906 L0 33.847999572753906z"/></clipPath><text font-size="12" clip-path="url(#id12)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="14.0" xml:space="preserve" y="21.423999786376953" textLength="54.0">Publisher</tspan></text></g></g><g transform="translate(116.5 145.1465)"><path fill="#ffffff" fill-opacity="1.0" d="M115.00000000000001 25.0 Q115.00000000000001 35.354843 98.15939999999996 42.67725 Q81.31799499999998 50.0 57.50000000000001 50.0 Q33.68292499999999 50.0 16.841465489999997 42.677624 Q0.0 35.35525 0.0 25.0 Q0.0 14.64475 16.841463189999995 7.3223763 Q33.68292499999999 0.0 57.50000000000001 0.0 Q81.31840209999994 0.0 98.15939999999996 7.3223753 Q115.00000000000001 14.644578 115.00000000000001 25.0 L115.00000000000001 25.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(15.920599842071528 7.961000442504883)"><clipPath id="id13"><path d="M0 0 L83.16799964904784 0 L83.16799964904784 33.847999572753906 L0 33.847999572753906z"/></clipPath><text font-size="12" clip-path="url(#id13)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="27.0" xml:space="preserve" y="21.423999786376953" textLength="28.0">Book</tspan></text></g></g><g transform="translate(116.5 415.5)"><path fill="#ffffff" fill-opacity="1.0" d="M115.00000000000001 25.0 Q115.00000000000001 35.354843 98.15939999999996 42.67725 Q81.31799499999998 50.0 57.50000000000001 50.0 Q33.68292499999999 50.0 16.841465489999997 42.677624 Q0.0 35.35525 0.0 25.0 Q0.0 14.64475 16.841463189999995 7.3223763 Q33.68292499999999 0.0 57.50000000000001 0.0 Q81.31840209999994 0.0 98.15939999999996 7.3223753 Q115.00000000000001 14.644578 115.00000000000001 25.0 L115.00000000000001 25.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(14.920599842071528 7.961000442504883)"><clipPath id="id14"><path d="M0 0 L83.16799964904784 0 L83.16799964904784 33.847999572753906 L0 33.847999572753906z"/></clipPath><text font-size="12" clip-path="url(#id14)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="14.0" xml:space="preserve" y="21.423999786376953" textLength="55.0">Comment</tspan></text></g></g><path fill="none" stroke-linejoin="round" stroke-dasharray="6.0 2.0" d="M231.5 170.1465 L319.61622482651507 187.46430654493017" stroke="#000000" stroke-width="2.0" marker-end="url(#id15)"/><path fill="none" stroke-linejoin="round" stroke-dasharray="6.0 2.0" d="M231.5 238.8535 L319.61622482651507 221.53569544483895" stroke="#000000" stroke-width="2.0" marker-end="url(#id16)"/><path fill="none" stroke-linejoin="round" stroke-dasharray="6.0 2.0" d="M231.5 440.5 L293.5289580126552 440.5" stroke="#000000" stroke-width="2.0" marker-end="url(#id17)"/><g transform="translate(89.0 100.0)"><clipPath id="id18"><path d="M0 0 L176.0 0 L176.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id18)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="bold"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="169.0">Model < ActiveRecord::Base</tspan></text></g><g transform="translate(322.91054198734474 100.0)"><clipPath id="id19"><path d="M0 0 L44.0 0 L44.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id19)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="bold"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="35.0">Proxy</tspan></text></g><g transform="translate(116.5 299.1465)"><path fill="#ffffff" fill-opacity="1.0" d="M115.00000000000001 25.0 Q115.00000000000001 35.354843 98.15940000000002 42.67725 Q81.31799500000004 50.0 57.50000000000001 50.0 Q33.68292500000001 50.0 16.84146549 42.677624 Q0.0 35.35525 0.0 25.0 Q0.0 14.64475 16.84146319000001 7.3223763 Q33.68292500000001 0.0 57.50000000000001 0.0 Q81.31840210000003 0.0 98.15940000000002 7.3223753 Q115.00000000000001 14.644578 115.00000000000001 25.0 L115.00000000000001 25.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(14.92059984207154 7.961000442504883)"><clipPath id="id20"><path d="M0 0 L83.16799964904786 0 L83.16799964904786 33.847999572753906 L0 33.847999572753906z"/></clipPath><text font-size="12" clip-path="url(#id20)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="18.0" xml:space="preserve" y="21.423999786376953" textLength="46.0">BigData</tspan></text></g></g><g transform="translate(293.95090530472953 290.0751120949758)"><path fill="#ffffff" fill-opacity="1.0" d="M50.95963817063662 68.14277779981754 L-1.5432100042289676E-14 34.071388899908776 L50.95963817063662 1.3489209749195652E-14 L101.91927634127326 34.071388899908776 L50.95963817063662 68.14277779981754 L50.95963817063662 68.14277779981754z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(19.633727393157077 20.881670919088414)"><clipPath id="id21"><path d="M0 0 L62.14222129521437 0 L62.14222129521437 26.463928188151918 L0 26.463928188151918z"/></clipPath><text font-size="12" clip-path="url(#id21)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="10.0" xml:space="preserve" y="17.73196409407596" textLength="41.0">special</tspan></text></g></g><g transform="translate(529.0 294.89650099488455)"><path fill="#ffffff" fill-opacity="1.0" d="M0.0 6.0 L63.99999999999999 6.0 L63.99999999999999 52.5 Q63.99999999999999 54.98528137423857 54.6274169979695 56.742640687119284 Q45.254833995939045 58.5 31.999999999999975 58.5 Q18.74516600406095 58.5 9.37258300203047 56.742640687119284 Q0.0 54.98528137423857 0.0 52.5 L0.0 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><path fill="#ffffff" fill-opacity="1.0" d="M63.99999999999999 6.0 Q63.99999999999999 8.485281374238571 54.6274169979695 10.242640687119284 Q45.254833995939045 11.999999999999998 31.999999999999996 12.0 Q18.745166004060952 12.0 9.37258300203048 10.242640687119286 Q0.0 8.485281374238571 0.0 6.000000000000001 Q0.0 3.5147186257614313 9.37258300203047 1.7573593128807152 Q18.74516600406095 8.881784197001252E-16 31.999999999999975 0.0 Q45.254833995939045 -8.881784197001252E-16 54.6274169979695 1.7573593128807143 Q63.99999999999999 3.5147186257614287 63.99999999999999 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(0.0 12.0)"><clipPath id="id22"><path d="M0 0 L64.0 0 L64.0 46.5 L0 46.5z"/></clipPath><text font-size="12" clip-path="url(#id22)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="18.0" xml:space="preserve" y="10.75" textLength="28.0">main</tspan><tspan x="11.0" xml:space="preserve" y="27.75" textLength="41.0">special</tspan><tspan x="16.0" xml:space="preserve" y="44.75" textLength="31.0">slave</tspan></text></g></g><g transform="translate(529.0 209.6035)"><path fill="#ffffff" fill-opacity="1.0" d="M0.0 6.0 L64.00000000000006 6.0 L64.00000000000006 52.5 Q64.00000000000006 54.98528137423857 54.62741699796954 56.742640687119284 Q45.25483399593911 58.5 32.00000000000002 58.5 Q18.745166004060973 58.5 9.372583002030485 56.742640687119284 Q0.0 54.98528137423857 0.0 52.5 L0.0 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><path fill="#ffffff" fill-opacity="1.0" d="M64.00000000000006 6.0 Q64.00000000000006 8.485281374238571 54.62741699796954 10.242640687119284 Q45.25483399593911 11.999999999999998 32.00000000000003 12.0 Q18.745166004060973 12.0 9.372583002030488 10.242640687119286 Q0.0 8.485281374238571 0.0 6.000000000000001 Q0.0 3.5147186257614313 9.372583002030485 1.7573593128807152 Q18.745166004060973 8.881784197001252E-16 32.00000000000002 0.0 Q45.25483399593911 -8.881784197001252E-16 54.62741699796954 1.7573593128807143 Q64.00000000000006 3.5147186257614287 64.00000000000006 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(0.0 12.0)"><clipPath id="id23"><path d="M0 0 L64.0 0 L64.0 46.5 L0 46.5z"/></clipPath><text font-size="12" clip-path="url(#id23)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="18.0" xml:space="preserve" y="19.25" textLength="28.0">main</tspan><tspan x="16.0" xml:space="preserve" y="36.25" textLength="31.0">slave</tspan></text></g></g><g transform="translate(529.0 445.6035)"><path fill="#ffffff" fill-opacity="1.0" d="M0.0 6.0 L64.00000000000006 6.0 L64.00000000000006 52.5 Q64.00000000000006 54.98528137423857 54.62741699796954 56.742640687119284 Q45.25483399593911 58.5 32.00000000000002 58.5 Q18.745166004060973 58.5 9.372583002030485 56.742640687119284 Q0.0 54.98528137423857 0.0 52.5 L0.0 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><path fill="#ffffff" fill-opacity="1.0" d="M64.00000000000006 6.0 Q64.00000000000006 8.485281374238571 54.62741699796954 10.242640687119284 Q45.25483399593911 11.999999999999998 32.00000000000003 12.0 Q18.745166004060973 12.0 9.372583002030488 10.242640687119286 Q0.0 8.485281374238571 0.0 6.000000000000001 Q0.0 3.5147186257614313 9.372583002030485 1.7573593128807152 Q18.745166004060973 8.881784197001252E-16 32.00000000000002 0.0 Q45.25483399593911 -8.881784197001252E-16 54.62741699796954 1.7573593128807143 Q64.00000000000006 3.5147186257614287 64.00000000000006 6.0z" stroke-width="1.0" stroke-linejoin="round" stroke="#000000"/><g transform="translate(0.0 12.0)"><clipPath id="id24"><path d="M0 0 L64.0 0 L64.0 46.5 L0 46.5z"/></clipPath><text font-size="12" clip-path="url(#id24)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="5.0" xml:space="preserve" y="19.25" textLength="53.0">comment</tspan><tspan x="16.0" xml:space="preserve" y="36.25" textLength="31.0">slave</tspan></text></g></g><g transform="translate(529.0 100.0)"><clipPath id="id25"><path d="M0 0 L64.0 0 L64.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id25)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="bold"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="55.0">Database</tspan></text></g><path fill="none" stroke-linejoin="round" stroke-dasharray="6.0 2.0" d="M231.5 324.1465 L293.95090530472953 324.14650099488455" stroke="#000000" stroke-width="2.0" marker-end="url(#id26)"/><path fill="none" marker-end="url(#id27)" d="M370.3903625606845 307.1108065449302 L529.0 184.77149999999997" stroke-width="2.0" stroke-linejoin="round" stroke="#e33933"/><path fill="none" marker-end="url(#id28)" d="M370.3903625606845 341.18219544483895 L529.0 324.14650099488455" stroke-width="2.0" stroke-linejoin="round" stroke="#74c14a"/><g transform="translate(389.0 344.7178898947933)"><clipPath id="id29"><path d="M0 0 L58.0 0 L58.0 27.0 L0 27.0z"/></clipPath><text font-size="12" clip-path="url(#id29)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="51.0">readonly</tspan></text></g><g transform="translate(395.87018164600283 280.0751120949758)"><clipPath id="id30"><path d="M0 0 L58.0 0 L58.0 20.0 L0 20.0z"/></clipPath><text font-size="12" clip-path="url(#id30)" text-decoration="none" fill="#000000" font-family="Arial,Arial" font-style="normal" font-weight="normal"><tspan x="2.0" xml:space="preserve" y="15.0" textLength="50.0">writable</tspan></text></g></g></svg>
|
data/benchmark/proxy.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'benchmark/ips'
|
2
|
+
require 'switch_point'
|
3
|
+
require 'active_record'
|
4
|
+
|
5
|
+
SwitchPoint.configure do |config|
|
6
|
+
config.define_switch_point :proxy,
|
7
|
+
readonly: :proxy_readonly,
|
8
|
+
writable: :proxy_writable
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
class Plain < ActiveRecord::Base
|
13
|
+
end
|
14
|
+
|
15
|
+
class Proxy1 < ActiveRecord::Base
|
16
|
+
use_switch_point :proxy
|
17
|
+
end
|
18
|
+
|
19
|
+
class ProxyBase < ActiveRecord::Base
|
20
|
+
self.abstract_class = true
|
21
|
+
use_switch_point :proxy
|
22
|
+
end
|
23
|
+
|
24
|
+
class Proxy2 < ProxyBase
|
25
|
+
end
|
26
|
+
|
27
|
+
database_config = { adapter: 'sqlite3', database: ':memory:' }
|
28
|
+
ActiveRecord::Base.configurations = {
|
29
|
+
'default' => database_config.dup,
|
30
|
+
'proxy_readonly' => database_config.dup,
|
31
|
+
'proxy_writable' => database_config.dup,
|
32
|
+
}
|
33
|
+
ActiveRecord::Base.establish_connection(:default)
|
34
|
+
|
35
|
+
Plain.connection.execute('CREATE TABLE plains (id integer primary key autoincrement)')
|
36
|
+
[:readonly, :writable].each do |mode|
|
37
|
+
ProxyBase.public_send("with_#{mode}") do
|
38
|
+
%w[proxy1s proxy2s].each do |table|
|
39
|
+
ProxyBase.connection.execute("CREATE TABLE #{table} (id integer primary key autoincrement)")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Benchmark.ips do |x|
|
45
|
+
x.report('plain') do
|
46
|
+
Plain.create
|
47
|
+
Plain.first
|
48
|
+
end
|
49
|
+
|
50
|
+
x.report('proxy1') do
|
51
|
+
Proxy1.with_writable { Proxy1.create }
|
52
|
+
Proxy1.first
|
53
|
+
end
|
54
|
+
|
55
|
+
x.report('proxy2') do
|
56
|
+
Proxy2.with_writable { Proxy2.create }
|
57
|
+
Proxy2.first
|
58
|
+
end
|
59
|
+
|
60
|
+
x.compare!
|
61
|
+
end
|
data/gemfiles/rails_edge.gemfile
CHANGED
data/lib/switch_point.rb
CHANGED
@@ -36,10 +36,18 @@ module SwitchPoint
|
|
36
36
|
with_mode(:readonly, *names, &block)
|
37
37
|
end
|
38
38
|
|
39
|
+
def with_readonly_all(&block)
|
40
|
+
with_readonly(*config.keys, &block)
|
41
|
+
end
|
42
|
+
|
39
43
|
def with_writable(*names, &block)
|
40
44
|
with_mode(:writable, *names, &block)
|
41
45
|
end
|
42
46
|
|
47
|
+
def with_writable_all(&block)
|
48
|
+
with_writable(*config.keys, &block)
|
49
|
+
end
|
50
|
+
|
43
51
|
def with_mode(mode, *names, &block)
|
44
52
|
names.reverse.inject(block) do |func, name|
|
45
53
|
lambda do
|
@@ -52,8 +60,10 @@ module SwitchPoint
|
|
52
60
|
end
|
53
61
|
|
54
62
|
ActiveSupport.on_load(:active_record) do
|
55
|
-
require 'switch_point/model'
|
56
63
|
require 'switch_point/connection'
|
64
|
+
require 'switch_point/model'
|
65
|
+
require 'switch_point/query_cache'
|
66
|
+
|
57
67
|
ActiveRecord::Base.send(:include, SwitchPoint::Model)
|
58
68
|
ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
|
59
69
|
include SwitchPoint::Connection
|
data/lib/switch_point/config.rb
CHANGED
@@ -22,11 +22,11 @@ module SwitchPoint
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def database_name(name, mode)
|
25
|
-
|
25
|
+
fetch(name)[mode]
|
26
26
|
end
|
27
27
|
|
28
28
|
def model_name(name, mode)
|
29
|
-
if
|
29
|
+
if fetch(name)[mode]
|
30
30
|
"#{name}_#{mode}".camelize
|
31
31
|
else
|
32
32
|
nil
|
data/lib/switch_point/model.rb
CHANGED
@@ -6,6 +6,8 @@ module SwitchPoint
|
|
6
6
|
model.singleton_class.class_eval do
|
7
7
|
include ClassMethods
|
8
8
|
alias_method_chain :connection, :switch_point
|
9
|
+
alias_method_chain :cache, :switch_point
|
10
|
+
alias_method_chain :uncached, :switch_point
|
9
11
|
end
|
10
12
|
end
|
11
13
|
|
@@ -18,6 +20,22 @@ module SwitchPoint
|
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
23
|
+
def cache_with_switch_point(&block)
|
24
|
+
if switch_point_proxy
|
25
|
+
switch_point_proxy.cache(&block)
|
26
|
+
else
|
27
|
+
cache_without_switch_point(&block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def uncached_with_switch_point(&block)
|
32
|
+
if switch_point_proxy
|
33
|
+
switch_point_proxy.uncached(&block)
|
34
|
+
else
|
35
|
+
uncached_without_switch_point(&block)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
21
39
|
def with_readonly(&block)
|
22
40
|
if switch_point_proxy
|
23
41
|
switch_point_proxy.with_readonly(&block)
|
data/lib/switch_point/proxy.rb
CHANGED
@@ -142,5 +142,17 @@ module SwitchPoint
|
|
142
142
|
def connected?
|
143
143
|
model_for_connection.connected?
|
144
144
|
end
|
145
|
+
|
146
|
+
def cache(&block)
|
147
|
+
r = with_readonly { model_for_connection }
|
148
|
+
w = with_writable { model_for_connection }
|
149
|
+
r.cache { w.cache(&block) }
|
150
|
+
end
|
151
|
+
|
152
|
+
def uncached(&block)
|
153
|
+
r = with_readonly { model_for_connection }
|
154
|
+
w = with_writable { model_for_connection }
|
155
|
+
r.uncached { w.uncached(&block) }
|
156
|
+
end
|
145
157
|
end
|
146
158
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SwitchPoint
|
2
|
+
class QueryCache
|
3
|
+
def initialize(app, names = nil)
|
4
|
+
@app = app
|
5
|
+
@names = names
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
names.reverse.inject(lambda { @app.call(env) }) do |func, name|
|
10
|
+
lambda { ProxyRepository.checkout(name).cache(&func) }
|
11
|
+
end.call
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def names
|
17
|
+
@names ||= SwitchPoint.config.keys
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/switch_point/version.rb
CHANGED
@@ -69,7 +69,6 @@ RSpec.describe SwitchPoint::Model do
|
|
69
69
|
|
70
70
|
it 'works with newly checked-out connection' do
|
71
71
|
Thread.start do
|
72
|
-
expect(Book.connection.pool.connections.size).to be > 1 # Assertion
|
73
72
|
Book.with_writable do
|
74
73
|
Book.create
|
75
74
|
end
|
@@ -398,4 +397,34 @@ RSpec.describe SwitchPoint::Model do
|
|
398
397
|
end
|
399
398
|
end
|
400
399
|
end
|
400
|
+
|
401
|
+
describe '.cache' do
|
402
|
+
it 'enables query cache for both readonly and writable' do
|
403
|
+
Book.connection
|
404
|
+
Book.with_writable { Book.connection }
|
405
|
+
|
406
|
+
Book.cache do
|
407
|
+
expect { Book.count }.to change { Book.connection.query_cache.size }.from(0).to(1)
|
408
|
+
Book.with_writable do
|
409
|
+
expect { Book.count }.to change { Book.connection.query_cache.size }.from(0).to(1)
|
410
|
+
end
|
411
|
+
end
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
415
|
+
describe '.uncached' do
|
416
|
+
it 'disables query cache for both readonly and writable' do
|
417
|
+
Book.connection
|
418
|
+
Book.with_writable { Book.connection }
|
419
|
+
|
420
|
+
Book.cache do
|
421
|
+
Book.uncached do
|
422
|
+
expect { Book.count }.to_not change { Book.connection.query_cache.size }.from(0)
|
423
|
+
Book.with_writable do
|
424
|
+
expect { Book.count }.to_not change { Book.connection.query_cache.size }.from(0)
|
425
|
+
end
|
426
|
+
end
|
427
|
+
end
|
428
|
+
end
|
429
|
+
end
|
401
430
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rack'
|
3
|
+
|
4
|
+
class TestApp
|
5
|
+
def call(env)
|
6
|
+
state = {}
|
7
|
+
[Nanika1, Nanika2].each do |model|
|
8
|
+
r = model.with_readonly { model.connection.query_cache_enabled }
|
9
|
+
w = model.with_writable { model.connection.query_cache_enabled }
|
10
|
+
state[model.name] = { readonly: r, writable: r }
|
11
|
+
end
|
12
|
+
env[:state] = state
|
13
|
+
:result
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
RSpec.describe SwitchPoint::QueryCache do
|
18
|
+
let(:app) do
|
19
|
+
Rack::Builder.new do
|
20
|
+
use SwitchPoint::QueryCache
|
21
|
+
run TestApp.new
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#call' do
|
26
|
+
it 'enables query cache of all models' do
|
27
|
+
env = {}
|
28
|
+
expect(app.call(env)).to eq(:result)
|
29
|
+
expect(env[:state]).to eq(
|
30
|
+
'Nanika1' => { readonly: true, writable: true },
|
31
|
+
'Nanika2' => { readonly: true, writable: true },
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'when names are specified' do
|
36
|
+
let(:app) do
|
37
|
+
Rack::Builder.new do
|
38
|
+
use SwitchPoint::QueryCache, [:main, :nanika1]
|
39
|
+
run TestApp.new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'enables query caches of specified models' do
|
44
|
+
env = {}
|
45
|
+
expect(app.call(env)).to eq(:result)
|
46
|
+
expect(env[:state]).to eq(
|
47
|
+
'Nanika1' => { readonly: true, writable: true },
|
48
|
+
'Nanika2' => { readonly: false, writable: false },
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'when unknown name is specified' do
|
54
|
+
let(:app) do
|
55
|
+
Rack::Builder.new do
|
56
|
+
use SwitchPoint::QueryCache, [:unknown]
|
57
|
+
run TestApp.new
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'raises error' do
|
62
|
+
expect { app.call({}) }.to raise_error(KeyError)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/spec/switch_point_spec.rb
CHANGED
@@ -31,6 +31,12 @@ RSpec.describe SwitchPoint do
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
34
|
+
|
35
|
+
context 'with unknown name' do
|
36
|
+
it 'raises error' do
|
37
|
+
expect { SwitchPoint.writable!(:unknown) }.to raise_error(KeyError)
|
38
|
+
end
|
39
|
+
end
|
34
40
|
end
|
35
41
|
|
36
42
|
describe '.with_writable' do
|
@@ -44,5 +50,22 @@ RSpec.describe SwitchPoint do
|
|
44
50
|
expect(Publisher).to connect_to('main_readonly.sqlite3')
|
45
51
|
expect(Nanika1).to connect_to('main_readonly.sqlite3')
|
46
52
|
end
|
53
|
+
|
54
|
+
context 'with unknown name' do
|
55
|
+
it 'raises error' do
|
56
|
+
expect { SwitchPoint.with_writable(:unknown) { raise RuntimeError } }.to raise_error(KeyError)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe '.with_writable_all' do
|
62
|
+
it 'changes all connections' do
|
63
|
+
expect(Book).to connect_to('main_readonly.sqlite3')
|
64
|
+
expect(Comment).to connect_to('comment_readonly.sqlite3')
|
65
|
+
SwitchPoint.with_writable_all do
|
66
|
+
expect(Book).to connect_to('main_writable.sqlite3')
|
67
|
+
expect(Comment).to connect_to('comment_writable.sqlite3')
|
68
|
+
end
|
69
|
+
end
|
47
70
|
end
|
48
71
|
end
|
data/switch_point.gemspec
CHANGED
@@ -19,8 +19,10 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_development_dependency "appraisal"
|
22
|
+
spec.add_development_dependency "benchmark-ips"
|
22
23
|
spec.add_development_dependency "bundler"
|
23
24
|
spec.add_development_dependency "coveralls"
|
25
|
+
spec.add_development_dependency "rack"
|
24
26
|
spec.add_development_dependency "rake"
|
25
27
|
spec.add_development_dependency "rspec", ">= 3.0"
|
26
28
|
spec.add_development_dependency "sqlite3"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: switch_point
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kohei Suzuki
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-04-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: appraisal
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: benchmark-ips
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: bundler
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +66,20 @@ dependencies:
|
|
52
66
|
- - ">="
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rack
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
55
83
|
- !ruby/object:Gem::Dependency
|
56
84
|
name: rake
|
57
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -125,9 +153,11 @@ files:
|
|
125
153
|
- README.md
|
126
154
|
- Rakefile
|
127
155
|
- assets/switch_point.svg
|
156
|
+
- benchmark/proxy.rb
|
128
157
|
- gemfiles/rails_3.2.gemfile
|
129
158
|
- gemfiles/rails_4.0.gemfile
|
130
159
|
- gemfiles/rails_4.1.gemfile
|
160
|
+
- gemfiles/rails_4.2.gemfile
|
131
161
|
- gemfiles/rails_edge.gemfile
|
132
162
|
- lib/switch_point.rb
|
133
163
|
- lib/switch_point/config.rb
|
@@ -135,10 +165,12 @@ files:
|
|
135
165
|
- lib/switch_point/model.rb
|
136
166
|
- lib/switch_point/proxy.rb
|
137
167
|
- lib/switch_point/proxy_repository.rb
|
168
|
+
- lib/switch_point/query_cache.rb
|
138
169
|
- lib/switch_point/version.rb
|
139
170
|
- spec/models.rb
|
140
171
|
- spec/spec_helper.rb
|
141
172
|
- spec/switch_point/model_spec.rb
|
173
|
+
- spec/switch_point/query_cache_spec.rb
|
142
174
|
- spec/switch_point_spec.rb
|
143
175
|
- switch_point.gemspec
|
144
176
|
homepage: https://github.com/eagletmt/switch_point
|
@@ -161,7 +193,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
161
193
|
version: '0'
|
162
194
|
requirements: []
|
163
195
|
rubyforge_project:
|
164
|
-
rubygems_version: 2.
|
196
|
+
rubygems_version: 2.4.5
|
165
197
|
signing_key:
|
166
198
|
specification_version: 4
|
167
199
|
summary: Switching database connection between readonly one and writable one.
|
@@ -169,4 +201,5 @@ test_files:
|
|
169
201
|
- spec/models.rb
|
170
202
|
- spec/spec_helper.rb
|
171
203
|
- spec/switch_point/model_spec.rb
|
204
|
+
- spec/switch_point/query_cache_spec.rb
|
172
205
|
- spec/switch_point_spec.rb
|