fake_arel 0.2 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/fake_arel.rb CHANGED
@@ -8,7 +8,7 @@ require 'fake_arel/with_scope_replacement'
8
8
  require 'fake_arel/rails_3_finders'
9
9
 
10
10
  module FakeArel
11
- VERSION = '0.2'
11
+ VERSION = '0.5'
12
12
  ActiveRecord::Base.send :include, Rails3Finders
13
13
  ActiveRecord::Base.send :include, WithScopeReplacement
14
14
  end
@@ -6,26 +6,10 @@ module ActiveRecord
6
6
 
7
7
  scopes[name] = lambda do |parent_scope, *args|
8
8
  Scope.new(parent_scope, case options
9
- when Hash
9
+ when Hash, Scope
10
10
  options
11
- when Scope
12
- # unspin the scope and generate a hash
13
- local_scope = options.proxy_scope
14
- ret = options.proxy_options
15
- while local_scope.class == ActiveRecord::NamedScope::Scope
16
- ret[:conditions] = merge_conditions(ret[:conditions], local_scope.proxy_options[:conditions])
17
- ret[:includes] = merge_includes(ret[:includes], local_scope.proxy_options[:includes]) if ret[:includes] || local_scope.proxy_options[:includes]
18
- ret[:joins] = merge_includes(ret[:joins], local_scope.proxy_options[:joins])
19
- ret[:order] = merge_includes(ret[:order], local_scope.proxy_options[:order]) if ret[:order] || local_scope.proxy_options[:order]
20
- local_scope = local_scope.proxy_scope
21
- end
22
- ret
23
11
  when Proc
24
- if self.model_name != parent_scope.model_name
25
- options.bind(parent_scope).call(*args)
26
- else
27
- options.call(*args)
28
- end
12
+ options.call(*args)
29
13
  end, &block)
30
14
  end
31
15
 
@@ -36,92 +20,26 @@ module ActiveRecord
36
20
  end
37
21
 
38
22
  class Scope
39
- attr_reader :proxy_scope, :proxy_options, :current_scoped_methods_when_defined
40
23
  undef select
41
- [].methods.each do |m|
42
- unless m =~ /^__/ || (NON_DELEGATE_METHODS + ['select']).include?(m.to_s)
43
- delegate m, :to => :proxy_found
44
- end
45
- end
46
-
47
- delegate :scopes, :with_scope, :scoped_methods, :to => :proxy_scope
48
24
 
25
+ alias initialize_without_arel initialize
49
26
  def initialize(proxy_scope, options = {}, &block)
50
- options ||= {}
51
- options = options.proxy_options if options.class == ActiveRecord::NamedScope::Scope
52
- [options[:extend]].flatten.each { |extension| extend extension } if options[:extend]
53
- extend Module.new(&block) if block_given?
54
- unless Scope === proxy_scope
55
- @current_scoped_methods_when_defined = proxy_scope.send(:current_scoped_methods)
56
- end
57
- @proxy_scope, @proxy_options = proxy_scope, options.except(:extend)
58
- end
59
-
60
- def reload
61
- load_found; self
62
- end
63
-
64
- def first(*args)
65
- if args.first.kind_of?(Integer) || (@found && !args.first.kind_of?(Hash))
66
- proxy_found.first(*args)
67
- else
68
- find(:first, *args)
69
- end
70
- end
71
-
72
- def last(*args)
73
- if args.first.kind_of?(Integer) || (@found && !args.first.kind_of?(Hash))
74
- proxy_found.last(*args)
75
- else
76
- find(:last, *args)
77
- end
78
- end
79
-
80
- def size
81
- @found ? @found.length : count
82
- end
83
-
84
- def empty?
85
- @found ? @found.empty? : count.zero?
86
- end
87
-
88
- def respond_to?(method, include_private = false)
89
- super || @proxy_scope.respond_to?(method, include_private)
90
- end
91
-
92
- def any?
93
- if block_given?
94
- proxy_found.any? { |*block_args| yield(*block_args) }
95
- else
96
- !empty?
97
- end
98
- end
99
-
100
- protected
101
- def proxy_found
102
- @found || load_found
103
- end
104
-
105
- private
106
- def method_missing(method, *args, &block)
107
- if scopes.include?(method)
108
- scopes[method].call(self, *args)
109
- else
110
- with_scope({:find => proxy_options, :create => proxy_options[:conditions].is_a?(Hash) ? proxy_options[:conditions] : {}}, :reverse_merge) do
111
- method = :new if method == :build
112
- if current_scoped_methods_when_defined && !scoped_methods.include?(current_scoped_methods_when_defined)
113
- with_scope current_scoped_methods_when_defined do
114
- proxy_scope.send(method, *args, &block)
115
- end
116
- else
117
- proxy_scope.send(method, *args, &block)
118
- end
119
- end
120
- end
121
- end
122
-
123
- def load_found
124
- @found = find(:all)
27
+ options = options.unspin if options.class == ActiveRecord::NamedScope::Scope
28
+ initialize_without_arel(proxy_scope, options, &block)
29
+ end
30
+
31
+ def unspin
32
+ # unspin the scope and generate a hash
33
+ local_scope = proxy_scope
34
+ ret = proxy_options
35
+ while local_scope.class == ActiveRecord::NamedScope::Scope
36
+ ret[:conditions] = merge_conditions(ret[:conditions], local_scope.proxy_options[:conditions])
37
+ ret[:includes] = merge_includes(ret[:includes], local_scope.proxy_options[:includes]) if ret[:includes] || local_scope.proxy_options[:includes]
38
+ ret[:joins] = merge_includes(ret[:joins], local_scope.proxy_options[:joins])
39
+ ret[:order] = [local_scope.proxy_options[:order], ret[:order]].select{|o| !o.blank?}.join(',') if ret[:order] || local_scope.proxy_options[:order]
40
+ local_scope = local_scope.proxy_scope
41
+ end
42
+ ret
125
43
  end
126
44
  end
127
45
 
@@ -7,8 +7,8 @@ module Rails3Finders
7
7
  named_scope :offset, lambda {|offset| {:offset => offset}}
8
8
  named_scope :limit, lambda {|limit| {:limit => limit}}
9
9
  named_scope :includes, lambda { |*includes| { :include => includes }}
10
- named_scope :select, lambda {|*select| {:select => select }}
11
- named_scope :order, lambda {|order| {:order => order }}
10
+ named_scope :select, lambda {|*select| {:select => select.join(',') }}
11
+ named_scope :order, lambda {|*order| {:order => order.join(',') }}
12
12
  named_scope :joins, lambda {|*join| {:joins => join }}
13
13
  named_scope :from, lambda {|*from| {:from => from }}
14
14
  named_scope :having, lambda {|*having| {:having => having }}
@@ -5,7 +5,7 @@ module WithScopeReplacement
5
5
  def to_sql
6
6
  construct_finder_sql self.current_scoped_methods[:find]
7
7
  end
8
-
8
+
9
9
  def with_scope(method_scoping = {}, action = :merge, &block)
10
10
  method_scoping = {:find => method_scoping.proxy_options} if method_scoping.class == ActiveRecord::NamedScope::Scope
11
11
  method_scoping = method_scoping.method_scoping if method_scoping.respond_to?(:method_scoping)
@@ -41,6 +41,10 @@ module WithScopeReplacement
41
41
  hash[method][key] = merge_includes(hash[method][key], params[key]).uniq
42
42
  elsif key == :joins && merge
43
43
  hash[method][key] = merge_joins(params[key], hash[method][key])
44
+ # see https://rails.lighthouseapp.com/projects/8994/tickets/2810-with_scope-should-accept-and-use-order-option
45
+ # it works now in reverse order to comply with ActiveRecord 3
46
+ elsif key == :order && merge && !default_scoping.any?{ |s| s[method].keys.include?(key) }
47
+ hash[method][key] = [hash[method][key], params[key]].select{|o| !o.blank?}.join(', ')
44
48
  else
45
49
  hash[method][key] = hash[method][key] || params[key]
46
50
  end
@@ -66,12 +70,6 @@ module WithScopeReplacement
66
70
  self.scoped_methods.pop
67
71
  end
68
72
  end
69
-
70
- # Works like with_scope, but discards any nested properties.
71
- def with_exclusive_scope(method_scoping = {}, &block)
72
- with_scope(method_scoping, :overwrite, &block)
73
- end
74
-
75
73
  end
76
74
  end
77
75
  end
@@ -67,10 +67,35 @@ describe "chained nested named scopes" do
67
67
  Reply.topic_4_id_asc.all.should == Reply.find(:all, :conditions => {:topic_id => 4}, :order=>'id asc')
68
68
  Reply.topic_4_id_desc.all.should == Reply.find(:all, :conditions => {:topic_id => 4}, :order=>'id desc')
69
69
  end
70
+
71
+ it "should properly chain scope in definitions by lambda" do
72
+ Reply.recent_topic_id(4).all.should == Reply.find_all_by_id(5)
73
+ end
74
+
75
+ it "should properly chain order scope in definitions by lambda" do
76
+ Reply.topic__id_asc(4).all.should == Reply.find(:all, :conditions => {:topic_id => 4}, :order=>'id asc')
77
+ Reply.order('id desc').topic_id(4).all.should == Reply.find(:all, :conditions => {:topic_id => 4}, :order=>'id desc')
78
+ Reply.topic__id_desc(4).all.should == Reply.find(:all, :conditions => {:topic_id => 4}, :order=>'id desc')
79
+ end
80
+
81
+ it "should chain order scopes" do
82
+ # see https://rails.lighthouseapp.com/projects/8994/tickets/2810-with_scope-should-accept-and-use-order-option
83
+ # it works now in reverse order to comply with ActiveRecord 3
84
+ Reply.order('topic_id asc').order('created_at desc').all.should == Reply.find(:all, :order=>'topic_id asc, created_at desc')
85
+ Reply.order('topic_id asc').id_desc.all.should == Reply.find(:all, :order=>'topic_id asc, id desc')
86
+ Reply.topic_id_asc.id_desc.all.should == Reply.find(:all, :order=>'topic_id asc, id desc')
87
+ Reply.topic_id_asc_id_desc.all.should == Reply.find(:all, :order=>'topic_id asc, id desc')
88
+ Reply.lam_topic_id_asc_id_desc.all.should == Reply.find(:all, :order=>'topic_id asc, id desc')
89
+ Reply.with_scope(:find=>{:order=>'topic_id asc'}) do
90
+ Reply.with_scope(:find=>{:order=>'created_at desc'}) do
91
+ Reply.all
92
+ end
93
+ end.should == Reply.find(:all, :order=>'created_at desc, topic_id asc')
94
+ end
70
95
  end
71
96
 
72
97
  describe "keep scoped functionality" do
73
98
  it "should respond to scoped" do
74
- Reply.scoped.class.should == ActiveRecord::NamedScope::Scope
99
+ Reply.scoped({}).class.should == ActiveRecord::NamedScope::Scope
75
100
  end
76
101
  end
@@ -19,6 +19,13 @@ class Reply < ActiveRecord::Base
19
19
  named_scope :id_desc, order('id desc')
20
20
  named_scope :topic_4_id_asc, id_asc.where(:topic_id => 4)
21
21
  named_scope :topic_4_id_desc, id_desc.where(:topic_id => 4)
22
+ named_scope :topic_id, lambda{|topic_id| where(:topic_id => topic_id)}
23
+ named_scope :recent_topic_id, lambda{|topic_id| recent.where(:topic_id => topic_id)}
24
+ named_scope :topic__id_asc, lambda{|topic_id| id_asc.where(:topic_id => topic_id)}
25
+ named_scope :topic__id_desc, lambda{|topic_id| id_desc.where(:topic_id => topic_id)}
26
+ named_scope :topic_id_asc, order('topic_id asc')
27
+ named_scope :topic_id_asc_id_desc, order('topic_id asc').id_desc
28
+ named_scope :lam_topic_id_asc_id_desc, lambda{ topic_id_asc.id_desc }
22
29
 
23
30
  validates_presence_of :content
24
31
 
data/spec/test.db CHANGED
Binary file
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fake_arel
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15
4
+ hash: 1
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 2
9
- version: "0.2"
8
+ - 5
9
+ version: "0.5"
10
10
  platform: ruby
11
11
  authors:
12
12
  - Grant Ammons
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-08-13 00:00:00 -04:00
17
+ date: 2010-08-17 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency