sexy_scopes 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/sexy_scopes.rb CHANGED
@@ -1,7 +1,15 @@
1
+ require 'active_support/dependencies/autoload'
2
+
1
3
  module SexyScopes
2
4
  %w( Version VERSION ).each do |constant|
3
5
  autoload constant, 'sexy_scopes/version'
4
6
  end
7
+
8
+ extend ActiveSupport::Autoload
9
+
10
+ autoload :Wrappers
11
+ autoload :ExpressionWrappers
12
+ autoload :PredicateWrappers
5
13
  end
6
14
 
7
15
  if defined? Rails::Railtie
@@ -1,92 +1,6 @@
1
- require 'delegate'
2
1
  require 'active_record'
3
- require 'sexy_scopes/wrappers'
4
- require 'sexy_scopes/arel'
2
+ require 'sexy_scopes/active_record/class_methods'
3
+ require 'sexy_scopes/active_record/dynamic_methods'
5
4
 
6
- module SexyScopes
7
- module ActiveRecord
8
- include Wrappers
9
-
10
- # Creates and extends an Arel <tt>Attribute</tt> representing the table's column with
11
- # the given <tt>name</tt>.
12
- #
13
- # @param [String, Symbol] name The attribute name
14
- #
15
- # @note Please note that no exception is raised if no such column actually exists.
16
- #
17
- # @example
18
- # User.where(User.attribute(:score) > 1000)
19
- # # => SELECT "users".* FROM "users" WHERE ("users"."score" > 1000)
20
- #
21
- def attribute(name)
22
- attribute = arel_table[name]
23
- extend_expression(attribute)
24
- end
25
-
26
- # Creates and extends an Arel <tt>SqlLiteral</tt> instance for the given <tt>expression</tt>,
27
- # first converted to a string using <tt>to_s</tt>.
28
- #
29
- # @param [String, #to_s] expression Any SQL expression.
30
- #
31
- # @example
32
- # def Circle.with_perimeter_smaller_than(perimeter)
33
- # where sql(2 * Math::PI) * radius < perimeter
34
- # end
35
- #
36
- # Circle.with_perimeter_smaller_than(20)
37
- # # => SELECT "circles".* FROM "circles" WHERE (6.283185307179586 * "circles"."radius" < 20)
38
- #
39
- def sql_literal(expression)
40
- ::Arel.sql(expression.to_s).tap do |literal|
41
- extend_expression(literal)
42
- extend_predicate(literal)
43
- end
44
- end
45
- alias_method :sql, :sql_literal
46
-
47
- # @!visibility private
48
- def respond_to?(method_name, include_private = false) # :nodoc:
49
- super || column_names.include?(method_name.to_s)
50
- end
51
-
52
- private
53
- # Equivalent to calling {#attribute} with the missing method's <tt>name</tt> if the table
54
- # has a column with that name.
55
- #
56
- # Delegates to superclass implementation otherwise, eventually raising <tt>NoMethodError</tt>.
57
- #
58
- # @see #attribute
59
- #
60
- # @note Due to the way this works, be careful not to use this syntactic sugar with existing
61
- # <tt>ActiveRecord::Base</tt> methods (see last example).
62
- #
63
- # @raise [NoMethodError] if the table has no corresponding column
64
- #
65
- # @example
66
- # # Suppose the "users" table has an "email" column, then these are equivalent:
67
- # User.email
68
- # User.attribute(:email)
69
- #
70
- # @example
71
- # # Here is the previous example (from `attribute`) rewritten:
72
- # User.where(User.score > 1000)
73
- # # => SELECT "users".* FROM "users" WHERE ("users"."score" > 1000)
74
- #
75
- # @example
76
- # # Don't use it with existing `ActiveRecord::Base` methods, i.e. `name`:
77
- # User.name # => "User"
78
- # # In these cases you'll have to use `attribute` explicitely
79
- # User.attribute(:name)
80
- #
81
- def method_missing(name, *args)
82
- if column_names.include?(name.to_s)
83
- attribute(name)
84
- else
85
- super
86
- end
87
- end
88
- end
89
-
90
- # Add these methods to Active Record
91
- ::ActiveRecord::Base.extend SexyScopes::ActiveRecord
92
- end
5
+ ActiveRecord::Base.extend SexyScopes::ActiveRecord::ClassMethods
6
+ ActiveRecord::Base.extend SexyScopes::ActiveRecord::DynamicMethods
@@ -0,0 +1,47 @@
1
+ require 'sexy_scopes/arel'
2
+ require 'sexy_scopes/wrappers'
3
+
4
+ module SexyScopes
5
+ module ActiveRecord
6
+ module ClassMethods
7
+ include Wrappers
8
+
9
+ # Creates and extends an Arel <tt>Attribute</tt> representing the table's column with
10
+ # the given <tt>name</tt>.
11
+ #
12
+ # @param [String, Symbol] name The attribute name
13
+ #
14
+ # @note Please note that no exception is raised if no such column actually exists.
15
+ #
16
+ # @example
17
+ # User.where(User.attribute(:score) > 1000)
18
+ # # => SELECT "users".* FROM "users" WHERE ("users"."score" > 1000)
19
+ #
20
+ def attribute(name)
21
+ attribute = arel_table[name]
22
+ extend_expression(attribute)
23
+ end
24
+
25
+ # Creates and extends an Arel <tt>SqlLiteral</tt> instance for the given <tt>expression</tt>,
26
+ # first converted to a string using <tt>to_s</tt>.
27
+ #
28
+ # @param [String, #to_s] expression Any SQL expression.
29
+ #
30
+ # @example
31
+ # def Circle.with_perimeter_smaller_than(perimeter)
32
+ # where sql(2 * Math::PI) * radius < perimeter
33
+ # end
34
+ #
35
+ # Circle.with_perimeter_smaller_than(20)
36
+ # # => SELECT "circles".* FROM "circles" WHERE (6.283185307179586 * "circles"."radius" < 20)
37
+ #
38
+ def sql_literal(expression)
39
+ ::Arel.sql(expression.to_s).tap do |literal|
40
+ extend_expression(literal)
41
+ extend_predicate(literal)
42
+ end
43
+ end
44
+ alias_method :sql, :sql_literal
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,69 @@
1
+ module SexyScopes
2
+ module ActiveRecord
3
+ module DynamicMethods
4
+ # @!visibility private
5
+ def respond_to?(method_name, include_private = false) # :nodoc:
6
+ super || respond_to_missing?(method_name, include_private)
7
+ end
8
+
9
+ # # @!visibility private
10
+ def respond_to_missing?(method_name, include_private = false) # :nodoc:
11
+ Object.respond_to?(:respond_to_missing?) && super || sexy_scopes_has_attribute?(method_name)
12
+ end
13
+
14
+ private
15
+ # Equivalent to calling {#attribute} with the missing method's <tt>name</tt> if the table
16
+ # has a column with that name.
17
+ #
18
+ # Delegates to superclass implementation otherwise, eventually raising <tt>NoMethodError</tt>.
19
+ #
20
+ # @see #attribute
21
+ #
22
+ # @note Due to the way this works, be careful not to use this syntactic sugar with existing
23
+ # <tt>ActiveRecord::Base</tt> methods (see last example).
24
+ #
25
+ # @raise [NoMethodError] if the table has no corresponding column
26
+ #
27
+ # @example
28
+ # # Suppose the "users" table has an "email" column, then these are equivalent:
29
+ # User.email
30
+ # User.attribute(:email)
31
+ #
32
+ # @example
33
+ # # Here is the previous example (from `attribute`) rewritten:
34
+ # User.where(User.score > 1000)
35
+ # # => SELECT "users".* FROM "users" WHERE ("users"."score" > 1000)
36
+ #
37
+ # @example
38
+ # # Don't use it with existing `ActiveRecord::Base` methods, i.e. `name`:
39
+ # User.name # => "User"
40
+ # # In these cases you'll have to use `attribute` explicitely
41
+ # User.attribute(:name)
42
+ #
43
+ def method_missing(name, *args)
44
+ if sexy_scopes_has_attribute?(name)
45
+ sexy_scopes_define_attribute_method(name)
46
+ attribute(name)
47
+ else
48
+ super
49
+ end
50
+ end
51
+
52
+ def sexy_scopes_define_attribute_method(name)
53
+ class_eval <<-EVAL, __FILE__, __LINE__ + 1
54
+ def self.#{name} # def self.username
55
+ attribute(:#{name}) # attribute(:username)
56
+ end # end
57
+ EVAL
58
+ end
59
+
60
+ def sexy_scopes_has_attribute?(attribute_name)
61
+ if equal?(::ActiveRecord::Base) || abstract_class? || !table_exists?
62
+ false
63
+ else
64
+ column_names.include?(attribute_name.to_s)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -2,10 +2,9 @@ module SexyScopes
2
2
  module Arel
3
3
  extend ActiveSupport::Autoload
4
4
 
5
- autoload :ExpressionWrappers
6
- autoload :PredicateWrappers
7
- autoload :ExpressionMethods
5
+ autoload :MathMethods
8
6
  autoload :PredicateMethods
7
+ autoload :BooleanMethods
9
8
  end
10
9
  end
11
10
 
@@ -1,8 +1,6 @@
1
1
  module SexyScopes
2
2
  module Arel
3
- module PredicateWrappers
4
- include Wrappers
5
-
3
+ module BooleanMethods
6
4
  def not
7
5
  extend_predicate(super)
8
6
  end
@@ -1,6 +1,6 @@
1
1
  module SexyScopes
2
2
  module Arel
3
- module ExpressionMethods
3
+ module MathMethods
4
4
  def *(other)
5
5
  extend_expression(super)
6
6
  end
@@ -16,6 +16,10 @@ module SexyScopes
16
16
  def /(other)
17
17
  extend_expression(super)
18
18
  end
19
+
20
+ def coerce(other)
21
+ [extend_expression(::Arel.sql(other.to_s)), self]
22
+ end
19
23
  end
20
24
  end
21
25
  end
@@ -0,0 +1,7 @@
1
+ module SexyScopes
2
+ module ExpressionWrappers
3
+ include Wrappers
4
+ include Arel::PredicateMethods
5
+ include Arel::MathMethods
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ module SexyScopes
2
+ module PredicateWrappers
3
+ include Wrappers
4
+ include Arel::BooleanMethods
5
+ end
6
+ end
@@ -2,9 +2,17 @@ module SexyScopes
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 5
5
- TINY = 0
5
+ TINY = 1
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
+
9
+ class << self
10
+ # Allows {Version} to display ({to_s}) and behave ({to_str}) as a string
11
+ def to_str
12
+ STRING
13
+ end
14
+ alias_method :to_s, :to_str
15
+ end
8
16
  end
9
17
 
10
18
  VERSION = Version::STRING
@@ -3,11 +3,11 @@ module SexyScopes
3
3
  module Wrappers # :nodoc:
4
4
  private
5
5
  def extend_expression(expression)
6
- expression.extend(Arel::ExpressionWrappers)
6
+ expression.extend(ExpressionWrappers)
7
7
  end
8
8
 
9
9
  def extend_predicate(predicate)
10
- predicate.extend(Arel::PredicateWrappers)
10
+ predicate.extend(PredicateWrappers)
11
11
  end
12
12
  end
13
13
  end
data/sexy_scopes.gemspec CHANGED
@@ -20,10 +20,12 @@ Gem::Specification.new do |gem|
20
20
  gem.add_dependency 'activerecord', '~> 3.0'
21
21
 
22
22
  gem.add_development_dependency 'bundler', '~> 1.0'
23
- gem.add_development_dependency 'rake'
23
+ gem.add_development_dependency 'rake', '~> 0.9'
24
24
  gem.add_development_dependency 'rails', '~> 3.0'
25
25
  gem.add_development_dependency 'rspec', '~> 2.0'
26
- gem.add_development_dependency 'sqlite3'
26
+ gem.add_development_dependency 'sqlite3', '~> 1.0'
27
+ gem.add_development_dependency 'redcarpet', '~> 2.2'
28
+ gem.add_development_dependency 'yard', '~> 0.8'
27
29
  if RUBY_VERSION >= '1.9'
28
30
  gem.add_development_dependency 'simplecov'
29
31
  else
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ describe SexyScopes::ActiveRecord::ClassMethods do
4
+ it "should extend ActiveRecord::Base" do
5
+ ActiveRecord::Base.should be_extended_by SexyScopes::ActiveRecord::ClassMethods
6
+ end
7
+
8
+ describe ".attribute(name)" do
9
+ subject { User.attribute(:username) }
10
+
11
+ it "should return an Arel attribute for the given name" do
12
+ subject.should eql User.arel_table[:username]
13
+ end
14
+
15
+ it { should be_extended_by SexyScopes::ExpressionWrappers }
16
+ end
17
+
18
+ describe ".sql_literal(expression)" do
19
+ subject { User.sql_literal('NOW()') }
20
+
21
+ it "should return an Arel literal for given expression" do
22
+ subject.should eql(::Arel.sql('NOW()'))
23
+ end
24
+
25
+ it "should be aliased as `sql`" do
26
+ SexyScopes::ActiveRecord::ClassMethods.instance_method(:sql).should ==
27
+ SexyScopes::ActiveRecord::ClassMethods.instance_method(:sql_literal)
28
+ end
29
+
30
+ it { should be_extended_by SexyScopes::ExpressionWrappers }
31
+
32
+ it { should be_extended_by SexyScopes::PredicateWrappers }
33
+ end
34
+ end
35
+
36
+ describe SexyScopes::ActiveRecord::DynamicMethods do
37
+ before do
38
+ ActiveRecord::Migration.create_table :temp_users
39
+ ActiveRecord::Migration.add_column :temp_users, :username, :string
40
+ class ::TempUser < ActiveRecord::Base; end
41
+ end
42
+
43
+ after do
44
+ Object.send(:remove_const, :TempUser)
45
+ ActiveRecord::Migration.drop_table :temp_users
46
+ end
47
+
48
+ it "should delegate to `attribute` when the method name is the name of an existing column" do
49
+ TempUser.should respond_to(:username)
50
+ TempUser.should_receive(:attribute).with(:username).once.and_return(:ok)
51
+ TempUser.username.should == :ok
52
+ end
53
+
54
+ it "should define an attribute method to avoid repeated `method_missing` calls" do
55
+ TempUser.username
56
+ TempUser.should_not_receive(:method_missing)
57
+ TempUser.username
58
+ end
59
+
60
+ ruby_19 do
61
+ it "should return a Method object for an existing column" do
62
+ expect { TempUser.method(:username) }.to_not raise_error
63
+ end
64
+ end
65
+
66
+ it "should raise NoMethodError for a non-existing column" do
67
+ TempUser.should_not respond_to(:foobar)
68
+ expect { TempUser.foobar }.to raise_error NoMethodError
69
+ end
70
+
71
+ it "should not raise error when table doesn't exist" do
72
+ TempUser.table_name = "inexistent_users"
73
+ expect { TempUser.respond_to?(:username) }.to_not raise_error
74
+ end
75
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe SexyScopes::Arel::BooleanMethods do
4
+ before do
5
+ @attribute = User.attribute(:score)
6
+ @predicate = @attribute < 1000
7
+ @predicate2 = @attribute >= 200
8
+ end
9
+
10
+ describe ".not" do
11
+ subject { @predicate.not }
12
+
13
+ it_behaves_like "a predicate method"
14
+
15
+ it { should convert_to_sql %{NOT ("users"."score" < 1000)} }
16
+
17
+ it "should be aliased as `~`" do
18
+ @predicate.method(:~).should == @predicate.method(:not)
19
+ end
20
+ end
21
+
22
+ describe ".and(predicate)" do
23
+ subject { @predicate.and(@predicate2) }
24
+
25
+ it_behaves_like "a predicate method"
26
+
27
+ it { should convert_to_sql %{"users"."score" < 1000 AND "users"."score" >= 200} }
28
+
29
+ it "should be aliased as `&`" do
30
+ @predicate.method(:&).should == @predicate.method(:and)
31
+ end
32
+ end
33
+
34
+ describe ".or(predicate)" do
35
+ subject { @predicate.or(@predicate2) }
36
+
37
+ it_behaves_like "a predicate method"
38
+
39
+ it { should convert_to_sql %{("users"."score" < 1000 OR "users"."score" >= 200)} }
40
+
41
+ it "should be aliased as `|`" do
42
+ @predicate.method(:|).should == @predicate.method(:or)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,2 @@
1
+ class User < ActiveRecord::Base
2
+ end
@@ -0,0 +1,9 @@
1
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
2
+
3
+ ActiveRecord::Schema.verbose = false
4
+ ActiveRecord::Schema.define do
5
+ create_table :users do |t|
6
+ t.string :username
7
+ t.integer :score
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ RSpec::Matchers.define :be_extended_by do |expected|
2
+ match do |actual|
3
+ extended_modules = actual.singleton_class.included_modules
4
+ extended_modules.include?(expected)
5
+ end
6
+ end
@@ -0,0 +1,13 @@
1
+ RSpec::Matchers.define :convert_to_sql do |expected|
2
+ match do |actual|
3
+ actual.to_sql == expected
4
+ end
5
+
6
+ description do
7
+ "convert to the following SQL: #{expected}"
8
+ end
9
+
10
+ failure_message_for_should do |actual|
11
+ "expected generated SQL to be \n #{expected}\ngot\n #{actual.to_sql}"
12
+ end
13
+ end
@@ -1,14 +1,14 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  shared_examples "an expression method" do
4
4
  it "should return an Arel node" do
5
5
  subject.class.name.should =~ /^Arel::/
6
6
  end
7
7
 
8
- it { should be_extended_by SexyScopes::Arel::ExpressionWrappers }
8
+ it { should be_extended_by SexyScopes::ExpressionWrappers }
9
9
  end
10
10
 
11
- describe SexyScopes::Arel::ExpressionMethods do
11
+ describe SexyScopes::Arel::MathMethods do
12
12
  before do
13
13
  @attribute = User.attribute(:score)
14
14
  end
@@ -44,4 +44,12 @@ describe SexyScopes::Arel::ExpressionMethods do
44
44
 
45
45
  it { should convert_to_sql %{"users"."score" / 42.0} }
46
46
  end
47
+
48
+ describe "type coercion" do
49
+ subject { 42.0 / @attribute }
50
+
51
+ it_behaves_like "an expression method"
52
+
53
+ it { should convert_to_sql %{42.0 / "users"."score"} }
54
+ end
47
55
  end
@@ -1,12 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- shared_examples "a predicate method" do
4
- it "should return an Arel node" do
5
- subject.class.name.should =~ /^Arel::/
6
- end
7
-
8
- it { should be_extended_by SexyScopes::Arel::PredicateWrappers }
9
- end
1
+ require 'spec_helper'
10
2
 
11
3
  describe SexyScopes::Arel::PredicateMethods do
12
4
  before do
data/spec/spec_helper.rb CHANGED
@@ -7,36 +7,22 @@ require 'rspec'
7
7
  require 'active_record'
8
8
  require 'sexy_scopes'
9
9
 
10
- RSpec::Matchers.define :be_extended_by do |expected|
11
- match do |actual|
12
- extended_modules = actual.singleton_class.included_modules
13
- extended_modules.include?(expected)
14
- end
10
+ RSpec.configure do |config|
11
+ config.extend Module.new {
12
+ def ruby_19
13
+ yield if RUBY_VERSION >= "1.9"
14
+ end
15
+ }
15
16
  end
16
17
 
17
- RSpec::Matchers.define :convert_to_sql do |expected|
18
- match do |actual|
19
- actual.to_sql == expected
20
- end
21
-
22
- description do
23
- "convert to the following SQL: #{expected}"
24
- end
25
-
26
- failure_message_for_should do |actual|
27
- "expected generated SQL to be \n #{expected}\ngot\n #{actual.to_sql}"
28
- end
18
+ Dir.glob(File.join(File.dirname(__FILE__), '{fixtures,matchers}', '*')) do |file|
19
+ require file
29
20
  end
30
21
 
31
- ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
32
-
33
- ActiveRecord::Schema.verbose = false
34
- ActiveRecord::Schema.define do
35
- create_table :users do |t|
36
- t.string :username
37
- t.integer :score
22
+ shared_examples "a predicate method" do
23
+ it "should return an Arel node" do
24
+ subject.class.name.should =~ /^Arel::/
38
25
  end
39
- end
40
-
41
- class User < ActiveRecord::Base
26
+
27
+ it { should be_extended_by SexyScopes::PredicateWrappers }
42
28
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sexy_scopes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-29 00:00:00.000000000 Z
12
+ date: 2013-01-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -48,17 +48,17 @@ dependencies:
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
51
- - - ! '>='
51
+ - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: '0'
53
+ version: '0.9'
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  none: false
58
58
  requirements:
59
- - - ! '>='
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '0.9'
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: rails
64
64
  requirement: !ruby/object:Gem::Requirement
@@ -96,17 +96,49 @@ dependencies:
96
96
  requirement: !ruby/object:Gem::Requirement
97
97
  none: false
98
98
  requirements:
99
- - - ! '>='
99
+ - - ~>
100
100
  - !ruby/object:Gem::Version
101
- version: '0'
101
+ version: '1.0'
102
102
  type: :development
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
- - - ! '>='
107
+ - - ~>
108
108
  - !ruby/object:Gem::Version
109
- version: '0'
109
+ version: '1.0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: redcarpet
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: '2.2'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: '2.2'
126
+ - !ruby/object:Gem::Dependency
127
+ name: yard
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ~>
132
+ - !ruby/object:Gem::Version
133
+ version: '0.8'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ~>
140
+ - !ruby/object:Gem::Version
141
+ version: '0.8'
110
142
  - !ruby/object:Gem::Dependency
111
143
  name: simplecov
112
144
  requirement: !ruby/object:Gem::Requirement
@@ -137,18 +169,26 @@ files:
137
169
  - Rakefile
138
170
  - lib/sexy_scopes.rb
139
171
  - lib/sexy_scopes/active_record.rb
172
+ - lib/sexy_scopes/active_record/class_methods.rb
173
+ - lib/sexy_scopes/active_record/dynamic_methods.rb
140
174
  - lib/sexy_scopes/arel.rb
141
- - lib/sexy_scopes/arel/expression_methods.rb
142
- - lib/sexy_scopes/arel/expression_wrappers.rb
175
+ - lib/sexy_scopes/arel/boolean_methods.rb
176
+ - lib/sexy_scopes/arel/math_methods.rb
143
177
  - lib/sexy_scopes/arel/predicate_methods.rb
144
- - lib/sexy_scopes/arel/predicate_wrappers.rb
178
+ - lib/sexy_scopes/expression_wrappers.rb
179
+ - lib/sexy_scopes/predicate_wrappers.rb
145
180
  - lib/sexy_scopes/railtie.rb
146
181
  - lib/sexy_scopes/version.rb
147
182
  - lib/sexy_scopes/wrappers.rb
148
183
  - sexy_scopes.gemspec
149
- - spec/expression_methods_spec.rb
184
+ - spec/active_record_spec.rb
185
+ - spec/boolean_methods_spec.rb
186
+ - spec/fixtures/models.rb
187
+ - spec/fixtures/schema.rb
188
+ - spec/matchers/be_extended_by.rb
189
+ - spec/matchers/convert_to_sql.rb
190
+ - spec/math_methods_spec.rb
150
191
  - spec/predicate_methods_spec.rb
151
- - spec/sexy_scopes_spec.rb
152
192
  - spec/spec_helper.rb
153
193
  homepage: https://github.com/samleb/sexy_scopes
154
194
  licenses:
@@ -163,18 +203,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
163
203
  - - ! '>='
164
204
  - !ruby/object:Gem::Version
165
205
  version: '0'
166
- segments:
167
- - 0
168
- hash: 953557397482339219
169
206
  required_rubygems_version: !ruby/object:Gem::Requirement
170
207
  none: false
171
208
  requirements:
172
209
  - - ! '>='
173
210
  - !ruby/object:Gem::Version
174
211
  version: '0'
175
- segments:
176
- - 0
177
- hash: 953557397482339219
178
212
  requirements: []
179
213
  rubyforge_project:
180
214
  rubygems_version: 1.8.23
@@ -182,7 +216,13 @@ signing_key:
182
216
  specification_version: 3
183
217
  summary: Write beautiful and expressive ActiveRecord scopes without SQL.
184
218
  test_files:
185
- - spec/expression_methods_spec.rb
219
+ - spec/active_record_spec.rb
220
+ - spec/boolean_methods_spec.rb
221
+ - spec/fixtures/models.rb
222
+ - spec/fixtures/schema.rb
223
+ - spec/matchers/be_extended_by.rb
224
+ - spec/matchers/convert_to_sql.rb
225
+ - spec/math_methods_spec.rb
186
226
  - spec/predicate_methods_spec.rb
187
- - spec/sexy_scopes_spec.rb
188
227
  - spec/spec_helper.rb
228
+ has_rdoc:
@@ -1,9 +0,0 @@
1
- module SexyScopes
2
- module Arel
3
- module ExpressionWrappers
4
- include Wrappers
5
- include PredicateMethods
6
- include ExpressionMethods
7
- end
8
- end
9
- end
@@ -1,47 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- describe SexyScopes::ActiveRecord do
4
- it "should extend ActiveRecord::Base" do
5
- ActiveRecord::Base.should be_extended_by SexyScopes::ActiveRecord
6
- end
7
-
8
- describe ".attribute(name)" do
9
- subject { User.attribute(:username) }
10
-
11
- it "should return an Arel attribute for the given name" do
12
- subject.should eql User.arel_table[:username]
13
- end
14
-
15
- it { should be_extended_by SexyScopes::Arel::ExpressionWrappers }
16
- end
17
-
18
- describe ".sql_literal(expression)" do
19
- subject { User.sql_literal('NOW()') }
20
-
21
- it "should return an Arel literal for given expression" do
22
- subject.should eql(::Arel.sql('NOW()'))
23
- end
24
-
25
- it "should be aliased as `sql`" do
26
- SexyScopes::ActiveRecord.instance_method(:sql).should ==
27
- SexyScopes::ActiveRecord.instance_method(:sql_literal)
28
- end
29
-
30
- it { should be_extended_by SexyScopes::Arel::ExpressionWrappers }
31
-
32
- it { should be_extended_by SexyScopes::Arel::PredicateWrappers }
33
- end
34
-
35
- context "dynamic method handling (method_missing/respond_to?)" do
36
- it "should delegate to `attribute` when the method name is the name of an existing column" do
37
- User.should respond_to(:username)
38
- User.should_receive(:attribute).with(:username).once.and_return(:ok)
39
- User.username.should == :ok
40
- end
41
-
42
- it "should raise NoMethodError otherwise" do
43
- User.should_not respond_to(:foobar)
44
- lambda { User.foobar }.should raise_error NoMethodError
45
- end
46
- end
47
- end