aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/associations/ar_joins_test.rb
blob: e6a9180faeacef7dfe09655f6062141a5c0be935 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
require 'abstract_unit'
require 'fixtures/post'
require 'fixtures/comment'
require 'fixtures/author'
require 'fixtures/category'
require 'fixtures/categorization'
require 'fixtures/company'
require 'fixtures/topic'
require 'fixtures/reply'
require 'fixtures/developer'
require 'fixtures/project'

class ArJoinsTest < Test::Unit::TestCase
  fixtures :authors, :posts, :comments, :categories, :categories_posts, :people,
           :developers, :projects, :developers_projects,
           :categorizations, :companies, :accounts, :topics

  def test_ar_joins
    authors = Author.find(:all, :joins => :posts, :conditions => ['posts.type = ?', "Post"])
    assert_not_equal(0 , authors.length)
    authors.each do |author|
      assert !(author.send(:instance_variables).include? "@posts")
      assert(!author.readonly?, "non-string join value produced read-only result.")
    end
  end

  def test_ar_joins_with_cascaded_two_levels
    authors = Author.find(:all, :joins=>{:posts=>:comments})
    assert_equal(2, authors.length)
    authors.each do |author|
      assert !(author.send(:instance_variables).include? "@posts")
      assert(!author.readonly?, "non-string join value produced read-only result.")
    end
    authors = Author.find(:all, :joins=>{:posts=>:comments}, :conditions => ["comments.body = ?", "go crazy" ])
    assert_equal(1, authors.length)
    authors.each do |author|
      assert !(author.send(:instance_variables).include? "@posts")
      assert(!author.readonly?, "non-string join value produced read-only result.")
    end
  end


  def test_ar_joins_with_complex_conditions
    authors = Author.find(:all, :joins=>{:posts=>[:comments, :categories]},
    :conditions => ["categories.name = ?  AND posts.title = ?", "General", "So I was thinking"]
    )
    assert_equal(1, authors.length)
    authors.each do |author|
      assert !(author.send(:instance_variables).include? "@posts")
      assert(!author.readonly?, "non-string join value produced read-only result.")
    end
    assert_equal("David", authors.first.name)
  end

  def test_ar_join_with_has_many_and_limit_and_scoped_and_explicit_conditions
    Post.with_scope(:find => { :conditions => "1=1" }) do
      posts = authors(:david).posts.find(:all,
        :joins    => :comments,
        :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'",
        :limit      => 2
      )
      assert_equal 2, posts.size

      count = Post.count(
        :joins    => [ :comments, :author ],
        :conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')",
        :limit      => 2
      )
      assert_equal count, posts.size
    end
  end

  def test_ar_join_with_scoped_order_using_association_limiting_without_explicit_scope
    posts_with_explicit_order = Post.find(:all, :conditions => 'comments.id is not null', :joins => :comments, :order => 'posts.id DESC', :limit => 2)
    posts_with_scoped_order = Post.with_scope(:find => {:order => 'posts.id DESC'}) do
      Post.find(:all, :conditions => 'comments.id is not null', :joins => :comments, :limit => 2)
    end
    assert_equal posts_with_explicit_order, posts_with_scoped_order
  end

  def test_scoped_find_include
    # with the include, will retrieve only developers for the given project
    scoped_developers = Developer.with_scope(:find => { :joins => :projects }) do
      Developer.find(:all, :conditions => 'projects.id = 2')
    end
    assert scoped_developers.include?(developers(:david))
    assert !scoped_developers.include?(developers(:jamis))
    assert_equal 1, scoped_developers.size
  end


  def test_nested_scoped_find_ar_join
    Developer.with_scope(:find => { :joins => :projects }) do
      Developer.with_scope(:find => { :conditions => "projects.id = 2" }) do
        assert_equal('David', Developer.find(:first).name)
      end
    end
  end

  def test_nested_scoped_find_merged_ar_join
    # :include's remain unique and don't "double up" when merging
    Developer.with_scope(:find => { :joins => :projects, :conditions => "projects.id = 2" }) do
      Developer.with_scope(:find => { :joins => :projects }) do
        assert_equal 1, Developer.instance_eval('current_scoped_methods')[:find][:ar_joins].length
        assert_equal('David', Developer.find(:first).name)
      end
    end
    # the nested scope doesn't remove the first :include
    Developer.with_scope(:find => { :joins => :projects, :conditions => "projects.id = 2" }) do
      Developer.with_scope(:find => { :joins => [] }) do
        assert_equal 1, Developer.instance_eval('current_scoped_methods')[:find][:ar_joins].length
        assert_equal('David', Developer.find(:first).name)
      end
    end
    # mixing array and symbol include's will merge correctly
    Developer.with_scope(:find => { :joins => [:projects], :conditions => "projects.id = 2" }) do
      Developer.with_scope(:find => { :joins => :projects }) do
        assert_equal 1, Developer.instance_eval('current_scoped_methods')[:find][:ar_joins].length
        assert_equal('David', Developer.find(:first).name)
      end
    end
  end

  def test_nested_scoped_find_replace_include
    Developer.with_scope(:find => { :joins => :projects }) do
      Developer.with_exclusive_scope(:find => { :joins => [] }) do
        assert_equal 0, Developer.instance_eval('current_scoped_methods')[:find][:ar_joins].length
      end
    end
  end

#
# Calculations
#
  def test_count_with_ar_joins
    assert_equal(2, Author.count(:joins => :posts, :conditions => ['posts.type = ?', "Post"]))
    assert_equal(1, Author.count(:joins => :posts, :conditions => ['posts.type = ?', "SpecialPost"]))
  end

  def test_should_get_maximum_of_field_with_joins
    assert_equal 50, Account.maximum(:credit_limit, :joins=> :firm, :conditions => "companies.name != 'Summit'")
  end

  def test_should_get_maximum_of_field_with_scoped_include
    Account.with_scope :find => { :joins => :firm, :conditions => "companies.name != 'Summit'" } do
      assert_equal 50, Account.maximum(:credit_limit)
    end
  end

  def test_should_not_modify_options_when_using_ar_joins_on_count
    options = {:conditions => 'companies.id > 1', :joins => :firm}
    options_copy = options.dup

    Account.count(:all, options)
    assert_equal options_copy, options
  end

end