page_iterator 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +76 -0
- data/lib/page_iterator.rb +14 -10
- data/page_iterator.gemspec +5 -5
- metadata +6 -6
- data/Rakefile +0 -44
data/README.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# PageIterator
|
2
|
+
|
3
|
+
The idea is splitting a large number of data in small parts (pagination concept) and iterating through them, so the execution of your script, batch file, rake task and so on, can be better managed regarding CPU and memory.
|
4
|
+
The differential of **PageIterator** is that it keeps track of each iterated page in a log file. If the iteration was interrupted for any reason, the next execution of that iteration is going to start from the page it was previously interrupted.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
gem install page_iterator
|
9
|
+
|
10
|
+
### Usage
|
11
|
+
page_iterator = PageIterator.new(<NUMBER_OF_TOTAL_ITEMS>, <FILENAME_TO_LOG>)
|
12
|
+
|
13
|
+
page_iterator.each_remaining_page! do |page|
|
14
|
+
# do something here
|
15
|
+
end
|
16
|
+
|
17
|
+
### PageIterator Resources
|
18
|
+
* `page_iterator.each_remaining_page! { |page| }` - iterates through each page passing the current page number as parameter to the block
|
19
|
+
* `page_iterator.next!` - increments one page and logs it to filesystem. **PageIterator** execute it after each iteration
|
20
|
+
* `page_iterator.previous!` - decrement one page and logs it to filesystem.
|
21
|
+
* `page_iterator.total_pages` - total number of pages
|
22
|
+
* `page_iterator.remaining_items` - number of remaining items to be iterated through pages
|
23
|
+
* `page_iterator.remaining_pages` - range of remaining pages to be iterated
|
24
|
+
* `page_iterator.per_page` - number of items per page. Default: 50
|
25
|
+
|
26
|
+
|
27
|
+
### Limitations
|
28
|
+
There is plenty room for improvements, but so far **PageIterator** just splits the total number of items to be processed, gets page numbers and other valued numbers calculated from the initial data, but it doesn't iterate through the items themselves. It's still needed a pagination mechanism for the items.
|
29
|
+
|
30
|
+
|
31
|
+
### Real Life Usage Example
|
32
|
+
The example below shows **PageIterator** in action.
|
33
|
+
Consider the following MongoMapper document.
|
34
|
+
|
35
|
+
class Person
|
36
|
+
include MongoMapper::Document
|
37
|
+
key :name, String
|
38
|
+
key :status, String
|
39
|
+
timestamps!
|
40
|
+
end
|
41
|
+
|
42
|
+
It could be any other Mapping layer that provides pagination feature.
|
43
|
+
|
44
|
+
If you want to iterate through all records from the database an amount each time, you can do the following
|
45
|
+
|
46
|
+
STDOUT.sync = true
|
47
|
+
STDOUT.write "Running..."
|
48
|
+
|
49
|
+
page_iterator = PageIterator.new(Person.count, "current_page.log")
|
50
|
+
|
51
|
+
STDOUT.write "\n - #{Person.to_s} (#{page_iterator.remaining_items}/#{page_iterator.total_items})"
|
52
|
+
page_iterator.each_remaining_page! do |page|
|
53
|
+
person_list = Person.paginate(:per_page => page_iterator.per_page , :page => page)
|
54
|
+
person_list.each do |person|
|
55
|
+
person.status = 'active'
|
56
|
+
if person.save
|
57
|
+
STDOUT.write "."
|
58
|
+
else
|
59
|
+
STDOUT.write "F"
|
60
|
+
exit(1)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
The script is setting the status of a Person instance to *active*. If something goes wrong, the script will print *F* in the screen and exit. So, after you fix the reason of failure (*F*) and run the script again, **PageIterator** is going to start the execution from the page where the failure happened, and not since the beginning of the collection.
|
66
|
+
It's possible to see that it's still needed a pagination mechanism for the items themselves, as `paginate` method that MongoMapper provides.
|
67
|
+
|
68
|
+
|
69
|
+
## Project
|
70
|
+
* https://github.com/ericfer/page_iterator
|
71
|
+
|
72
|
+
## Report bugs and suggestions
|
73
|
+
* [Issue Tracker](https://github.com/ericfer/page_iterator/issues)
|
74
|
+
|
75
|
+
## Author
|
76
|
+
* [Eric Fer](https://github.com/ericfer)
|
data/lib/page_iterator.rb
CHANGED
@@ -1,22 +1,26 @@
|
|
1
1
|
class PageIterator
|
2
|
-
|
2
|
+
DEFAULT_ITEMS_PER_PAGE = 50
|
3
3
|
|
4
|
-
attr_reader :
|
4
|
+
attr_reader :total_items
|
5
5
|
|
6
|
-
def initialize(
|
7
|
-
@
|
8
|
-
@
|
6
|
+
def initialize(total_items, logfile, items_per_page=DEFAULT_ITEMS_PER_PAGE)
|
7
|
+
@total_items = total_items
|
8
|
+
@items_per_page = items_per_page
|
9
9
|
@logfile = logfile
|
10
10
|
@current_page = current_page_from_file
|
11
11
|
end
|
12
12
|
|
13
|
+
def per_page
|
14
|
+
@items_per_page
|
15
|
+
end
|
16
|
+
|
13
17
|
def total_pages
|
14
|
-
pages = @
|
18
|
+
pages = @total_items / @items_per_page
|
15
19
|
if pages == 0
|
16
20
|
1
|
17
21
|
else
|
18
|
-
|
19
|
-
|
22
|
+
last_page_items = @total_items % @items_per_page
|
23
|
+
last_page_items > 0 ? pages + 1 : pages
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
@@ -30,11 +34,11 @@ class PageIterator
|
|
30
34
|
log @current_page
|
31
35
|
end
|
32
36
|
|
33
|
-
def
|
37
|
+
def remaining_items
|
34
38
|
if @current_page > total_pages
|
35
39
|
0
|
36
40
|
else
|
37
|
-
@
|
41
|
+
@total_items - (@current_page - 1) * @items_per_page
|
38
42
|
end
|
39
43
|
end
|
40
44
|
|
data/page_iterator.gemspec
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
gem_name =
|
1
|
+
gem_name = File.basename(__FILE__, ".gemspec")
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = gem_name
|
5
|
-
s.version = "0.1.
|
6
|
-
s.summary = "
|
5
|
+
s.version = "0.1.1"
|
6
|
+
s.summary = "Split a number of data in pages and iterate through them, keeping track in a log file"
|
7
7
|
s.author = "Eric Fer"
|
8
8
|
s.email = "eric.fer@gmail.com"
|
9
9
|
s.homepage = "https://github.com/ericfer/#{gem_name}"
|
10
|
+
s.files = Dir["**/*.{md,rb,gemspec}"] - Dir["spec/**/*.rb"]
|
11
|
+
s.rubyforge_project = gem_name
|
10
12
|
s.add_development_dependency "rspec"
|
11
13
|
s.add_development_dependency "mocha"
|
12
|
-
s.rubyforge_project = gem_name
|
13
|
-
s.files = Dir["{lib/**/*.rb,README.rdoc,Rakefile,*.gemspec}"]
|
14
14
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: page_iterator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Eric Fer
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-04-01 00:00:00 -03:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -55,8 +55,8 @@ extensions: []
|
|
55
55
|
extra_rdoc_files: []
|
56
56
|
|
57
57
|
files:
|
58
|
+
- README.md
|
58
59
|
- lib/page_iterator.rb
|
59
|
-
- Rakefile
|
60
60
|
- page_iterator.gemspec
|
61
61
|
has_rdoc: true
|
62
62
|
homepage: https://github.com/ericfer/page_iterator
|
@@ -91,6 +91,6 @@ rubyforge_project: page_iterator
|
|
91
91
|
rubygems_version: 1.3.7
|
92
92
|
signing_key:
|
93
93
|
specification_version: 3
|
94
|
-
summary:
|
94
|
+
summary: Split a number of data in pages and iterate through them, keeping track in a log file
|
95
95
|
test_files: []
|
96
96
|
|
data/Rakefile
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
begin
|
2
|
-
require 'rspec/core/rake_task'
|
3
|
-
|
4
|
-
desc "Run specs"
|
5
|
-
RSpec::Core::RakeTask.new do |t|
|
6
|
-
t.rspec_opts = %w(-fs --color)
|
7
|
-
end
|
8
|
-
rescue LoadError
|
9
|
-
task :spec do
|
10
|
-
abort "Run `rake spec:deps` to be able to run the specs"
|
11
|
-
end
|
12
|
-
|
13
|
-
namespace :spec do
|
14
|
-
desc "Ensure spec dependencies are installed"
|
15
|
-
task :deps do
|
16
|
-
sh "gem list rspec | (grep 'rspec (2.0' 1> /dev/null) || gem install rspec --no-ri --no-rdoc"
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
gem_name = Dir["*.gemspec"].first.match(/\A(\w*).gemspec\z/).captures.first
|
22
|
-
|
23
|
-
desc "Build the gem, removing old ones"
|
24
|
-
task :build do
|
25
|
-
# gem_name = 'rakesupport'
|
26
|
-
gem_files = Dir['*.gem']
|
27
|
-
commands = []
|
28
|
-
commands << ["rm #{ gem_files.join(' ') }"] unless gem_files.empty?
|
29
|
-
commands << ["gem build #{gem_name}.gemspec"]
|
30
|
-
sh commands.join(" && ")
|
31
|
-
end
|
32
|
-
|
33
|
-
desc "Build and install the gem"
|
34
|
-
task :install => :build do
|
35
|
-
# gem_name = 'rakesupport'
|
36
|
-
gem_file = Dir['*.gem'].first
|
37
|
-
if gem_file.nil?
|
38
|
-
puts "There is no gem file to install"
|
39
|
-
else
|
40
|
-
sh "gem uninstall --ignore-dependencies #{gem_name}; gem install #{gem_file}"
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
task :default => :spec
|