will_paginate 2.1.0

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.

Potentially problematic release.


This version of will_paginate might be problematic. Click here for more details.

@@ -0,0 +1,131 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+ require 'will_paginate/core_ext'
3
+
4
+ class ArrayPaginationTest < Test::Unit::TestCase
5
+ def test_simple
6
+ collection = ('a'..'e').to_a
7
+
8
+ [{ :page => 1, :per_page => 3, :expected => %w( a b c ) },
9
+ { :page => 2, :per_page => 3, :expected => %w( d e ) },
10
+ { :page => 1, :per_page => 5, :expected => %w( a b c d e ) },
11
+ { :page => 3, :per_page => 5, :expected => [] },
12
+ ].
13
+ each do |conditions|
14
+ assert_equal conditions[:expected], collection.paginate(conditions.slice(:page, :per_page))
15
+ end
16
+ end
17
+
18
+ def test_defaults
19
+ result = (1..50).to_a.paginate
20
+ assert_equal 1, result.current_page
21
+ assert_equal 30, result.size
22
+ end
23
+
24
+ def test_deprecated_api
25
+ assert_deprecated 'paginate API' do
26
+ result = (1..50).to_a.paginate(2, 10)
27
+ assert_equal 2, result.current_page
28
+ assert_equal (11..20).to_a, result
29
+ assert_equal 50, result.total_entries
30
+ end
31
+
32
+ assert_deprecated { [].paginate nil }
33
+ end
34
+
35
+ def test_total_entries_has_precedence
36
+ result = %w(a b c).paginate :total_entries => 5
37
+ assert_equal 5, result.total_entries
38
+ end
39
+
40
+ def test_argument_error_with_params_and_another_argument
41
+ assert_raise ArgumentError do
42
+ [].paginate({}, 5)
43
+ end
44
+ end
45
+
46
+ def test_paginated_collection
47
+ entries = %w(a b c)
48
+ collection = create(2, 3, 10) do |pager|
49
+ assert_equal entries, pager.replace(entries)
50
+ end
51
+
52
+ assert_equal entries, collection
53
+ assert_respond_to_all collection, %w(page_count each offset size current_page per_page total_entries)
54
+ assert_kind_of Array, collection
55
+ assert_instance_of Array, collection.entries
56
+ assert_equal 3, collection.offset
57
+ assert_equal 4, collection.page_count
58
+ assert !collection.out_of_bounds?
59
+ end
60
+
61
+ def test_out_of_bounds
62
+ entries = create(2, 3, 2){}
63
+ assert entries.out_of_bounds?
64
+
65
+ entries = create(1, 3, 2){}
66
+ assert !entries.out_of_bounds?
67
+ end
68
+
69
+ def test_guessing_total_count
70
+ entries = create do |pager|
71
+ # collection is shorter than limit
72
+ pager.replace array
73
+ end
74
+ assert_equal 8, entries.total_entries
75
+
76
+ entries = create(2, 5, 10) do |pager|
77
+ # collection is shorter than limit, but we have an explicit count
78
+ pager.replace array
79
+ end
80
+ assert_equal 10, entries.total_entries
81
+
82
+ entries = create do |pager|
83
+ # collection is the same as limit; we can't guess
84
+ pager.replace array(5)
85
+ end
86
+ assert_equal nil, entries.total_entries
87
+
88
+ entries = create do |pager|
89
+ # collection is empty; we can't guess
90
+ pager.replace array(0)
91
+ end
92
+ assert_equal nil, entries.total_entries
93
+ end
94
+
95
+ def test_invalid_page
96
+ bad_input = [0, -1, nil, '', 'Schnitzel']
97
+
98
+ bad_input.each do |bad|
99
+ assert_raise(WillPaginate::InvalidPage) { create(bad) }
100
+ end
101
+ end
102
+
103
+ def test_invalid_per_page_setting
104
+ assert_raise(ArgumentError) { create(1, -1) }
105
+ end
106
+
107
+ private
108
+ def create(page = 2, limit = 5, total = nil, &block)
109
+ if block_given?
110
+ WillPaginate::Collection.create(page, limit, total, &block)
111
+ else
112
+ WillPaginate::Collection.new(page, limit, total)
113
+ end
114
+ end
115
+
116
+ def array(size = 3)
117
+ Array.new(size)
118
+ end
119
+
120
+ def collect_deprecations
121
+ old_behavior = WillPaginate::Deprecation.behavior
122
+ deprecations = []
123
+ WillPaginate::Deprecation.behavior = Proc.new do |message, callstack|
124
+ deprecations << message
125
+ end
126
+ result = yield
127
+ [result, deprecations]
128
+ ensure
129
+ WillPaginate::Deprecation.behavior = old_behavior
130
+ end
131
+ end
data/test/boot.rb ADDED
@@ -0,0 +1,23 @@
1
+ plugin_root = File.join(File.dirname(__FILE__), '..')
2
+ version = ENV['RAILS_VERSION']
3
+ version = nil if version and version == ""
4
+
5
+ # first look for a symlink to a copy of the framework
6
+ if !version and framework_root = ["#{plugin_root}/rails", "#{plugin_root}/../../rails"].find { |p| File.directory? p }
7
+ puts "found framework root: #{framework_root}"
8
+ # this allows for a plugin to be tested outside of an app and without Rails gems
9
+ $:.unshift "#{framework_root}/activesupport/lib", "#{framework_root}/activerecord/lib", "#{framework_root}/actionpack/lib"
10
+ else
11
+ # simply use installed gems if available
12
+ puts "using Rails#{version ? ' ' + version : nil} gems"
13
+ require 'rubygems'
14
+
15
+ if version
16
+ gem 'rails', version
17
+ else
18
+ gem 'actionpack'
19
+ gem 'activerecord'
20
+ end
21
+ end
22
+
23
+ $:.unshift "#{plugin_root}/lib"
data/test/console ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
3
+ libs = []
4
+ dirname = File.dirname(__FILE__)
5
+
6
+ libs << 'irb/completion'
7
+ libs << File.join(dirname, 'lib', 'load_fixtures')
8
+
9
+ exec "#{irb}#{libs.map{ |l| " -r #{l}" }.join} --simple-prompt"
@@ -0,0 +1,322 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+ require File.dirname(__FILE__) + '/lib/activerecord_test_case'
3
+
4
+ require 'will_paginate'
5
+ WillPaginate.enable_activerecord
6
+
7
+ class FinderTest < ActiveRecordTestCase
8
+ fixtures :topics, :replies, :users, :projects, :developers_projects
9
+
10
+ def test_new_methods_presence
11
+ assert_respond_to_all Topic, %w(per_page paginate paginate_by_sql)
12
+ end
13
+
14
+ def test_simple_paginate
15
+ entries = Topic.paginate :page => nil
16
+ assert_equal 1, entries.current_page
17
+ assert_nil entries.previous_page
18
+ assert_nil entries.next_page
19
+ assert_equal 1, entries.page_count
20
+ assert_equal 4, entries.size
21
+
22
+ entries = Topic.paginate :page => 2
23
+ assert_equal 2, entries.current_page
24
+ assert_equal 1, entries.previous_page
25
+ assert_equal 1, entries.page_count
26
+ assert entries.empty?
27
+ end
28
+
29
+ def test_parameter_api
30
+ # :page parameter in options is required!
31
+ assert_raise(ArgumentError){ Topic.paginate }
32
+ assert_raise(ArgumentError){ Topic.paginate({}) }
33
+
34
+ # explicit :all should not break anything
35
+ assert_equal Topic.paginate(:page => nil), Topic.paginate(:all, :page => 1)
36
+
37
+ # :count could be nil and we should still not cry
38
+ assert_nothing_raised { Topic.paginate :page => 1, :count => nil }
39
+ end
40
+
41
+ def test_paginate_with_per_page
42
+ entries = Topic.paginate :page => 1, :per_page => 1
43
+ assert_equal 1, entries.size
44
+ assert_equal 4, entries.page_count
45
+
46
+ # Developer class has explicit per_page at 10
47
+ entries = Developer.paginate :page => 1
48
+ assert_equal 10, entries.size
49
+ assert_equal 2, entries.page_count
50
+
51
+ entries = Developer.paginate :page => 1, :per_page => 5
52
+ assert_equal 11, entries.total_entries
53
+ assert_equal 5, entries.size
54
+ assert_equal 3, entries.page_count
55
+ end
56
+
57
+ def test_paginate_with_order
58
+ entries = Topic.paginate :page => 1, :order => 'created_at desc'
59
+ expected = [topics(:futurama), topics(:harvey_birdman), topics(:rails), topics(:ar)].reverse
60
+ assert_equal expected, entries.to_a
61
+ assert_equal 1, entries.page_count
62
+ end
63
+
64
+ def test_paginate_with_conditions
65
+ entries = Topic.paginate :page => 1, :conditions => ["created_at > ?", 30.minutes.ago]
66
+ expected = [topics(:rails), topics(:ar)]
67
+ assert_equal expected, entries.to_a
68
+ assert_equal 1, entries.page_count
69
+ end
70
+
71
+ def test_paginate_with_include_and_conditions
72
+ entries = Topic.paginate \
73
+ :page => 1,
74
+ :include => :replies,
75
+ :conditions => "replies.content LIKE 'Bird%' ",
76
+ :per_page => 10
77
+
78
+ expected = Topic.find :all,
79
+ :include => 'replies',
80
+ :conditions => "replies.content LIKE 'Bird%' ",
81
+ :limit => 10
82
+
83
+ assert_equal expected, entries.to_a
84
+ assert_equal 1, entries.total_entries
85
+ end
86
+
87
+ def test_paginate_with_include_and_order
88
+ entries = Topic.paginate \
89
+ :page => 1,
90
+ :include => :replies,
91
+ :order => 'replies.created_at asc, topics.created_at asc',
92
+ :per_page => 10
93
+
94
+ expected = Topic.find :all,
95
+ :include => 'replies',
96
+ :order => 'replies.created_at asc, topics.created_at asc',
97
+ :limit => 10
98
+
99
+ assert_equal expected, entries.to_a
100
+ assert_equal 4, entries.total_entries
101
+ end
102
+
103
+ def test_paginate_associations_with_include
104
+ entries, project = nil, projects(:active_record)
105
+
106
+ assert_nothing_raised "THIS IS A BUG in Rails 1.2.3 that was fixed in [7326]. " +
107
+ "Please upgrade to the 1-2-stable branch or edge Rails." do
108
+ entries = project.topics.paginate \
109
+ :page => 1,
110
+ :include => :replies,
111
+ :conditions => "replies.content LIKE 'Nice%' ",
112
+ :per_page => 10
113
+ end
114
+
115
+ expected = Topic.find :all,
116
+ :include => 'replies',
117
+ :conditions => "project_id = #{project.id} AND replies.content LIKE 'Nice%' ",
118
+ :limit => 10
119
+
120
+ assert_equal expected, entries.to_a
121
+ end
122
+
123
+ def test_paginate_associations
124
+ dhh = users :david
125
+ expected_name_ordered = [projects(:action_controller), projects(:active_record)]
126
+ expected_id_ordered = [projects(:active_record), projects(:action_controller)]
127
+
128
+ # with association-specified order
129
+ entries = dhh.projects.paginate(:page => 1)
130
+ assert_equal expected_name_ordered, entries
131
+ assert_equal 2, entries.total_entries
132
+
133
+ # with explicit order
134
+ entries = dhh.projects.paginate(:page => 1, :order => 'projects.id')
135
+ assert_equal expected_id_ordered, entries
136
+ assert_equal 2, entries.total_entries
137
+
138
+ assert_nothing_raised { dhh.projects.find(:all, :order => 'projects.id', :limit => 4) }
139
+ entries = dhh.projects.paginate(:page => 1, :order => 'projects.id', :per_page => 4)
140
+ assert_equal expected_id_ordered, entries
141
+
142
+ # has_many with implicit order
143
+ topic = Topic.find(1)
144
+ expected = [replies(:spam), replies(:witty_retort)]
145
+ assert_equal expected.map(&:id).sort, topic.replies.paginate(:page => 1).map(&:id).sort
146
+ assert_equal expected.reverse, topic.replies.paginate(:page => 1, :order => 'replies.id ASC')
147
+ end
148
+
149
+ def test_paginate_association_extension
150
+ project = Project.find(:first)
151
+ entries = project.replies.paginate_recent :page => 1
152
+ assert_equal [replies(:brave)], entries
153
+ end
154
+
155
+ def test_paginate_with_joins
156
+ entries = Developer.paginate :page => 1,
157
+ :joins => 'LEFT JOIN developers_projects ON users.id = developers_projects.developer_id',
158
+ :conditions => 'project_id = 1'
159
+ assert_equal 2, entries.size
160
+ developer_names = entries.map { |d| d.name }
161
+ assert developer_names.include?('David')
162
+ assert developer_names.include?('Jamis')
163
+
164
+ expected = entries.to_a
165
+ entries = Developer.paginate :page => 1,
166
+ :joins => 'LEFT JOIN developers_projects ON users.id = developers_projects.developer_id',
167
+ :conditions => 'project_id = 1', :count => { :select => "users.id" }
168
+ assert_equal expected, entries.to_a
169
+ end
170
+
171
+ def test_paginate_with_group
172
+ entries = Developer.paginate :page => 1, :per_page => 10,
173
+ :group => 'salary', :select => 'salary', :order => 'salary'
174
+ expected = [ users(:david), users(:jamis), users(:dev_10), users(:poor_jamis) ].map(&:salary).sort
175
+ assert_equal expected, entries.map(&:salary)
176
+ end
177
+
178
+ def test_paginate_with_dynamic_finder
179
+ expected = [replies(:witty_retort), replies(:spam)]
180
+ assert_equal expected, Reply.paginate_by_topic_id(1, :page => 1)
181
+
182
+ entries = Developer.paginate :conditions => { :salary => 100000 }, :page => 1, :per_page => 5
183
+ assert_equal 8, entries.total_entries
184
+ assert_equal entries, Developer.paginate_by_salary(100000, :page => 1, :per_page => 5)
185
+
186
+ # dynamic finder + conditions
187
+ entries = Developer.paginate_by_salary(100000, :page => 1,
188
+ :conditions => ['id > ?', 6])
189
+ assert_equal 4, entries.total_entries
190
+ assert_equal (7..10).to_a, entries.map(&:id)
191
+
192
+ assert_raises NoMethodError do
193
+ Developer.paginate_by_inexistent_attribute 100000, :page => 1
194
+ end
195
+ end
196
+
197
+ def test_scoped_paginate
198
+ entries = Developer.with_poor_ones { Developer.paginate :page => 1 }
199
+
200
+ assert_equal 2, entries.size
201
+ assert_equal 2, entries.total_entries
202
+ end
203
+
204
+ def test_readonly
205
+ assert_nothing_raised { Developer.paginate :readonly => true, :page => 1 }
206
+ end
207
+
208
+ # this functionality is temporarily removed
209
+ def xtest_pagination_defines_method
210
+ pager = "paginate_by_created_at"
211
+ assert !User.methods.include?(pager), "User methods should not include `#{pager}` method"
212
+ # paginate!
213
+ assert 0, User.send(pager, nil, :page => 1).total_entries
214
+ # the paging finder should now be defined
215
+ assert User.methods.include?(pager), "`#{pager}` method should be defined on User"
216
+ end
217
+
218
+ # Is this Rails 2.0? Find out by testing find_all which was removed in [6998]
219
+ unless Developer.respond_to? :find_all
220
+ def test_paginate_array_of_ids
221
+ # AR finders also accept arrays of IDs
222
+ # (this was broken in Rails before [6912])
223
+ entries = Developer.paginate((1..8).to_a, :per_page => 3, :page => 2, :order => 'id')
224
+ assert_equal (4..6).to_a, entries.map(&:id)
225
+ assert_equal 8, entries.total_entries
226
+ end
227
+ end
228
+
229
+ uses_mocha 'internals' do
230
+ def test_implicit_all_with_dynamic_finders
231
+ Topic.expects(:find_all_by_foo).returns([])
232
+ Topic.expects(:count).returns(0)
233
+ Topic.paginate_by_foo :page => 1
234
+ end
235
+
236
+ def test_guessing_the_total_count
237
+ Topic.expects(:find).returns(Array.new(2))
238
+ Topic.expects(:count).never
239
+
240
+ entries = Topic.paginate :page => 2, :per_page => 4
241
+ assert_equal 6, entries.total_entries
242
+ end
243
+
244
+ def test_extra_parameters_stay_untouched
245
+ Topic.expects(:find).with(:all, {:foo => 'bar', :limit => 4, :offset => 0 }).returns(Array.new(5))
246
+ Topic.expects(:count).with({:foo => 'bar'}).returns(1)
247
+
248
+ Topic.paginate :foo => 'bar', :page => 1, :per_page => 4
249
+ end
250
+
251
+ def test_count_skips_select
252
+ Developer.stubs(:find).returns([])
253
+ Developer.expects(:count).with({}).returns(0)
254
+ Developer.paginate :select => 'salary', :page => 1
255
+ end
256
+
257
+ def test_count_select_when_distinct
258
+ Developer.stubs(:find).returns([])
259
+ Developer.expects(:count).with(:select => 'DISTINCT salary').returns(0)
260
+ Developer.paginate :select => 'DISTINCT salary', :page => 1
261
+ end
262
+
263
+ def test_should_use_scoped_finders_if_present
264
+ # scope-out compatibility
265
+ Topic.expects(:find_best).returns(Array.new(5))
266
+ Topic.expects(:with_best).returns(1)
267
+
268
+ Topic.paginate_best :page => 1, :per_page => 4
269
+ end
270
+
271
+ def test_paginate_by_sql
272
+ assert_respond_to Developer, :paginate_by_sql
273
+ Developer.expects(:find_by_sql).with(regexp_matches(/sql LIMIT 3(,| OFFSET) 3/)).returns([])
274
+ Developer.expects(:count_by_sql).with('SELECT COUNT(*) FROM (sql) AS count_table').returns(0)
275
+
276
+ entries = Developer.paginate_by_sql 'sql', :page => 2, :per_page => 3
277
+ end
278
+
279
+ def test_paginate_by_sql_respects_total_entries_setting
280
+ Developer.expects(:find_by_sql).returns([])
281
+ Developer.expects(:count_by_sql).never
282
+
283
+ entries = Developer.paginate_by_sql 'sql', :page => 1, :total_entries => 999
284
+ assert_equal 999, entries.total_entries
285
+ end
286
+
287
+ def test_paginate_by_sql_strips_order_by_when_counting
288
+ Developer.expects(:find_by_sql).returns([])
289
+ Developer.expects(:count_by_sql).with("SELECT COUNT(*) FROM (sql\n ) AS count_table").returns(0)
290
+
291
+ entries = Developer.paginate_by_sql "sql\n ORDER\nby foo, bar, `baz` ASC", :page => 1
292
+ end
293
+
294
+ # TODO: counts are still wrong
295
+ def test_ability_to_use_with_custom_finders
296
+ # acts_as_taggable defines find_tagged_with(tag, options)
297
+ Topic.expects(:find_tagged_with).with('will_paginate', :offset => 0, :limit => 5).returns([])
298
+ Topic.expects(:count).with({}).returns(0)
299
+
300
+ Topic.paginate_tagged_with 'will_paginate', :page => 1, :per_page => 5
301
+ end
302
+
303
+ def test_array_argument_doesnt_eliminate_count
304
+ ids = (1..8).to_a
305
+ Developer.expects(:find_all_by_id).returns([])
306
+ Developer.expects(:count).returns(0)
307
+
308
+ Developer.paginate_by_id(ids, :per_page => 3, :page => 2, :order => 'id')
309
+ end
310
+
311
+ def test_paginating_finder_doesnt_mangle_options
312
+ Developer.expects(:find).returns([])
313
+ Developer.expects(:count).returns(0)
314
+ options = { :page => 1 }
315
+ options.expects(:delete).never
316
+ options_before = options.dup
317
+
318
+ Developer.paginate(options)
319
+ assert_equal options, options_before
320
+ end
321
+ end
322
+ end
@@ -0,0 +1,3 @@
1
+ class Admin < User
2
+ has_many :companies, :finder_sql => 'SELECT * FROM companies'
3
+ end
@@ -0,0 +1,11 @@
1
+ class Developer < User
2
+ has_and_belongs_to_many :projects, :include => :topics, :order => 'projects.name'
3
+
4
+ def self.with_poor_ones(&block)
5
+ with_scope :find => { :conditions => ['salary <= ?', 80000], :order => 'salary' } do
6
+ yield
7
+ end
8
+ end
9
+
10
+ def self.per_page() 10 end
11
+ end
@@ -0,0 +1,13 @@
1
+ david_action_controller:
2
+ developer_id: 1
3
+ project_id: 2
4
+ joined_on: 2004-10-10
5
+
6
+ david_active_record:
7
+ developer_id: 1
8
+ project_id: 1
9
+ joined_on: 2004-10-10
10
+
11
+ jamis_active_record:
12
+ developer_id: 2
13
+ project_id: 1
@@ -0,0 +1,15 @@
1
+ class Project < ActiveRecord::Base
2
+ has_and_belongs_to_many :developers, :uniq => true
3
+
4
+ has_many :topics
5
+ # :finder_sql => 'SELECT * FROM topics WHERE (topics.project_id = #{id})',
6
+ # :counter_sql => 'SELECT COUNT(*) FROM topics WHERE (topics.project_id = #{id})'
7
+
8
+ has_many :replies, :through => :topics do
9
+ def find_recent(params = {})
10
+ with_scope :find => { :conditions => ['replies.created_at > ?', 15.minutes.ago] } do
11
+ find :all, params
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ action_controller:
2
+ id: 2
3
+ name: Active Controller
4
+
5
+ active_record:
6
+ id: 1
7
+ name: Active Record
@@ -0,0 +1,29 @@
1
+ witty_retort:
2
+ id: 1
3
+ topic_id: 1
4
+ content: Birdman is better!
5
+ created_at: <%= 6.hours.ago.to_s(:db) %>
6
+
7
+ another:
8
+ id: 2
9
+ topic_id: 2
10
+ content: Nuh uh!
11
+ created_at: <%= 1.hour.ago.to_s(:db) %>
12
+
13
+ spam:
14
+ id: 3
15
+ topic_id: 1
16
+ content: Nice site!
17
+ created_at: <%= 1.hour.ago.to_s(:db) %>
18
+
19
+ decisive:
20
+ id: 4
21
+ topic_id: 4
22
+ content: "I'm getting to the bottom of this"
23
+ created_at: <%= 30.minutes.ago.to_s(:db) %>
24
+
25
+ brave:
26
+ id: 5
27
+ topic_id: 4
28
+ content: "AR doesn't scare me a bit"
29
+ created_at: <%= 10.minutes.ago.to_s(:db) %>
@@ -0,0 +1,5 @@
1
+ class Reply < ActiveRecord::Base
2
+ belongs_to :topic, :include => [:replies]
3
+
4
+ validates_presence_of :content
5
+ end
@@ -0,0 +1,38 @@
1
+ ActiveRecord::Schema.define do
2
+
3
+ create_table "users", :force => true do |t|
4
+ t.column "name", :text
5
+ t.column "salary", :integer, :default => 70000
6
+ t.column "created_at", :datetime
7
+ t.column "updated_at", :datetime
8
+ t.column "type", :text
9
+ end
10
+
11
+ create_table "projects", :force => true do |t|
12
+ t.column "name", :text
13
+ end
14
+
15
+ create_table "developers_projects", :id => false, :force => true do |t|
16
+ t.column "developer_id", :integer, :null => false
17
+ t.column "project_id", :integer, :null => false
18
+ t.column "joined_on", :date
19
+ t.column "access_level", :integer, :default => 1
20
+ end
21
+
22
+ create_table "topics", :force => true do |t|
23
+ t.column "project_id", :integer
24
+ t.column "title", :string
25
+ t.column "subtitle", :string
26
+ t.column "content", :text
27
+ t.column "created_at", :datetime
28
+ t.column "updated_at", :datetime
29
+ end
30
+
31
+ create_table "replies", :force => true do |t|
32
+ t.column "content", :text
33
+ t.column "created_at", :datetime
34
+ t.column "updated_at", :datetime
35
+ t.column "topic_id", :integer
36
+ end
37
+
38
+ end
@@ -0,0 +1,4 @@
1
+ class Topic < ActiveRecord::Base
2
+ has_many :replies, :dependent => :destroy, :order => 'replies.created_at DESC'
3
+ belongs_to :project
4
+ end
@@ -0,0 +1,30 @@
1
+ futurama:
2
+ id: 1
3
+ title: Isnt futurama awesome?
4
+ subtitle: It really is, isnt it.
5
+ content: I like futurama
6
+ created_at: <%= 1.day.ago.to_s(:db) %>
7
+ updated_at:
8
+
9
+ harvey_birdman:
10
+ id: 2
11
+ title: Harvey Birdman is the king of all men
12
+ subtitle: yup
13
+ content: He really is
14
+ created_at: <%= 2.hours.ago.to_s(:db) %>
15
+ updated_at:
16
+
17
+ rails:
18
+ id: 3
19
+ project_id: 1
20
+ title: Rails is nice
21
+ subtitle: It makes me happy
22
+ content: except when I have to hack internals to fix pagination. even then really.
23
+ created_at: <%= 20.minutes.ago.to_s(:db) %>
24
+
25
+ ar:
26
+ id: 4
27
+ project_id: 1
28
+ title: ActiveRecord sometimes freaks me out
29
+ content: "I mean, what's the deal with eager loading?"
30
+ created_at: <%= 15.minutes.ago.to_s(:db) %>
@@ -0,0 +1,2 @@
1
+ class User < ActiveRecord::Base
2
+ end
@@ -0,0 +1,35 @@
1
+ david:
2
+ id: 1
3
+ name: David
4
+ salary: 80000
5
+ type: Developer
6
+
7
+ jamis:
8
+ id: 2
9
+ name: Jamis
10
+ salary: 150000
11
+ type: Developer
12
+
13
+ <% for digit in 3..10 %>
14
+ dev_<%= digit %>:
15
+ id: <%= digit %>
16
+ name: fixture_<%= digit %>
17
+ salary: 100000
18
+ type: Developer
19
+ <% end %>
20
+
21
+ poor_jamis:
22
+ id: 11
23
+ name: Jamis
24
+ salary: 9000
25
+ type: Developer
26
+
27
+ admin:
28
+ id: 12
29
+ name: admin
30
+ type: Admin
31
+
32
+ goofy:
33
+ id: 13
34
+ name: Goofy
35
+ type: Admin