jferris-sconnect 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +45 -0
- data/Rakefile +62 -0
- data/lib/sconnect.rb +15 -0
- data/lib/sconnect/not.rb +55 -0
- data/lib/sconnect/or.rb +67 -0
- data/spec/not_spec.rb +66 -0
- data/spec/or_spec.rb +109 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/support/active_record_extensions.rb +18 -0
- data/spec/support/model_builder.rb +67 -0
- data/spec/support/scope_matcher.rb +8 -0
- data/spec/support/scope_options_matcher.rb +38 -0
- metadata +68 -0
data/README.rdoc
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
= Sconnect
|
2
|
+
|
3
|
+
Sconnect is an extension to ActiveRecord's named_scopes that allows you to combine scopes in more interesting and useful ways.
|
4
|
+
|
5
|
+
== Download
|
6
|
+
|
7
|
+
Github: http://github.com/jferris/sconnect/tree/master
|
8
|
+
|
9
|
+
== Examples
|
10
|
+
|
11
|
+
Given the following model:
|
12
|
+
|
13
|
+
class Post < ActiveRecord::Base
|
14
|
+
named_scope :published, :conditions => { :published => true }
|
15
|
+
named_scope :titled, :conditions => "title IS NOT NULL"
|
16
|
+
named_scope :from_today, lambda {
|
17
|
+
{ :conditions => ['created_at >= ?', 1.day.ago] }
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
ActiveRecord provides scope chains:
|
22
|
+
|
23
|
+
# All published posts with titles
|
24
|
+
Post.published.titled
|
25
|
+
|
26
|
+
# All published posts from today
|
27
|
+
Post.published.from_today
|
28
|
+
|
29
|
+
Sconnect extends these scopes:
|
30
|
+
|
31
|
+
# All posts that are either published or titled
|
32
|
+
Post.published.or.titled
|
33
|
+
|
34
|
+
# All posts that are published but not created today
|
35
|
+
Post.published.not.from_today
|
36
|
+
|
37
|
+
# All posts that are either published or untitled
|
38
|
+
Post.published.or.not.titled
|
39
|
+
|
40
|
+
# All posts from today that are either published or titled
|
41
|
+
Post.published.or.titled.from_today
|
42
|
+
|
43
|
+
== Author
|
44
|
+
|
45
|
+
Sconnect was written by Joe Ferris.
|
data/Rakefile
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rcov'
|
3
|
+
require 'spec/rake/spectask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
|
7
|
+
Spec::Rake::SpecTask.new do |t|
|
8
|
+
t.libs << 'spec'
|
9
|
+
t.spec_opts << '-O spec/spec.opts'
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'Generate documentation'
|
13
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
14
|
+
rdoc.rdoc_dir = 'rdoc'
|
15
|
+
rdoc.title = 'Sconnect'
|
16
|
+
rdoc.options <<
|
17
|
+
'--line-numbers' <<
|
18
|
+
'--inline-source' <<
|
19
|
+
"--main" <<
|
20
|
+
"README.rdoc"
|
21
|
+
rdoc.rdoc_files.include('README.rdoc')
|
22
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
+
end
|
24
|
+
|
25
|
+
task :default => :spec
|
26
|
+
|
27
|
+
spec = Gem::Specification.new do |s|
|
28
|
+
s.name = %q{sconnect}
|
29
|
+
s.version = "0.1"
|
30
|
+
s.summary = %q{Sconnect extends ActiveRecord's named scoped_chains to be
|
31
|
+
more useful an interesting.}
|
32
|
+
s.description = %q{Sconnect extends ActiveRecord's named_scope chains to allow
|
33
|
+
scopes to be combined inclusively, inverted, and more.}
|
34
|
+
|
35
|
+
s.files = FileList['[A-Z]*', 'lib/**/*.rb', 'spec/**/*.rb']
|
36
|
+
s.require_path = 'lib'
|
37
|
+
s.test_files = Dir[*['spec/**/*_spec.rb']]
|
38
|
+
|
39
|
+
s.has_rdoc = true
|
40
|
+
s.extra_rdoc_files = ["README.rdoc"]
|
41
|
+
s.rdoc_options = ['--line-numbers', '--inline-source', "--main", "README.rdoc"]
|
42
|
+
|
43
|
+
s.authors = ["Joe Ferris"]
|
44
|
+
s.email = %q{jferris@thoughtbot.com}
|
45
|
+
|
46
|
+
s.platform = Gem::Platform::RUBY
|
47
|
+
end
|
48
|
+
|
49
|
+
Rake::GemPackageTask.new spec do |pkg|
|
50
|
+
pkg.need_tar = true
|
51
|
+
pkg.need_zip = true
|
52
|
+
end
|
53
|
+
|
54
|
+
desc "Clean files generated by rake tasks"
|
55
|
+
task :clobber => [:clobber_rdoc, :clobber_package]
|
56
|
+
|
57
|
+
desc "Generate a gemspec file"
|
58
|
+
task :gemspec do
|
59
|
+
File.open("#{spec.name}.gemspec", 'w') do |f|
|
60
|
+
f.write spec.to_ruby
|
61
|
+
end
|
62
|
+
end
|
data/lib/sconnect.rb
ADDED
data/lib/sconnect/not.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
module Sconnect #:nodoc:
|
2
|
+
class NotScope < ActiveRecord::NamedScope::Scope #:nodoc:
|
3
|
+
|
4
|
+
delegate :current_scoped_methods, :sanitize_sql, :to => :proxy_scope
|
5
|
+
|
6
|
+
def initialize(proxy_scope)
|
7
|
+
@proxy_scope = proxy_scope
|
8
|
+
end
|
9
|
+
|
10
|
+
def proxy_options
|
11
|
+
@proxy_options ||= invert_scope_conditions(@right_scope)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def invert_scope_conditions(scope)
|
17
|
+
scope = scope.merge(:conditions => invert_conditions(scope[:conditions]))
|
18
|
+
end
|
19
|
+
|
20
|
+
def invert_conditions(conditions)
|
21
|
+
"NOT (#{sanitize_sql(conditions)})"
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_missing(method, *args, &block)
|
25
|
+
if scopes.include?(method)
|
26
|
+
right_scope = scopes[method].call(self, *args)
|
27
|
+
if @right_scope
|
28
|
+
right_scope
|
29
|
+
else
|
30
|
+
@right_scope = right_scope.proxy_options
|
31
|
+
self
|
32
|
+
end
|
33
|
+
else
|
34
|
+
super(method, *args, &block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module ActiveRecordClassExtensions
|
40
|
+
# Inverts the conditions of the following scope.
|
41
|
+
#
|
42
|
+
# Examples:
|
43
|
+
# # Returns all unpublished posts
|
44
|
+
# Post.not.published
|
45
|
+
#
|
46
|
+
# # Returns all unpublished posts from today
|
47
|
+
# Post.not.published.from_today
|
48
|
+
#
|
49
|
+
# # Same as above
|
50
|
+
# Post.from_today.not.published
|
51
|
+
def not
|
52
|
+
NotScope.new(self)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/sconnect/or.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
module Sconnect #:nodoc:
|
2
|
+
class OrScope < ActiveRecord::NamedScope::Scope #:nodoc:
|
3
|
+
|
4
|
+
delegate :current_scoped_methods, :sanitize_sql, :to => :proxy_scope
|
5
|
+
|
6
|
+
def initialize(left_scope)
|
7
|
+
@left_scope = left_scope.proxy_options
|
8
|
+
@proxy_scope = left_scope.proxy_scope
|
9
|
+
end
|
10
|
+
|
11
|
+
def proxy_options
|
12
|
+
@proxy_options ||= inclusively_combine_scopes(@left_scope, @right_scope)
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def inclusively_combine_scopes(left, right)
|
18
|
+
exclusively_combine_scopes(left, right).
|
19
|
+
merge(:conditions => combine_conditions(left, right))
|
20
|
+
end
|
21
|
+
|
22
|
+
def exclusively_combine_scopes(left, right)
|
23
|
+
with_scope(:find => left) do
|
24
|
+
with_scope(:find => right) do
|
25
|
+
current_scoped_methods[:find]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def combine_conditions(*scopes)
|
31
|
+
segments = scopes.collect do |scope|
|
32
|
+
sanitize_sql(scope[:conditions])
|
33
|
+
end
|
34
|
+
conditions = "(#{segments.join(') OR (')})"
|
35
|
+
end
|
36
|
+
|
37
|
+
def method_missing(method, *args, &block)
|
38
|
+
if scopes.include?(method)
|
39
|
+
right_scope = scopes[method].call(self, *args)
|
40
|
+
if @right_scope
|
41
|
+
right_scope
|
42
|
+
else
|
43
|
+
@right_scope = right_scope.proxy_options
|
44
|
+
self
|
45
|
+
end
|
46
|
+
else
|
47
|
+
super(method, *args, &block)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
module ScopeExtensions
|
53
|
+
# Joins the left and right-hand scopes into an inclusive conditional clause.
|
54
|
+
#
|
55
|
+
# Examples:
|
56
|
+
#
|
57
|
+
# # Posts published or owned by the user
|
58
|
+
# Post.published.or.owned_by(@user)
|
59
|
+
#
|
60
|
+
# # Posts from today that are either published or owned by the given user
|
61
|
+
# # (note that "or" binds tighter than the implicit "and")
|
62
|
+
# Post.from_today.published.or.owned_by(@user)
|
63
|
+
def or
|
64
|
+
OrScope.new(self)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/spec/not_spec.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Post" do
|
4
|
+
|
5
|
+
include ModelBuilder
|
6
|
+
|
7
|
+
before do
|
8
|
+
define_model :user
|
9
|
+
define_model :category
|
10
|
+
define_model :post, :published => :boolean,
|
11
|
+
:title => :string,
|
12
|
+
:user_id => :integer,
|
13
|
+
:category_id => :integer do
|
14
|
+
belongs_to :user
|
15
|
+
belongs_to :category
|
16
|
+
named_scope :published, :conditions => { :published => true },
|
17
|
+
:include => :user
|
18
|
+
named_scope :titled, :conditions => "title IS NOT NULL",
|
19
|
+
:include => :category
|
20
|
+
named_scope :from_today, lambda {
|
21
|
+
{ :conditions => ['created_at >= ?', 1.day.ago] }
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "titled but not published", :shared => true do
|
27
|
+
it "should find an unpublished, titled post" do
|
28
|
+
should include(Post.create!(:published => false, :title => 'Title'))
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should not find an unpublished, titled post" do
|
32
|
+
should_not include(Post.create!(:published => true, :title => 'Title'))
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should not find an published, untitled post" do
|
36
|
+
should_not include(Post.create!(:published => true, :title => nil))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe ".not.published" do
|
41
|
+
subject { Post.not.published }
|
42
|
+
|
43
|
+
it "should find an unpublished post" do
|
44
|
+
should include(Post.create!(:published => false))
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should not find an unpublished post" do
|
48
|
+
should_not include(Post.create!(:published => true))
|
49
|
+
end
|
50
|
+
|
51
|
+
it { should be_chainable }
|
52
|
+
end
|
53
|
+
|
54
|
+
describe ".not.published.titled" do
|
55
|
+
subject { Post.not.published }
|
56
|
+
it_should_behave_like "titled but not published"
|
57
|
+
it { should be_chainable }
|
58
|
+
end
|
59
|
+
|
60
|
+
describe ".titled.not.published" do
|
61
|
+
subject { Post.not.published }
|
62
|
+
it_should_behave_like "titled but not published"
|
63
|
+
it { should be_chainable }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
data/spec/or_spec.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Post" do
|
4
|
+
|
5
|
+
include ModelBuilder
|
6
|
+
|
7
|
+
before do
|
8
|
+
define_model :user
|
9
|
+
define_model :category
|
10
|
+
define_model :post, :published => :boolean,
|
11
|
+
:title => :string,
|
12
|
+
:user_id => :integer,
|
13
|
+
:category_id => :integer do
|
14
|
+
belongs_to :user
|
15
|
+
belongs_to :category
|
16
|
+
named_scope :published, :conditions => { :published => true },
|
17
|
+
:include => :user
|
18
|
+
named_scope :titled, :conditions => "title IS NOT NULL",
|
19
|
+
:include => :category
|
20
|
+
named_scope :from_today, lambda {
|
21
|
+
{ :conditions => ['created_at >= ?', 1.day.ago] }
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "published.or.titled", :shared => true do
|
27
|
+
it "should find a published, untitled post" do
|
28
|
+
should include(Post.create!(:published => true, :title => nil))
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should find an unpublished, titled post" do
|
32
|
+
should include(Post.create!(:published => false, :title => 'Title'))
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should find a published, titled post" do
|
36
|
+
should include(Post.create!(:published => true, :title => 'Title'))
|
37
|
+
end
|
38
|
+
|
39
|
+
it "not should find an unpublished, untitled post" do
|
40
|
+
should_not include(Post.create!(:published => false, :title => nil))
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should use non-conditional options from .published.titled" do
|
44
|
+
should include_scope_options_from(Post.published.titled)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "from_today", :shared => true do
|
49
|
+
it "not find a post published two days ago" do
|
50
|
+
should_not include(Post.create!(:published => true,
|
51
|
+
:title => 'Title',
|
52
|
+
:created_at => 2.days.ago))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe ".published.or.titled" do
|
57
|
+
subject { Post.published.or.titled }
|
58
|
+
it_should_behave_like "published.or.titled"
|
59
|
+
it { should be_chainable }
|
60
|
+
end
|
61
|
+
|
62
|
+
describe ".from_today.published.or.titled" do
|
63
|
+
subject { Post.from_today.published.or.titled }
|
64
|
+
|
65
|
+
it_should_behave_like "published.or.titled"
|
66
|
+
it_should_behave_like "from_today"
|
67
|
+
it { should be_chainable }
|
68
|
+
end
|
69
|
+
|
70
|
+
describe ".published.or.titled.from_today" do
|
71
|
+
subject { Post.published.or.titled.from_today }
|
72
|
+
|
73
|
+
it_should_behave_like "published.or.titled"
|
74
|
+
it_should_behave_like "from_today"
|
75
|
+
it { should be_chainable }
|
76
|
+
end
|
77
|
+
|
78
|
+
describe ".published.or.titled.or.from_today" do
|
79
|
+
subject { Post.published.or.titled.or.from_today }
|
80
|
+
|
81
|
+
it "should find a published, untitled post from today" do
|
82
|
+
should include(Post.create!(:published => true, :title => nil))
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should find an unpublished, titled post from today" do
|
86
|
+
should include(Post.create!(:published => false, :title => 'Title'))
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should find a published, titled post from today" do
|
90
|
+
should include(Post.create!(:published => true, :title => 'Title'))
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should find an unpublished, untitled post from today" do
|
94
|
+
should include(Post.create!(:published => false, :title => nil))
|
95
|
+
end
|
96
|
+
|
97
|
+
it "not should find an unpublished, untitled post from two days ago" do
|
98
|
+
should_not include(Post.create!(:published => false,
|
99
|
+
:title => nil,
|
100
|
+
:created_at => 2.days.ago))
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should use non-conditional options from .published.titled" do
|
104
|
+
should include_scope_options_from(Post.published.titled)
|
105
|
+
end
|
106
|
+
|
107
|
+
it { should be_chainable }
|
108
|
+
end
|
109
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
require 'active_record'
|
4
|
+
|
5
|
+
SCONNECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
6
|
+
|
7
|
+
Dir["#{SCONNECT_ROOT}/spec/support/**/*.rb"].each {|file| require(file) }
|
8
|
+
$: << "#{SCONNECT_ROOT}/lib"
|
9
|
+
|
10
|
+
ActiveRecord::Base.establish_connection(
|
11
|
+
:adapter => 'sqlite3',
|
12
|
+
:database => "#{SCONNECT_ROOT}/spec/database.sqlite3"
|
13
|
+
)
|
14
|
+
|
15
|
+
ActiveRecord::Base.logger = Logger.new("#{SCONNECT_ROOT}/spec/spec.log")
|
16
|
+
|
17
|
+
Spec::Runner.configure do |config|
|
18
|
+
config.include Matchers
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'sconnect'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Base
|
3
|
+
# This allows us to look at the options at the end of a chain of scopes.
|
4
|
+
def self.scope_options
|
5
|
+
current_scoped_methods[:find]
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module NamedScope
|
10
|
+
class Scope
|
11
|
+
# This allows Scope objects to be used as matchers. Without this hack, a
|
12
|
+
# Scope will be converted to an array when #should is called, so the
|
13
|
+
# matcher will always receive an array. This prevents #should from being
|
14
|
+
# delegated to the Scope's proxy.
|
15
|
+
remove_method :should
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module ModelBuilder
|
2
|
+
def self.included(example_group)
|
3
|
+
example_group.class_eval do
|
4
|
+
before do
|
5
|
+
@defined_constants = []
|
6
|
+
@created_tables = []
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
@defined_constants.each do |class_name|
|
11
|
+
Object.send(:remove_const, class_name)
|
12
|
+
end
|
13
|
+
|
14
|
+
@created_tables.each do |table_name|
|
15
|
+
ActiveRecord::Base.
|
16
|
+
connection.
|
17
|
+
execute("DROP TABLE IF EXISTS #{table_name}")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_table(table_name, &block)
|
24
|
+
connection = ActiveRecord::Base.connection
|
25
|
+
|
26
|
+
begin
|
27
|
+
connection.execute("DROP TABLE IF EXISTS #{table_name}")
|
28
|
+
connection.create_table(table_name, &block)
|
29
|
+
@created_tables << table_name
|
30
|
+
connection
|
31
|
+
rescue Exception => exception
|
32
|
+
connection.execute("DROP TABLE IF EXISTS #{table_name}")
|
33
|
+
raise exception
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def define_constant(class_name, base, &block)
|
38
|
+
class_name = class_name.to_s.camelize
|
39
|
+
|
40
|
+
klass = Class.new(base)
|
41
|
+
Object.const_set(class_name, klass)
|
42
|
+
|
43
|
+
klass.class_eval(&block) if block_given?
|
44
|
+
|
45
|
+
@defined_constants << class_name
|
46
|
+
|
47
|
+
klass
|
48
|
+
end
|
49
|
+
|
50
|
+
def define_model_class(class_name, &block)
|
51
|
+
define_constant(class_name, ActiveRecord::Base, &block)
|
52
|
+
end
|
53
|
+
|
54
|
+
def define_model(name, columns = {}, &block)
|
55
|
+
class_name = name.to_s.pluralize.classify
|
56
|
+
table_name = class_name.tableize
|
57
|
+
|
58
|
+
create_table(table_name) do |table|
|
59
|
+
columns.each do |name, type|
|
60
|
+
table.column name, type
|
61
|
+
end
|
62
|
+
table.timestamps
|
63
|
+
end
|
64
|
+
|
65
|
+
define_model_class(class_name, &block)
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Matchers
|
2
|
+
|
3
|
+
class ScopeOptionsMatcher
|
4
|
+
def initialize(expected)
|
5
|
+
@expected_scope_options = scope_options(expected)
|
6
|
+
end
|
7
|
+
|
8
|
+
def matches?(target)
|
9
|
+
target_scope_options = scope_options(target)
|
10
|
+
@expected_scope_options.detect do |@key, expected_values|
|
11
|
+
expected_values = [expected_values] unless expected_values.is_a?(Array)
|
12
|
+
@target_values = target_scope_options[@key]
|
13
|
+
@target_values = [@target_values] unless @target_values.is_a?(Array)
|
14
|
+
@missing =
|
15
|
+
expected_values.detect {|value| !@target_values.include?(value) }
|
16
|
+
end
|
17
|
+
|
18
|
+
@missing.nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
def failure_message
|
22
|
+
"Missing value #{@missing.inspect} for #{@key.inspect}" <<
|
23
|
+
" (found values: #{@target_values.inspect})"
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def scope_options(scope)
|
29
|
+
scope_options = scope.scope_options
|
30
|
+
scope_options.delete(:conditions)
|
31
|
+
scope_options
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def include_scope_options_from(scope)
|
36
|
+
ScopeOptionsMatcher.new(scope)
|
37
|
+
end
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jferris-sconnect
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joe Ferris
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-02-21 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Sconnect extends ActiveRecord's named_scope chains to allow scopes to be combined inclusively, inverted, and more.
|
17
|
+
email: jferris@thoughtbot.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
files:
|
25
|
+
- Rakefile
|
26
|
+
- README.rdoc
|
27
|
+
- lib/sconnect/not.rb
|
28
|
+
- lib/sconnect/or.rb
|
29
|
+
- lib/sconnect.rb
|
30
|
+
- spec/not_spec.rb
|
31
|
+
- spec/or_spec.rb
|
32
|
+
- spec/spec_helper.rb
|
33
|
+
- spec/support/active_record_extensions.rb
|
34
|
+
- spec/support/model_builder.rb
|
35
|
+
- spec/support/scope_matcher.rb
|
36
|
+
- spec/support/scope_options_matcher.rb
|
37
|
+
has_rdoc: true
|
38
|
+
homepage:
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options:
|
41
|
+
- --line-numbers
|
42
|
+
- --inline-source
|
43
|
+
- --main
|
44
|
+
- README.rdoc
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: "0"
|
52
|
+
version:
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: "0"
|
58
|
+
version:
|
59
|
+
requirements: []
|
60
|
+
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 1.2.0
|
63
|
+
signing_key:
|
64
|
+
specification_version: 2
|
65
|
+
summary: Sconnect extends ActiveRecord's named scoped_chains to be more useful an interesting.
|
66
|
+
test_files:
|
67
|
+
- spec/not_spec.rb
|
68
|
+
- spec/or_spec.rb
|