ScopedProxy 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +18 -0
- data/Manifest.txt +7 -0
- data/README.txt +105 -0
- data/Rakefile +25 -0
- data/lib/scoped_proxy.rb +142 -0
- data/spec/scoped_proxy_spec.rb +164 -0
- data/spec/spec_helper.rb +12 -0
- metadata +70 -0
data/History.txt
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
== 1.0.0 / 2007-12-16
|
2
|
+
|
3
|
+
First official release.
|
4
|
+
|
5
|
+
* Added default_proxy method.
|
6
|
+
|
7
|
+
* Added delegation/answer to respond_to?
|
8
|
+
|
9
|
+
== 0.5.2
|
10
|
+
|
11
|
+
Inofficial release on our blog neotrivium.com. Fixing a few bugs due to user reports.
|
12
|
+
|
13
|
+
* v0.4 Fixed a bug with scoping (another one) pointed out to me by Severin Schoepke.
|
14
|
+
Scoping will now even work in situations where an AssociationProxy sets the context.
|
15
|
+
|
16
|
+
* v0.3 Fixed a scoping bug pointed out by fractious; now scoping should work as advertised. Thanks go
|
17
|
+
to Florian Hanke for teaming up with me on this.
|
18
|
+
|
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
ScopedProxy
|
2
|
+
|
3
|
+
== SUMMARY
|
4
|
+
|
5
|
+
Finally, long awaited, scoped proxies as a release. Which you say. Admitted, there are about 15 plugins
|
6
|
+
that are called scoped_proxy, but only one comes with a full suite of tests that is full 40 lines longer
|
7
|
+
than the actual code. That is the scoped proxy you are looking at. It is y2k compliant and works as a gem.
|
8
|
+
Magnificent, isn't it?
|
9
|
+
|
10
|
+
This gem is all about simplicity; you won't find a whole toolbox here, just another valued screwdriver.
|
11
|
+
But we happen to encounter a lot of screws - hopefully you do too - and find this very useful. If you
|
12
|
+
want to skip all this summary that is really longer than all the other texts in this release, have a look
|
13
|
+
at the synopsis below.
|
14
|
+
|
15
|
+
== SYNOPSIS:
|
16
|
+
|
17
|
+
Allows storing scopes as names; that way you can address subsets of your model space by meaningful names.
|
18
|
+
|
19
|
+
require 'scoped_proxy' # Railsers: You might want to call this in environment.rb
|
20
|
+
|
21
|
+
class User < ActiveRecord::Base
|
22
|
+
scoped_proxy :role do |role|
|
23
|
+
{
|
24
|
+
:find => { :conditions => ['role = ?', role] }
|
25
|
+
}
|
26
|
+
end
|
27
|
+
scoped_proxy :deleted, :find => {
|
28
|
+
:conditions => 'deleted_at is not null'
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
admins = User.role('admin')
|
33
|
+
admins.count # => 12
|
34
|
+
admins.find(:all) # => [ ... ]
|
35
|
+
|
36
|
+
User.deleted.count # => a number
|
37
|
+
|
38
|
+
This implementation also brings (NEW, SHINY) default proxies. That means you can have a proxy in effect
|
39
|
+
when no other proxy is in effect.
|
40
|
+
|
41
|
+
class User < ActiveRecord::Base
|
42
|
+
default_proxy :find => { :conditions => 'deleted_at is null' }
|
43
|
+
end
|
44
|
+
|
45
|
+
User.find(:all) # only finds users that aren't deleted
|
46
|
+
|
47
|
+
== REQUIREMENTS:
|
48
|
+
|
49
|
+
* gem install metaid
|
50
|
+
|
51
|
+
== TESTING
|
52
|
+
|
53
|
+
If you want to run the rspec tests, you must have a database on localhost called 'test' and a user
|
54
|
+
called 'developer' that is allowed to (write)access it. Caution: running the tests will delete at least
|
55
|
+
your 'users' table in said database. But I hope you wouldn't run this on production, nor call your
|
56
|
+
production database 'test'. Warned you.
|
57
|
+
|
58
|
+
Details can be changed in spec/spec_helper.rb
|
59
|
+
|
60
|
+
== THANKS
|
61
|
+
|
62
|
+
Special Thanks to Florian Hanke (florian at restorm dot com) and Severin Schoepke (severin at restorm dot com).
|
63
|
+
They have played an enormous role in keeping this mean and lean. Thanks also to the rest of the gang - please
|
64
|
+
visit us at labs.restorm.com.
|
65
|
+
|
66
|
+
== CONTACT
|
67
|
+
|
68
|
+
Rubyforge Project:
|
69
|
+
|
70
|
+
http://rubyforge.org/projects/swissrb
|
71
|
+
|
72
|
+
Documentation:
|
73
|
+
|
74
|
+
upcoming...
|
75
|
+
|
76
|
+
Bugs:
|
77
|
+
|
78
|
+
http://rubyforge.org/tracker/?atid=19774&group_id=5130&func=browse
|
79
|
+
|
80
|
+
|
81
|
+
== LICENSE:
|
82
|
+
|
83
|
+
(The MIT License or the Ruby License, choose)
|
84
|
+
|
85
|
+
Copyright (c) 2007 Kaspar Schiess, all rights reserved
|
86
|
+
|
87
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
88
|
+
a copy of this software and associated documentation files (the
|
89
|
+
'Software'), to deal in the Software without restriction, including
|
90
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
91
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
92
|
+
permit persons to whom the Software is furnished to do so, subject to
|
93
|
+
the following conditions:
|
94
|
+
|
95
|
+
The above copyright notice and this permission notice shall be
|
96
|
+
included in all copies or substantial portions of the Software.
|
97
|
+
|
98
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
99
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
100
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
101
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
102
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
103
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
104
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
105
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'hoe'
|
3
|
+
require './lib/scoped_proxy'
|
4
|
+
|
5
|
+
namespace :hoe do
|
6
|
+
Hoe.new('ScopedProxy', ScopedProxy::VERSION) do |p|
|
7
|
+
p.rubyforge_name = 'swissrb'
|
8
|
+
p.author = 'Kaspar Schiess'
|
9
|
+
p.email = 'eule@space.ch'
|
10
|
+
p.summary = p.paragraphs_of('README.txt', 1..3).join("\n\n")
|
11
|
+
p.description = p.paragraphs_of('README.txt', 4..7).join(' ')
|
12
|
+
p.url = p.paragraphs_of('README.txt', 17).join(' ')
|
13
|
+
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'spec/rake/spectask'
|
18
|
+
require 'spec/translator'
|
19
|
+
|
20
|
+
task :default => :spec
|
21
|
+
|
22
|
+
desc "Run all specs in spec directory (excluding plugin specs)"
|
23
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
24
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
25
|
+
end
|
data/lib/scoped_proxy.rb
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'metaid'
|
2
|
+
require 'active_record'
|
3
|
+
|
4
|
+
# Smart scoping for AR models
|
5
|
+
# Author: Kaspar Schiess, (c) by Neotrivium AG, 2007
|
6
|
+
# Distributed under the terms of the Ruby License
|
7
|
+
|
8
|
+
module ScopedProxy
|
9
|
+
VERSION = '1.0.0'
|
10
|
+
|
11
|
+
# Allows you to create scoped proxies in models.
|
12
|
+
#
|
13
|
+
# Example
|
14
|
+
#
|
15
|
+
# class User < ActiveRecord::Base
|
16
|
+
# scoped_proxy :woman, :find => { :conditions => ['sex=?', 'f'] }
|
17
|
+
#
|
18
|
+
# Allowed options
|
19
|
+
# * :exclusive if set to true, this proxy will not apply if there is another proxy active.
|
20
|
+
#
|
21
|
+
class Proxy
|
22
|
+
cattr_accessor :active_proxy
|
23
|
+
@@active_proxy = false
|
24
|
+
|
25
|
+
def initialize(klass, scope={}, old_scope=nil, options={})
|
26
|
+
@klass, @scope, @old_scope = klass, scope, old_scope
|
27
|
+
@options = options
|
28
|
+
end
|
29
|
+
|
30
|
+
def method_missing(message, *args, &block)
|
31
|
+
exclusive_scope = @options[:exclusive] || false
|
32
|
+
activate_proxy = (! exclusive_scope) || (exclusive_scope && no_other_proxy_active?)
|
33
|
+
|
34
|
+
conditional_scope(@old_scope) do # Install previous scope
|
35
|
+
conditional_scope(@scope, activate_proxy) do # Install this scope
|
36
|
+
with_proxy do # Track active proxies
|
37
|
+
@klass.send(message, *args, &block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def respond_to_with_delegation?(symbol)
|
44
|
+
self.respond_to_without_delegation?(symbol) || @klass.respond_to?(symbol)
|
45
|
+
end
|
46
|
+
alias_method_chain :respond_to?, :delegation
|
47
|
+
|
48
|
+
# Mark the installation of a proxy. This information can be used to make proxies dependent upon context, as in
|
49
|
+
# the default proxy.
|
50
|
+
#
|
51
|
+
def with_proxy
|
52
|
+
begin
|
53
|
+
old_value = self.class.active_proxy
|
54
|
+
self.class.active_proxy = true
|
55
|
+
yield
|
56
|
+
ensure
|
57
|
+
self.class.active_proxy = old_value
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Is there no other proxy than this one active?
|
62
|
+
#
|
63
|
+
def no_other_proxy_active?
|
64
|
+
! self.class.active_proxy
|
65
|
+
end
|
66
|
+
|
67
|
+
# Install given scope if it is not nil and the predicate is true. Then yield.
|
68
|
+
#
|
69
|
+
def conditional_scope(scope, pred=true)
|
70
|
+
if scope && pred
|
71
|
+
klass_with_scope(@klass, scope) do
|
72
|
+
yield
|
73
|
+
end
|
74
|
+
else
|
75
|
+
yield
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Permit access to with_scope from outside the AR::Base class. This is an exception to the rule ;)
|
80
|
+
#
|
81
|
+
def klass_with_scope(klass, scope, &block)
|
82
|
+
klass.send(:with_scope, scope, &block)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.included(base)
|
87
|
+
base.extend(ClassMethods)
|
88
|
+
end
|
89
|
+
|
90
|
+
module ClassMethods
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
# Add a default proxy to the object. A default proxy is a proxy that is always in effect, unless another proxy is
|
95
|
+
# used.
|
96
|
+
#
|
97
|
+
# Example
|
98
|
+
#
|
99
|
+
# class User
|
100
|
+
# default_proxy :find => { :conditions => { :deleted_at => nil } }
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
# The example only returns users that haven't been marked as deleted - unless you use another proxy on the User
|
104
|
+
# object.
|
105
|
+
#
|
106
|
+
def default_proxy(scope=nil)
|
107
|
+
scoped_proxy :default_proxy, scope, :exclusive => true
|
108
|
+
|
109
|
+
[:find, :count].each do |meth|
|
110
|
+
meth_name = "#{meth}_with_default_proxy"
|
111
|
+
meth_without = "#{meth}_without_default_proxy"
|
112
|
+
metaclass.class_eval %Q{
|
113
|
+
def #{meth_name}(*args, &block)
|
114
|
+
default_proxy.#{meth_without}(*args, &block)
|
115
|
+
end
|
116
|
+
alias_method_chain :#{meth}, :default_proxy
|
117
|
+
}
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Install a scoped proxy with the given name.
|
122
|
+
#
|
123
|
+
# Example
|
124
|
+
#
|
125
|
+
# class User < ActiveRecord::Base
|
126
|
+
# scoped_proxy :woman, :find => { :conditions => ['sex=?', 'f'] }
|
127
|
+
#
|
128
|
+
def scoped_proxy(name, scope=nil, opts={}, &block)
|
129
|
+
meta_def(name) do |*args|
|
130
|
+
resulting_scope = scope
|
131
|
+
resulting_scope = block.call(*args) if block
|
132
|
+
|
133
|
+
target = self
|
134
|
+
Proxy.new(target, resulting_scope, self.current_scoped_methods, opts)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class ActiveRecord::Base
|
141
|
+
include ScopedProxy
|
142
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
require 'spec'
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
4
|
+
require 'scoped_proxy'
|
5
|
+
|
6
|
+
def silence
|
7
|
+
old_verbose, $VERBOSE = $VERBOSE, nil
|
8
|
+
yield
|
9
|
+
ensure
|
10
|
+
$VERBOSE = old_verbose
|
11
|
+
end
|
12
|
+
|
13
|
+
# NOTE: Running these tests WILL destroy a database called test (overwriting tables and such). You have been warned.
|
14
|
+
|
15
|
+
describe ScopedProxy, " availability" do
|
16
|
+
it "should be a module" do
|
17
|
+
ScopedProxy.should be_kind_of(Module)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
silence do
|
22
|
+
ActiveRecord::Schema.define do
|
23
|
+
create_table :users, :force => true do |t|
|
24
|
+
t.column :name, :string
|
25
|
+
t.column :role, :string
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
class User < ActiveRecord::Base
|
30
|
+
scoped_proxy :johns, :find => {
|
31
|
+
:conditions => ['name like ?', 'john%']
|
32
|
+
}
|
33
|
+
scoped_proxy :janes, :find => {
|
34
|
+
:conditions => ['name like ?', 'jane%']
|
35
|
+
}
|
36
|
+
end
|
37
|
+
john1 = User.create!(:name => 'john1', :role => 'admin')
|
38
|
+
john2 = User.create!(:name => 'john2', :role => 'user')
|
39
|
+
jane1 = User.create!(:name => 'jane1', :role => 'user')
|
40
|
+
|
41
|
+
describe User, " and users that are john" do
|
42
|
+
it "should have johns" do
|
43
|
+
User.should respond_to(:johns)
|
44
|
+
end
|
45
|
+
it "johns should return a proxy" do
|
46
|
+
User.johns.should be_kind_of(ScopedProxy::Proxy)
|
47
|
+
end
|
48
|
+
it "should allow us to find all johns" do
|
49
|
+
johns = User.find(:all, :conditions => 'name like \'john%\'')
|
50
|
+
|
51
|
+
User.johns.find(:all).should eql(johns)
|
52
|
+
end
|
53
|
+
it "should have count and other methods" do
|
54
|
+
User.johns.find(:all)
|
55
|
+
User.johns.count
|
56
|
+
end
|
57
|
+
it "should respond to count and other methods" do
|
58
|
+
User.johns.should respond_to(:count)
|
59
|
+
User.johns.should respond_to(:find)
|
60
|
+
User.johns.should respond_to(:destroy_all)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class User
|
65
|
+
scoped_proxy :role do |role|
|
66
|
+
{
|
67
|
+
:find => { :conditions => ['role = ?', role] }
|
68
|
+
}
|
69
|
+
end
|
70
|
+
end
|
71
|
+
describe User, "extended scoping" do
|
72
|
+
it "should have role proxy" do
|
73
|
+
User.should respond_to(:role)
|
74
|
+
end
|
75
|
+
it "should select roles as a filter" do
|
76
|
+
['admin', 'user'].each do |role|
|
77
|
+
expectation = User.find(:all, :conditions => {:role => role} )
|
78
|
+
User.role(role).find(:all).should eql(expectation)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
it "should allow combining roles into a bigger filter" do
|
82
|
+
# try both orders
|
83
|
+
User.janes.role('user').find(:first).should eql(jane1)
|
84
|
+
User.role('user').janes.find(:first).should eql(jane1)
|
85
|
+
end
|
86
|
+
it "should allow storing proxy and later on using it" do
|
87
|
+
janes = User.janes
|
88
|
+
|
89
|
+
janes.find(:first).should eql(jane1)
|
90
|
+
end
|
91
|
+
it "should capture its environment" do
|
92
|
+
johns = nil
|
93
|
+
User.send(:with_scope, :find => {:conditions => { :role => 'user'} } ) do
|
94
|
+
johns = User.johns
|
95
|
+
end
|
96
|
+
|
97
|
+
johns.find(:all).should eql([john2])
|
98
|
+
end
|
99
|
+
it "should capture a complex scoped environment" do
|
100
|
+
johns = nil
|
101
|
+
User.send(:with_scope, :find => {:conditions => { :role => 'user'} } ) do
|
102
|
+
johns = User.johns.role('admin')
|
103
|
+
end
|
104
|
+
|
105
|
+
johns.find(:all).should be_empty
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
silence do
|
110
|
+
ActiveRecord::Schema.define do
|
111
|
+
create_table :zebras, :force => true do |t|
|
112
|
+
t.column :stripes, :boolean
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
class Zebra < ActiveRecord::Base
|
117
|
+
default_proxy :find => {
|
118
|
+
:conditions => ['stripes = ?', true]
|
119
|
+
}
|
120
|
+
|
121
|
+
# Any further proxying will go back to unproxied default
|
122
|
+
scoped_proxy :bad
|
123
|
+
end
|
124
|
+
|
125
|
+
# All good zebras have stripes
|
126
|
+
10.times do Zebra.create!(:stripes => true) end
|
127
|
+
# Only some don't
|
128
|
+
Zebra.create!(:stripes => false)
|
129
|
+
|
130
|
+
describe Zebra, "default proxies" do
|
131
|
+
it "should not have johns or janes - that's User" do
|
132
|
+
# NOTE to the confused reader: For johns to be a method on User, it can either be a method of User's class (== Class)
|
133
|
+
# or a method of the singleton metaclass of User (== an anonymous class that inherits from Class). Now, we don't want
|
134
|
+
# stuff we define for the user (like eat_at_a_table) to be defined for all Zebras too - this is why we need #meta_def and
|
135
|
+
# not class_def. The two solutions are otherwise identical - this expectation forces the decision.
|
136
|
+
#
|
137
|
+
Zebra.should_not respond_to(:johns)
|
138
|
+
Zebra.should_not respond_to(:janes)
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should select only striped zebras by default" do
|
142
|
+
Zebra.count.should == 10
|
143
|
+
|
144
|
+
Zebra.find(:all).each do |zebra|
|
145
|
+
zebra.stripes.should eql(true)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
it "should select all zebras with any other proxy" do
|
149
|
+
Zebra.send(:with_scope, :find => { :conditions => ['id>0'] }) do
|
150
|
+
Zebra.bad.count.should == 11
|
151
|
+
end
|
152
|
+
Zebra.bad.count.should == 11
|
153
|
+
Zebra.bad.bad.count.should == 11
|
154
|
+
|
155
|
+
Zebra.bad.find(:all, :conditions => { :stripes => false }).each do |zebra|
|
156
|
+
zebra.stripes.should == false
|
157
|
+
end
|
158
|
+
end
|
159
|
+
it "should allow accessing the default proxy trough #default_proxy" do
|
160
|
+
default = Zebra.default_proxy
|
161
|
+
|
162
|
+
default.count.should == 10
|
163
|
+
end
|
164
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ScopedProxy
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ""
|
6
|
+
authors:
|
7
|
+
- Kaspar Schiess
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2007-12-21 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: hoe
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.3.0
|
23
|
+
version:
|
24
|
+
description: "== SYNOPSIS: Allows storing scopes as names; that way you can address subsets of your model space by meaningful names. require 'scoped_proxy' # Railsers: You might want to call this in environment.rb class User < ActiveRecord::Base scoped_proxy :role do |role| { :find => { :conditions => ['role = ?', role] } } end scoped_proxy :deleted, :find => { :conditions => 'deleted_at is not null' } end admins = User.role('admin') admins.count # => 12 admins.find(:all) # => [ ... ] User.deleted.count # => a number This implementation also brings (NEW, SHINY) default proxies. That means you can have a proxy in effect when no other proxy is in effect. class User < ActiveRecord::Base default_proxy :find => { :conditions => 'deleted_at is null' } end User.find(:all) # only finds users that aren't deleted"
|
25
|
+
email: eule@space.ch
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files:
|
31
|
+
- History.txt
|
32
|
+
- Manifest.txt
|
33
|
+
- README.txt
|
34
|
+
files:
|
35
|
+
- History.txt
|
36
|
+
- Manifest.txt
|
37
|
+
- README.txt
|
38
|
+
- Rakefile
|
39
|
+
- lib/scoped_proxy.rb
|
40
|
+
- spec/scoped_proxy_spec.rb
|
41
|
+
- spec/spec_helper.rb
|
42
|
+
has_rdoc: true
|
43
|
+
homepage: http://rubyforge.org/projects/swissrb
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options:
|
46
|
+
- --main
|
47
|
+
- README.txt
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "0"
|
61
|
+
version:
|
62
|
+
requirements: []
|
63
|
+
|
64
|
+
rubyforge_project: swissrb
|
65
|
+
rubygems_version: 0.9.5
|
66
|
+
signing_key:
|
67
|
+
specification_version: 2
|
68
|
+
summary: == SUMMARY Finally, long awaited, scoped proxies as a release. Which you say. Admitted, there are about 15 plugins that are called scoped_proxy, but only one comes with a full suite of tests that is full 40 lines longer than the actual code. That is the scoped proxy you are looking at. It is y2k compliant and works as a gem. Magnificent, isn't it? This gem is all about simplicity; you won't find a whole toolbox here, just another valued screwdriver. But we happen to encounter a lot of screws - hopefully you do too - and find this very useful. If you want to skip all this summary that is really longer than all the other texts in this release, have a look at the synopsis below.
|
69
|
+
test_files: []
|
70
|
+
|