pox_paginate 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,5 @@
1
+ = PoxPaginate
2
+
3
+ PoxPaginate is an extension to WillPaginate and ActiveResource that makes it possible to transparently paginate over a collection of XML serialised resources.
4
+
5
+ It currently depends on a patch to fix a bug in Rails that is documented in this {Lighthouse ticket}[https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/3217-parsing-an-xml-file-with-multiple-records-and-extra-attributes-besides-type-fails].
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ require 'spec'
2
+ require 'spec/rake/spectask'
3
+
4
+ desc 'Default: run spec tests.'
5
+ task :default => 'spec:unit'
6
+
7
+ namespace :spec do
8
+ desc "Run all unit specs"
9
+ Spec::Rake::SpecTask.new(:unit) do |task|
10
+ task.spec_files = FileList['spec/pox_paginate/**/*_spec.rb']
11
+ # task.spec_opts = ['--options', 'spec/spec.opts']
12
+ end
13
+ end
14
+
15
+ begin
16
+ require 'jeweler'
17
+ Jeweler::Tasks.new do |gemspec|
18
+ gemspec.name = "pox_paginate"
19
+ gemspec.summary = "Transparent support for pagination using WillPaginate using POX (Plain Old Xml) and ActiveResource"
20
+ gemspec.description = "Wrest is a HTTP and REST client library which allows you to quickly build well encapsulated, object oriented wrappers around any web service."
21
+ gemspec.authors = ["Sidu Ponnappa", "Niranjan Paranjape"]
22
+ gemspec.email = "opensource@c42.in"
23
+ gemspec.homepage = "http://github.com/kaiwren/wrest"
24
+ gemspec.has_rdoc = false
25
+ gemspec.require_path = "lib"
26
+ gemspec.files.exclude *['.gitignore']
27
+ gemspec.test_files.exclude *['.gitignore']
28
+ gemspec.add_dependency('activesupport', '>= 2.3.5')
29
+ gemspec.add_dependency('activeresource', '>= 2.3.5')
30
+ gemspec.add_dependency('will_paginate', '>= 2.3.12')
31
+ end
32
+
33
+ Jeweler::GemcutterTasks.new
34
+ rescue LoadError
35
+ puts "Jeweler not available. Install it with: gem install technicalpickles-jeweler -s http://gems.github.com"
36
+ puts "If you're using JRuby and are having trouble installing jeweler, try installing the git (gem install git) and rubyforge (gem install rubyforge) gems by hand. Also remember to update gems itself (jruby -S gem update --system)."
37
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,22 @@
1
+ module PoxPaginate
2
+ module ActiveResource
3
+ module XmlFormat
4
+ def self.included(mod)
5
+ mod.module_eval do
6
+ def decode_with_pagination_support(xml)
7
+ deserialised_xml = decode_without_pagination_support(xml)
8
+ root_attributes = ::ActiveSupport::XmlMini.root_node_attributes(xml)
9
+ if root_attributes['type'] == "array" && root_attributes['current_page']
10
+ RemoteCollection.create(root_attributes['current_page'], root_attributes['per_page'], root_attributes['total_entries']) do |pager|
11
+ pager.replace deserialised_xml
12
+ end
13
+ else
14
+ deserialised_xml
15
+ end
16
+ end
17
+ alias_method_chain :decode, :pagination_support
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,8 @@
1
+ module PoxPaginate
2
+ module ActiveResource
3
+ end
4
+ end
5
+
6
+ require "#{PoxPaginate::Root}/pox_paginate/active_resource/xml_format"
7
+
8
+ ActiveResource::Formats::XmlFormat.send :include, PoxPaginate::ActiveResource::XmlFormat
@@ -0,0 +1,25 @@
1
+ module PoxPaginate
2
+ module ActiveSupport
3
+ module CoreHashExt
4
+ def self.included(mod)
5
+ mod.module_eval do
6
+ alias_method :from_xml_without_extension, :from_xml
7
+ def from_xml(xml)
8
+ typecast_xml_value(unrename_keys(remove_pagination_attributes(::ActiveSupport::XmlMini.parse(xml))))
9
+ end
10
+
11
+ def remove_pagination_attributes(deserialized_xml)
12
+ if deserialized_xml.values.size == 1 && deserialized_xml.values.first['type'] == 'array'
13
+ clone = deserialized_xml.clone
14
+ clone.values.first.delete 'per_page'
15
+ clone.values.first.delete 'current_page'
16
+ clone.values.first.delete 'total_entries'
17
+ return clone
18
+ end
19
+ deserialized_xml
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,8 @@
1
+ module PoxPaginate
2
+ module ActiveSupport
3
+ end
4
+ end
5
+
6
+ require "#{PoxPaginate::Root}/pox_paginate/active_support/core_hash_ext"
7
+
8
+ ActiveSupport::CoreExtensions::Hash::Conversions::ClassMethods.send :include, PoxPaginate::ActiveSupport::CoreHashExt
@@ -0,0 +1,4 @@
1
+ module PoxPaginate
2
+ class RemoteCollection < WillPaginate::Collection
3
+ end
4
+ end
@@ -0,0 +1,43 @@
1
+ module PoxPaginate
2
+ module WillPaginate
3
+ module CollectionExtensions
4
+ def self.included(klass)
5
+ klass.class_eval do
6
+
7
+ def to_xml(options = {})
8
+ raise "Not all elements respond to to_xml" unless all? { |e| e.respond_to? :to_xml }
9
+ require 'builder' unless defined?(Builder)
10
+
11
+ options = options.dup
12
+ options[:root] ||= all? { |e| e.is_a?(first.class) && first.class.to_s != "Hash" } ? first.class.to_s.underscore.pluralize : "records"
13
+ options[:children] ||= options[:root].singularize
14
+ options[:indent] ||= 2
15
+ options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
16
+
17
+ root = options.delete(:root).to_s
18
+ children = options.delete(:children)
19
+
20
+ if !options.has_key?(:dasherize) || options[:dasherize]
21
+ root = root.dasherize
22
+ end
23
+
24
+ options[:builder].instruct! unless options.delete(:skip_instruct)
25
+
26
+ opts = options.merge({ :root => children })
27
+
28
+ xml = options[:builder]
29
+ if empty?
30
+ xml.tag!(root, options[:skip_types] ? {} : {:type => "array", :current_page => current_page, :per_page => per_page, :total_entries => total_entries})
31
+ else
32
+ xml.tag!(root, options[:skip_types] ? {} : {:type => "array", :current_page => current_page, :per_page => per_page, :total_entries => total_entries}) {
33
+ yield xml if block_given?
34
+ each { |e| e.to_xml(opts.merge({ :skip_instruct => true })) }
35
+ }
36
+ end
37
+ end
38
+
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,8 @@
1
+ module PoxPaginate
2
+ module WillPaginate
3
+ end
4
+ end
5
+
6
+ require "#{PoxPaginate::Root}/pox_paginate/will_paginate/collection_extensions"
7
+
8
+ WillPaginate::Collection.class_eval{ include PoxPaginate::WillPaginate::CollectionExtensions }
@@ -0,0 +1,8 @@
1
+ module PoxPaginate
2
+ module XmlMini
3
+ module JDOM
4
+ def root_node_attributes(xml)
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ module PoxPaginate
2
+ module XmlMini
3
+ module LibXML
4
+ def root_node_attributes(xml)
5
+ parser = ::LibXML::XML::Reader.string(xml)
6
+ parser.read
7
+ parser.has_attributes? ? parser.node.attributes.to_h : {}
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module PoxPaginate
2
+ module XmlMini
3
+ module Nokogiri
4
+ def root_node_attributes(xml)
5
+ parser = ::Nokogiri::XML::Reader.from_memory(xml)
6
+ parser.read
7
+ parser.attributes
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ module PoxPaginate
2
+ module XmlMini
3
+ module REXML
4
+ def root_node_attributes(xml)
5
+ require 'rexml/parsers/sax2parser'
6
+ parser = ::REXML::Parsers::SAX2Parser.new(xml)
7
+ root_attributes = nil
8
+ parser.listen(:start_element) do |uri, localname, qname, attributes|
9
+ root_attributes ||= attributes
10
+ end
11
+ parser.parse
12
+ root_attributes
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ module PoxPaginate
2
+ module XmlMini
3
+ end
4
+ end
5
+
6
+
7
+ # require "#{PoxPaginate::Root}/pox_paginate/xml_mini/libxml"
8
+ # require "#{PoxPaginate::Root}/pox_paginate/xml_mini/nokogiri"
9
+ # require "#{PoxPaginate::Root}/pox_paginate/xml_mini/jdom"
10
+
11
+ ActiveSupport::XmlMini.module_eval do
12
+ delegate :root_node_attributes, :to => :backend
13
+
14
+ def backend_with_root_node_attributes=(name)
15
+ result = ActiveSupport::XmlMini.backend_without_root_node_attributes=(name)
16
+ deserialiser = @backend.name.demodulize.gsub('XmlMini_', '')
17
+ require "#{PoxPaginate::Root}/pox_paginate/xml_mini/#{deserialiser.downcase}"
18
+ @backend.extend "PoxPaginate::XmlMini::#{deserialiser}".constantize
19
+ result
20
+ end
21
+ alias_method_chain :backend=, :root_node_attributes
22
+ end
23
+ ActiveSupport::XmlMini.backend=(ActiveSupport::XmlMini.backend)
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'active_resource'
3
+ require 'will_paginate'
4
+ require 'active_support'
5
+
6
+ module PoxPaginate
7
+ Root = File.dirname(__FILE__)
8
+ end
9
+
10
+ require "#{PoxPaginate::Root}/pox_paginate/active_support"
11
+ require "#{PoxPaginate::Root}/pox_paginate/remote_collection"
12
+ require "#{PoxPaginate::Root}/pox_paginate/active_resource"
13
+ require "#{PoxPaginate::Root}/pox_paginate/will_paginate"
14
+ require "#{PoxPaginate::Root}/pox_paginate/xml_mini"
@@ -0,0 +1,2 @@
1
+ adapter: sqlite3
2
+ database: ":memory:"
@@ -0,0 +1,12 @@
1
+ class CreateOogas < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :oogas do |t|
4
+ t.string :name
5
+ t.timestamps
6
+ end
7
+ end
8
+
9
+ def self.down
10
+ drop_table :oogas
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe PoxPaginate::ActiveResource::XmlFormat do
4
+ it "should foo" do
5
+ ::ActiveSupport::XmlMini.backend = 'LibXML'
6
+ collection = ActiveResource::Formats::XmlFormat.decode(paginated_xml(DateTime.parse('2010-02-06T21:09:48+05:30')))
7
+ collection.should be_a(PoxPaginate::RemoteCollection)
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe PoxPaginate::ActiveSupport::CoreHashExt do
4
+
5
+ it 'should from_xml ignores any root attributes other than type' do
6
+ Hash.from_xml(paginated_xml(@date)).should == {"oogas"=>[
7
+ {"name"=>"Foo", "updated_at"=>@date, "id"=>3, "created_at"=>@date},
8
+ {"name"=>"Baz", "updated_at"=>@date, "id"=>4, "created_at"=>@date}
9
+ ]}
10
+ end
11
+
12
+ end
@@ -0,0 +1,30 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe 'XmlSerializer Extensions' do
4
+ before :all do
5
+ Ooga.create!(:name => 'Coyote')
6
+ Ooga.create!(:name => 'Meh')
7
+ Ooga.create!(:name => 'Foo')
8
+ Ooga.create!(:name => 'Baz')
9
+ Ooga.create!(:name => 'Woot')
10
+ end
11
+
12
+ it "should ooga" do
13
+ Ooga.count.should == 5
14
+ end
15
+
16
+ it "should serialize to xml with root node attributes containing pagination metadata" do
17
+ page = Ooga.paginate :page => 2, :per_page => 2
18
+ xml = page.to_xml
19
+ xml.should match(/<oogas.*type=\"array\".*>\s+<ooga/)
20
+ xml.should match(/<oogas.*current_page=\"2\".*>\s+<ooga/)
21
+ xml.should match(/<oogas.*per_page=\"2\".*>\s+<ooga/)
22
+ xml.should match(/<oogas.*total_entries=\"5\".*>\s+<ooga/)
23
+ end
24
+
25
+ it "should have rails patched to allow deserialisation of tags with more than one attribute" do
26
+ # Patch at https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/3217-parsing-an-xml-file-with-multiple-records-and-extra-attributes-besides-type-fails
27
+ page = Ooga.paginate :page => 2, :per_page => 2
28
+ lambda{Hash.from_xml(page.to_xml)}.should_not raise_error
29
+ end
30
+ end
@@ -0,0 +1,47 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe PoxPaginate::XmlMini do
4
+ before :all do
5
+ @date = DateTime.parse('2010-02-06T21:09:48+05:30')
6
+ end
7
+
8
+ %w(REXML LibXML Nokogiri).each do |deserialiser|
9
+ describe "using #{deserialiser}" do
10
+ before :all do
11
+ ActiveSupport::XmlMini.backend = deserialiser
12
+ end
13
+
14
+ it "should be using the #{deserialiser} backend" do
15
+ ActiveSupport::XmlMini.backend.name.should == "ActiveSupport::XmlMini_#{deserialiser}"
16
+ end
17
+
18
+ it "should decorate backend= to extend the XmlMini_#{deserialiser} module" do
19
+ "ActiveSupport::XmlMini_#{deserialiser}".constantize.should respond_to(:root_node_attributes)
20
+ ActiveSupport::XmlMini.backend.name.should == "ActiveSupport::XmlMini_#{deserialiser}"
21
+ end
22
+
23
+ it "should parse xml with header attributes into a hash" do
24
+ Hash.from_xml(paginated_xml(@date)).should == {"oogas"=>[
25
+ {"name"=>"Foo", "updated_at"=>@date, "id"=>3, "created_at"=>@date},
26
+ {"name"=>"Baz", "updated_at"=>@date, "id"=>4, "created_at"=>@date}
27
+ ]}
28
+ end
29
+
30
+ it "should know how to extract root node attributes" do
31
+ ActiveSupport::XmlMini.root_node_attributes(paginated_xml(@date)).should == {
32
+ 'type' => "array",
33
+ 'total_entries' => "10",
34
+ 'per_page' => "2",
35
+ 'current_page' => "2"
36
+ }
37
+ end
38
+
39
+ it "should not add root node attributes if there are none" do
40
+ ActiveSupport::XmlMini.root_node_attributes(unpaginated_xml(@date)).should == {
41
+ 'type' => "array",
42
+ }
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,54 @@
1
+ require 'pp'
2
+ require 'rubygems'
3
+ require 'spec'
4
+ require 'active_record'
5
+
6
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/pox_paginate")
7
+
8
+ ActiveRecord::Base.establish_connection(YAML::load(File.open(File.dirname(__FILE__) + '/config/database.yml')))
9
+ ActiveRecord::Base.logger = Logger.new(File.open(File.dirname(__FILE__) + '/../log/test.log', 'a'))
10
+ ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/db/migrate')
11
+ WillPaginate.enable_activerecord
12
+
13
+ class Ooga < ActiveRecord::Base
14
+ end
15
+
16
+ def paginated_xml(date)
17
+ <<-EOXML
18
+ <?xml version="1.0" encoding="UTF-8"?>
19
+ <oogas type="array" total_entries="10" per_page="2" current_page="2">
20
+ <ooga>
21
+ <created-at type="datetime">#{date}</created-at>
22
+ <id type="integer">3</id>
23
+ <name>Foo</name>
24
+ <updated-at type="datetime">#{date}</updated-at>
25
+ </ooga>
26
+ <ooga>
27
+ <created-at type="datetime">#{date}</created-at>
28
+ <id type="integer">4</id>
29
+ <name>Baz</name>
30
+ <updated-at type="datetime">#{date}</updated-at>
31
+ </ooga>
32
+ </oogas>
33
+ EOXML
34
+ end
35
+
36
+ def unpaginated_xml(date)
37
+ <<-EOXML
38
+ <?xml version="1.0" encoding="UTF-8"?>
39
+ <oogas type="array">
40
+ <ooga>
41
+ <created-at type="datetime">#{date}</created-at>
42
+ <id type="integer">3</id>
43
+ <name>Foo</name>
44
+ <updated-at type="datetime">#{date}</updated-at>
45
+ </ooga>
46
+ <ooga>
47
+ <created-at type="datetime">#{date}</created-at>
48
+ <id type="integer">4</id>
49
+ <name>Baz</name>
50
+ <updated-at type="datetime">#{date}</updated-at>
51
+ </ooga>
52
+ </oogas>
53
+ EOXML
54
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pox_paginate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sidu Ponnappa
8
+ - Niranjan Paranjape
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2010-02-09 00:00:00 +05:30
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: activesupport
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 2.3.5
25
+ version:
26
+ - !ruby/object:Gem::Dependency
27
+ name: activeresource
28
+ type: :runtime
29
+ version_requirement:
30
+ version_requirements: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 2.3.5
35
+ version:
36
+ - !ruby/object:Gem::Dependency
37
+ name: will_paginate
38
+ type: :runtime
39
+ version_requirement:
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 2.3.12
45
+ version:
46
+ description: Wrest is a HTTP and REST client library which allows you to quickly build well encapsulated, object oriented wrappers around any web service.
47
+ email: opensource@c42.in
48
+ executables: []
49
+
50
+ extensions: []
51
+
52
+ extra_rdoc_files:
53
+ - README.rdoc
54
+ files:
55
+ - README.rdoc
56
+ - Rakefile
57
+ - VERSION
58
+ - lib/pox_paginate.rb
59
+ - lib/pox_paginate/active_resource.rb
60
+ - lib/pox_paginate/active_resource/xml_format.rb
61
+ - lib/pox_paginate/active_support.rb
62
+ - lib/pox_paginate/active_support/core_hash_ext.rb
63
+ - lib/pox_paginate/remote_collection.rb
64
+ - lib/pox_paginate/will_paginate.rb
65
+ - lib/pox_paginate/will_paginate/collection_extensions.rb
66
+ - lib/pox_paginate/xml_mini.rb
67
+ - lib/pox_paginate/xml_mini/jdom.rb
68
+ - lib/pox_paginate/xml_mini/libxml.rb
69
+ - lib/pox_paginate/xml_mini/nokogiri.rb
70
+ - lib/pox_paginate/xml_mini/rexml.rb
71
+ - spec/config/database.yml
72
+ - spec/db/migrate/001_create_oogas.rb
73
+ - spec/pox_paginate/active_resource/xml_format_spec.rb
74
+ - spec/pox_paginate/active_support/core_hash_ext_spec.rb
75
+ - spec/pox_paginate/will_paginate/collection_extensions_spec.rb
76
+ - spec/pox_paginate/xml_mini_spec.rb
77
+ - spec/spec_helper.rb
78
+ has_rdoc: true
79
+ homepage: http://github.com/kaiwren/wrest
80
+ licenses: []
81
+
82
+ post_install_message:
83
+ rdoc_options:
84
+ - --charset=UTF-8
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: "0"
92
+ version:
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: "0"
98
+ version:
99
+ requirements: []
100
+
101
+ rubyforge_project:
102
+ rubygems_version: 1.3.5
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Transparent support for pagination using WillPaginate using POX (Plain Old Xml) and ActiveResource
106
+ test_files:
107
+ - spec/db/migrate/001_create_oogas.rb
108
+ - spec/pox_paginate/active_resource/xml_format_spec.rb
109
+ - spec/pox_paginate/active_support/core_hash_ext_spec.rb
110
+ - spec/pox_paginate/will_paginate/collection_extensions_spec.rb
111
+ - spec/pox_paginate/xml_mini_spec.rb
112
+ - spec/spec_helper.rb