pagify 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +42 -0
- data/LICENSE +201 -0
- data/NOTICE +5 -0
- data/README +135 -0
- data/Rakefile +54 -0
- data/TODO +12 -0
- data/lib/pagify.rb +14 -0
- data/lib/pagify/active_record.rb +17 -0
- data/lib/pagify/array.rb +6 -0
- data/lib/pagify/data_mapper.rb +8 -0
- data/lib/pagify/helper/abstract.rb +112 -0
- data/lib/pagify/helper/detail/setting.rb +54 -0
- data/lib/pagify/helper/detail/setup.rb +23 -0
- data/lib/pagify/helper/html.rb +86 -0
- data/lib/pagify/helper/rails.rb +23 -0
- data/lib/pagify/page/basic.rb +56 -0
- data/lib/pagify/page/null.rb +10 -0
- data/lib/pagify/pager/active_record.rb +30 -0
- data/lib/pagify/pager/array.rb +21 -0
- data/lib/pagify/pager/basic.rb +114 -0
- data/lib/pagify/pager/data_mapper.rb +29 -0
- data/lib/pagify/pager/detail/page_accept_string_or_blank.rb +13 -0
- data/lib/pagify/pager/null.rb +15 -0
- data/lib/pagify/pagifier/abstract.rb +10 -0
- data/lib/pagify/pagifier/active_record.rb +11 -0
- data/lib/pagify/pagifier/array.rb +9 -0
- data/lib/pagify/pagifier/data_mapper.rb +11 -0
- data/lib/pagify/version.rb +4 -0
- data/pagify.gemspec +43 -0
- data/spec/pagify_spec.rb +8 -0
- data/spec/spec_helper.rb +17 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +292 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- data/tasks/zentest.rake +36 -0
- data/test/helper.rb +26 -0
- data/test/helper_model.rb +83 -0
- data/test/helper_pagify.rb +39 -0
- data/test/test_active_record.rb +66 -0
- data/test/test_array.rb +19 -0
- data/test/test_basic.rb +22 -0
- data/test/test_data_mapper.rb +56 -0
- data/test/test_html.rb +186 -0
- data/test/test_null.rb +31 -0
- data/test/test_rails.rb +32 -0
- metadata +163 -0
data/tasks/spec.rake
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
|
2
|
+
if HAVE_SPEC_RAKE_SPECTASK and not PROJ.spec.files.to_a.empty?
|
3
|
+
require 'spec/rake/verify_rcov'
|
4
|
+
|
5
|
+
namespace :spec do
|
6
|
+
|
7
|
+
desc 'Run all specs with basic output'
|
8
|
+
Spec::Rake::SpecTask.new(:run) do |t|
|
9
|
+
t.ruby_opts = PROJ.ruby_opts
|
10
|
+
t.spec_opts = PROJ.spec.opts
|
11
|
+
t.spec_files = PROJ.spec.files
|
12
|
+
t.libs += PROJ.libs
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Run all specs with text output'
|
16
|
+
Spec::Rake::SpecTask.new(:specdoc) do |t|
|
17
|
+
t.ruby_opts = PROJ.ruby_opts
|
18
|
+
t.spec_opts = PROJ.spec.opts + ['--format', 'specdoc']
|
19
|
+
t.spec_files = PROJ.spec.files
|
20
|
+
t.libs += PROJ.libs
|
21
|
+
end
|
22
|
+
|
23
|
+
if HAVE_RCOV
|
24
|
+
desc 'Run all specs with RCov'
|
25
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
26
|
+
t.ruby_opts = PROJ.ruby_opts
|
27
|
+
t.spec_opts = PROJ.spec.opts
|
28
|
+
t.spec_files = PROJ.spec.files
|
29
|
+
t.libs += PROJ.libs
|
30
|
+
t.rcov = true
|
31
|
+
t.rcov_dir = PROJ.rcov.dir
|
32
|
+
t.rcov_opts = PROJ.rcov.opts + ['--exclude', 'spec']
|
33
|
+
end
|
34
|
+
|
35
|
+
RCov::VerifyTask.new(:verify) do |t|
|
36
|
+
t.threshold = PROJ.rcov.threshold
|
37
|
+
t.index_html = File.join(PROJ.rcov.dir, 'index.html')
|
38
|
+
t.require_exact_threshold = PROJ.rcov.threshold_exact
|
39
|
+
end
|
40
|
+
|
41
|
+
task :verify => :rcov
|
42
|
+
remove_desc_for_task %w(spec:clobber_rcov)
|
43
|
+
end
|
44
|
+
|
45
|
+
end # namespace :spec
|
46
|
+
|
47
|
+
desc 'Alias to spec:run'
|
48
|
+
task :spec => 'spec:run'
|
49
|
+
|
50
|
+
task :clobber => 'spec:clobber_rcov' if HAVE_RCOV
|
51
|
+
|
52
|
+
end # if HAVE_SPEC_RAKE_SPECTASK
|
53
|
+
|
54
|
+
# EOF
|
data/tasks/svn.rake
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
if HAVE_SVN
|
3
|
+
|
4
|
+
unless PROJ.svn.root
|
5
|
+
info = %x/svn info ./
|
6
|
+
m = %r/^Repository Root:\s+(.*)$/.match(info)
|
7
|
+
PROJ.svn.root = (m.nil? ? '' : m[1])
|
8
|
+
end
|
9
|
+
PROJ.svn.root = File.join(PROJ.svn.root, PROJ.svn.path) unless PROJ.svn.path.empty?
|
10
|
+
|
11
|
+
namespace :svn do
|
12
|
+
|
13
|
+
# A prerequisites task that all other tasks depend upon
|
14
|
+
task :prereqs
|
15
|
+
|
16
|
+
desc 'Show tags from the SVN repository'
|
17
|
+
task :show_tags => 'svn:prereqs' do |t|
|
18
|
+
tags = %x/svn list #{File.join(PROJ.svn.root, PROJ.svn.tags)}/
|
19
|
+
tags.gsub!(%r/\/$/, '')
|
20
|
+
tags = tags.split("\n").sort {|a,b| b <=> a}
|
21
|
+
puts tags
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'Create a new tag in the SVN repository'
|
25
|
+
task :create_tag => 'svn:prereqs' do |t|
|
26
|
+
v = ENV['VERSION'] or abort 'Must supply VERSION=x.y.z'
|
27
|
+
abort "Versions don't match #{v} vs #{PROJ.version}" if v != PROJ.version
|
28
|
+
|
29
|
+
svn = PROJ.svn
|
30
|
+
trunk = File.join(svn.root, svn.trunk)
|
31
|
+
tag = "%s-%s" % [PROJ.name, PROJ.version]
|
32
|
+
tag = File.join(svn.root, svn.tags, tag)
|
33
|
+
msg = "Creating tag for #{PROJ.name} version #{PROJ.version}"
|
34
|
+
|
35
|
+
puts "Creating SVN tag '#{tag}'"
|
36
|
+
unless system "svn cp -m '#{msg}' #{trunk} #{tag}"
|
37
|
+
abort "Tag creation failed"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end # namespace :svn
|
42
|
+
|
43
|
+
task 'gem:release' => 'svn:create_tag'
|
44
|
+
|
45
|
+
end # if PROJ.svn.path
|
46
|
+
|
47
|
+
# EOF
|
data/tasks/test.rake
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
if test(?e, PROJ.test.file) or not PROJ.test.files.to_a.empty?
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
namespace :test do
|
6
|
+
|
7
|
+
Rake::TestTask.new(:run) do |t|
|
8
|
+
t.libs = PROJ.libs
|
9
|
+
t.test_files = if test(?f, PROJ.test.file) then [PROJ.test.file]
|
10
|
+
else PROJ.test.files end
|
11
|
+
t.ruby_opts += PROJ.ruby_opts
|
12
|
+
t.ruby_opts += PROJ.test.opts
|
13
|
+
end
|
14
|
+
|
15
|
+
if HAVE_RCOV
|
16
|
+
desc 'Run rcov on the unit tests'
|
17
|
+
task :rcov => :clobber_rcov do
|
18
|
+
opts = PROJ.rcov.opts.dup << '-o' << PROJ.rcov.dir
|
19
|
+
opts = opts.join(' ')
|
20
|
+
files = if test(?f, PROJ.test.file) then [PROJ.test.file]
|
21
|
+
else PROJ.test.files end
|
22
|
+
files = files.join(' ')
|
23
|
+
sh "#{RCOV} #{files} #{opts}"
|
24
|
+
end
|
25
|
+
|
26
|
+
task :clobber_rcov do
|
27
|
+
rm_r 'coverage' rescue nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end # namespace :test
|
32
|
+
|
33
|
+
desc 'Alias to test:run'
|
34
|
+
task :test => 'test:run'
|
35
|
+
|
36
|
+
task :clobber => 'test:clobber_rcov' if HAVE_RCOV
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
# EOF
|
data/tasks/zentest.rake
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
if HAVE_ZENTEST
|
2
|
+
|
3
|
+
# --------------------------------------------------------------------------
|
4
|
+
if test(?e, PROJ.test.file) or not PROJ.test.files.to_a.empty?
|
5
|
+
require 'autotest'
|
6
|
+
|
7
|
+
namespace :test do
|
8
|
+
task :autotest do
|
9
|
+
Autotest.run
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Run the autotest loop"
|
14
|
+
task :autotest => 'test:autotest'
|
15
|
+
|
16
|
+
end # if test
|
17
|
+
|
18
|
+
# --------------------------------------------------------------------------
|
19
|
+
if HAVE_SPEC_RAKE_SPECTASK and not PROJ.spec.files.to_a.empty?
|
20
|
+
require 'autotest/rspec'
|
21
|
+
|
22
|
+
namespace :spec do
|
23
|
+
task :autotest do
|
24
|
+
load '.autotest' if test(?f, '.autotest')
|
25
|
+
Autotest::Rspec.run
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "Run the autotest loop"
|
30
|
+
task :autotest => 'spec:autotest'
|
31
|
+
|
32
|
+
end # if rspec
|
33
|
+
|
34
|
+
end # if HAVE_ZENTEST
|
35
|
+
|
36
|
+
# EOF
|
data/test/helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
TestCase = begin
|
5
|
+
require 'minitest/unit'
|
6
|
+
MiniTest::Unit.autorun
|
7
|
+
MiniTest::Unit::TestCase
|
8
|
+
rescue LoadError
|
9
|
+
require 'test/unit'
|
10
|
+
Test::Unit::TestCase
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'pagify'
|
14
|
+
#gem 'dm-core', '<0.10'
|
15
|
+
#gem 'dm-aggregates', '<0.10'
|
16
|
+
require 'dm-core'
|
17
|
+
require 'dm-aggregates'
|
18
|
+
require 'active_record'
|
19
|
+
|
20
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('1.8.7')
|
21
|
+
class Symbol
|
22
|
+
def to_proc
|
23
|
+
lambda{ |*args| args.shift.__send__(self, *args) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
|
2
|
+
module SuiteForModel
|
3
|
+
|
4
|
+
def test_page_correctness_fixnum
|
5
|
+
page_correctness 1
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_page_correctness_string
|
9
|
+
page_correctness '1'
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_nil_page_default_page_1
|
13
|
+
users = send(:User).pagify :page => nil, :per_page => 2
|
14
|
+
assert_equal 2, users.pager.size
|
15
|
+
assert_equal 1, users.page
|
16
|
+
end
|
17
|
+
|
18
|
+
def page_correctness page
|
19
|
+
users = send(:User).pagify :page => page, :per_page => 2
|
20
|
+
|
21
|
+
assert_equal 2, users.pager.size
|
22
|
+
assert_equal 1, users.page
|
23
|
+
assert_equal send(:User).first, users.first
|
24
|
+
assert_equal 2, users.size
|
25
|
+
assert_equal send(:User).first(:offset => 2, :limit => 1), users.next.first
|
26
|
+
assert_equal 1, users.next.size
|
27
|
+
assert_equal Pagify::NullPage.new(users.pager), users.next.next
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_condition_chain
|
31
|
+
users_A = send(:User).all(:conditions => ['name = ?', 'A']).pagify :page => 1, :per_page => 1
|
32
|
+
assert_equal 1, users_A.size
|
33
|
+
assert_equal 2, users_A.pager.entries_count
|
34
|
+
assert_equal 2, users_A.pager.size # pages
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_association_pagify
|
38
|
+
user = send(:User).first
|
39
|
+
user.pets.push(*send(:Pet).all)
|
40
|
+
assert user.save
|
41
|
+
assert_equal 3, user.pets.count
|
42
|
+
|
43
|
+
page = all_pets_with_name_godfat(user).pagify :page => 2, :per_page => 1
|
44
|
+
assert_equal 1, page.size
|
45
|
+
assert_equal 2, page.pager.size
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.included test_case
|
49
|
+
test_case.module_eval do
|
50
|
+
# due to ruby const lookup is different from method lookup
|
51
|
+
def User; self.class.const_get(:User); end
|
52
|
+
def Pet; self.class.const_get(:Pet); end
|
53
|
+
end
|
54
|
+
|
55
|
+
test_case.const_get(:User).module_eval do
|
56
|
+
create :name => 'A'
|
57
|
+
create :name => 'A'
|
58
|
+
create :name => 'B'
|
59
|
+
end
|
60
|
+
|
61
|
+
test_case.const_get(:Pet).module_eval do
|
62
|
+
create :name => 'Qoo'
|
63
|
+
create :name => 'godfat'
|
64
|
+
create :name => 'godfat'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# include Extlib::Hook
|
69
|
+
#
|
70
|
+
# private
|
71
|
+
# def i_give_up
|
72
|
+
# if self.class == TestActiveRecord
|
73
|
+
# skip "it's toooooo hard to implement this for active record!! patch wanted!"
|
74
|
+
# end
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# [:test_same_pager_with_same_opts,
|
78
|
+
# :test_page_correctness,
|
79
|
+
# :test_condition_chain].each{ |test|
|
80
|
+
# before test.to_sym, :i_give_up
|
81
|
+
# }
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
class TestPagify < TestCase
|
3
|
+
def self.data; @data ||= (0..100).to_a; end
|
4
|
+
def for_pager pager
|
5
|
+
# assume data.size is 101, data is [0,1,2,3...]
|
6
|
+
pager.per_page = 10
|
7
|
+
assert_equal 11, pager.size
|
8
|
+
|
9
|
+
null_page = Pagify::NullPage.new(pager)
|
10
|
+
|
11
|
+
assert_equal null_page, pager[0]
|
12
|
+
assert_equal((0..9).to_a, pager.page(1).to_a)
|
13
|
+
assert_equal((10..19).to_a, pager[2].to_a)
|
14
|
+
assert_equal(20, pager.page(3).first)
|
15
|
+
assert_equal((90..99).to_a, pager[10].to_a)
|
16
|
+
assert_equal([100], pager.page(11).to_a)
|
17
|
+
assert_equal null_page, pager.page(12)
|
18
|
+
|
19
|
+
assert_equal(pager[1], pager[2].prev)
|
20
|
+
assert_equal(pager.page(11), pager[10].next)
|
21
|
+
assert_equal null_page, pager[1].prev
|
22
|
+
assert_equal Pagify::NullPage.new(pager), pager[10].next.next
|
23
|
+
|
24
|
+
assert_equal pager[4].data, pager[4].fetch
|
25
|
+
assert_equal(pager[1], pager.pages.first)
|
26
|
+
assert_equal(pager[2], pager.to_a[1])
|
27
|
+
assert_equal(5050, pager.inject(0){|r, i| r += i.inject(&:+) })
|
28
|
+
|
29
|
+
assert_equal 4, pager[4].page
|
30
|
+
|
31
|
+
assert_equal 10, pager[2].begin
|
32
|
+
assert_equal 19, pager[2].end
|
33
|
+
assert_equal 100, pager[11].end
|
34
|
+
|
35
|
+
pager.null_page = false
|
36
|
+
|
37
|
+
assert_nil pager[12]
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
|
2
|
+
require 'test/helper'
|
3
|
+
require 'test/helper_pagify'
|
4
|
+
require 'test/helper_model'
|
5
|
+
|
6
|
+
require 'pagify/active_record'
|
7
|
+
|
8
|
+
class TestActiveRecord < TestPagify
|
9
|
+
def test_for_active_record
|
10
|
+
for_pager Pagify::ActiveRecordPager.new(Topic)
|
11
|
+
end
|
12
|
+
|
13
|
+
class Topic
|
14
|
+
class << self
|
15
|
+
def count opts = {}
|
16
|
+
101
|
17
|
+
end
|
18
|
+
def find all, opts = {}
|
19
|
+
TestPagify.data[opts[:offset], opts[:limit]]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
DataMapper.setup(:active_record, 'sqlite3:tmp/active_record.sqlite3')
|
25
|
+
|
26
|
+
class UserForActiveRecord
|
27
|
+
include DataMapper::Resource
|
28
|
+
def self.default_repository_name
|
29
|
+
:active_record
|
30
|
+
end
|
31
|
+
property :id, Serial
|
32
|
+
property :name, String
|
33
|
+
storage_names[default_repository_name] = 'users'
|
34
|
+
auto_migrate!
|
35
|
+
end
|
36
|
+
|
37
|
+
class PetForActiveRecord
|
38
|
+
include DataMapper::Resource
|
39
|
+
def self.default_repository_name
|
40
|
+
:active_record
|
41
|
+
end
|
42
|
+
property :id, Serial
|
43
|
+
property :name, String
|
44
|
+
property :user_id, Integer, :nullable => true
|
45
|
+
storage_names[default_repository_name] = 'pets'
|
46
|
+
auto_migrate!
|
47
|
+
end
|
48
|
+
|
49
|
+
ActiveRecord::Base.establish_connection(
|
50
|
+
:adapter => 'sqlite3', :database => 'tmp/active_record.sqlite3')
|
51
|
+
|
52
|
+
class User < ActiveRecord::Base
|
53
|
+
has_many :pets
|
54
|
+
end
|
55
|
+
|
56
|
+
class Pet < ActiveRecord::Base
|
57
|
+
belongs_to :user
|
58
|
+
end
|
59
|
+
|
60
|
+
include SuiteForModel
|
61
|
+
|
62
|
+
def all_pets_with_name_godfat user
|
63
|
+
user.pets.all(:conditions => ['name = ?', 'godfat'])
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
data/test/test_array.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
require 'test/helper'
|
3
|
+
require 'test/helper_pagify'
|
4
|
+
|
5
|
+
class TestArray < TestPagify
|
6
|
+
def test_offset_bug
|
7
|
+
a = (0..9).to_a
|
8
|
+
pager = Pagify::ArrayPager.new a
|
9
|
+
pager.per_page = 5
|
10
|
+
assert_equal 5, pager[1].size
|
11
|
+
assert_equal 5, pager[2].size
|
12
|
+
assert_equal Pagify::NullPage.new(pager), pager[3]
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_for_array
|
16
|
+
for_pager Pagify::ArrayPager.new(TestPagify.data)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
data/test/test_basic.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
require 'test/helper'
|
3
|
+
require 'test/helper_pagify'
|
4
|
+
|
5
|
+
class TestBasic < TestPagify
|
6
|
+
def test_basic
|
7
|
+
pager = Pagify::BasicPager.new(
|
8
|
+
:fetcher => lambda{ |offset, per_page|
|
9
|
+
# if for rails,
|
10
|
+
# Data.find :all, :offset => offset, :limit => per_page
|
11
|
+
TestPagify.data[offset, per_page]
|
12
|
+
},
|
13
|
+
:counter => lambda{
|
14
|
+
# if for rails,
|
15
|
+
# Data.count
|
16
|
+
TestPagify.data.size
|
17
|
+
})
|
18
|
+
|
19
|
+
for_pager pager
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
|
2
|
+
require 'test/helper'
|
3
|
+
require 'test/helper_pagify'
|
4
|
+
require 'test/helper_model'
|
5
|
+
|
6
|
+
require 'pagify/data_mapper'
|
7
|
+
|
8
|
+
class TestDataMapper < TestPagify
|
9
|
+
def test_for_data_mapper
|
10
|
+
for_pager Pagify::DataMapperPager.new(Topic)
|
11
|
+
end
|
12
|
+
|
13
|
+
class Topic
|
14
|
+
class << self
|
15
|
+
def count opts = {}
|
16
|
+
101
|
17
|
+
end
|
18
|
+
def all opts = {}
|
19
|
+
TestPagify.data[opts[:offset], opts[:limit]]
|
20
|
+
end
|
21
|
+
def query
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
private
|
25
|
+
def with_scope query
|
26
|
+
yield
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
DataMapper.setup(:default, 'sqlite3::memory:')
|
32
|
+
|
33
|
+
class User
|
34
|
+
include DataMapper::Resource
|
35
|
+
property :id, Serial
|
36
|
+
property :name, String
|
37
|
+
has n, :pets
|
38
|
+
end
|
39
|
+
|
40
|
+
class Pet
|
41
|
+
include DataMapper::Resource
|
42
|
+
property :id, Serial
|
43
|
+
property :name, String
|
44
|
+
belongs_to :user, :nullable => true
|
45
|
+
end
|
46
|
+
|
47
|
+
User.auto_migrate!
|
48
|
+
Pet.auto_migrate!
|
49
|
+
|
50
|
+
include SuiteForModel
|
51
|
+
|
52
|
+
def all_pets_with_name_godfat user
|
53
|
+
user.pets.all(:name => 'godfat')
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|