contentstack 0.4.2 → 0.5.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a87ffedb4feafb037dccf082f50e3e2df92db4f68bbb2278c69fc6209ebd0f97
4
- data.tar.gz: b89fca962f1c9fe6c2839f41fe3ce761eed92f2329229dc41b3cb79383e40b7a
3
+ metadata.gz: 38cb9c00678c71f0e4d00449b051bdbfa8e743141c95989d27caf58802665a28
4
+ data.tar.gz: f916dfd420ea954d7d01208ab97df9e7e2d8a97777449bef101a39d41d4f720d
5
5
  SHA512:
6
- metadata.gz: d4af764bf1af5cd485a49bdb6ff127bd0a9a079f562c82a7ee27c79776324dd9b7c297291d1af71aadab8c19c7b0d989aede075689b7998b5d8ff858d65e8ce4
7
- data.tar.gz: 128181df6d6b5e93ec1ea4bee2ce3c6c9afad74fb2519cf52f0d9b41a7a57519935ae7e7ebb00db45dbbb56c98471b443105ea5e560f63e49f544f53e06befb0
6
+ metadata.gz: a7491b3bf5648675b9fd069bdf8dfff2c70e51d75594f1f2629b54632ca616be27cdebc6487dac9eb9f8fc242a440cd783167b94b0707f1a1879a925cde22301
7
+ data.tar.gz: f32ceecfa27bf63e217bcf27a6f11b62c054e2bef6a74c61a6659ff1508cdd4b8f5d14fb95b2df6814254e09e8898e18269a852bfc3eff925e53de6da4d293fa
data/.gitignore CHANGED
@@ -9,3 +9,4 @@ coverage
9
9
  .bundle/
10
10
  **/rspec_results.html
11
11
  vendor/
12
+ .dccache
data/.talismanrc ADDED
@@ -0,0 +1 @@
1
+ threshold: medium
data/CHANGELOG.md CHANGED
@@ -1,4 +1,10 @@
1
1
  ## CHANGELOG
2
+ ------------------------------------------------
3
+ ## Version 0.4.3
4
+ ### Date: 17th-Sept-2021
5
+ ### Dependency update
6
+ - Issue for Monkey patching resolved. Implemented Refine to extend class within module scope.
7
+
2
8
  ------------------------------------------------
3
9
  ## Version 0.4.2
4
10
  ### Date: 2nd-Sept-2021
data/CODEOWNERS ADDED
@@ -0,0 +1 @@
1
+ * @contentstack/security-admin @contentstack/sdk-admin
data/Gemfile.lock CHANGED
@@ -1,14 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- contentstack (0.4.1)
4
+ contentstack (0.5.0)
5
5
  activesupport (>= 3.2, < 6.2)
6
6
  contentstack_utils (~> 1.0, >= 1.0.1)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activesupport (6.1.4)
11
+ activesupport (6.1.5)
12
12
  concurrent-ruby (~> 1.0, >= 1.0.2)
13
13
  i18n (>= 1.6, < 2)
14
14
  minitest (>= 5.1)
@@ -16,8 +16,8 @@ GEM
16
16
  zeitwerk (~> 2.3)
17
17
  addressable (2.8.0)
18
18
  public_suffix (>= 2.0.2, < 5.0)
19
- concurrent-ruby (1.1.9)
20
- contentstack_utils (1.0.2)
19
+ concurrent-ruby (1.1.10)
20
+ contentstack_utils (1.1.0)
21
21
  activesupport (>= 3.2, < 6.2)
22
22
  nokogiri (~> 1.11, >= 1.11.0)
23
23
  crack (0.4.5)
@@ -25,15 +25,15 @@ GEM
25
25
  diff-lcs (1.4.4)
26
26
  docile (1.4.0)
27
27
  hashdiff (1.0.1)
28
- i18n (1.8.10)
28
+ i18n (1.10.0)
29
29
  concurrent-ruby (~> 1.0)
30
- mini_portile2 (2.5.3)
31
- minitest (5.14.4)
32
- nokogiri (1.11.7)
33
- mini_portile2 (~> 2.5.0)
30
+ mini_portile2 (2.8.0)
31
+ minitest (5.15.0)
32
+ nokogiri (1.13.4)
33
+ mini_portile2 (~> 2.8.0)
34
34
  racc (~> 1.4)
35
35
  public_suffix (4.0.6)
36
- racc (1.5.2)
36
+ racc (1.6.0)
37
37
  rexml (3.2.5)
38
38
  rspec (3.10.0)
39
39
  rspec-core (~> 3.10.0)
@@ -61,7 +61,7 @@ GEM
61
61
  crack (>= 0.3.2)
62
62
  hashdiff (>= 0.4.0, < 2.0.0)
63
63
  yard (0.9.26)
64
- zeitwerk (2.4.2)
64
+ zeitwerk (2.5.4)
65
65
 
66
66
  PLATFORMS
67
67
  ruby
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2012-2021 Contentstack. All Rights Reserved
3
+ Copyright (c) 2012-2022 Contentstack. All Rights Reserved
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -116,7 +116,7 @@ In a single instance, the [Get Multiple Entries](https://www.contentstack.com/do
116
116
 
117
117
  We have introduced Image Delivery APIs that let you retrieve images and then manipulate and optimize them for your digital properties. It lets you perform a host of other actions such as crop, trim, resize, rotate, overlay, and so on.
118
118
 
119
- For example, if you want to crop an image (with width as 300 and height as 400), you simply need to append query parameters at the end of the image URL, such as, https://images.contentstack.io/v3/assets/blteae40eb499811073/bltc5064f36b5855343/59e0c41ac0eddd140d5a8e3e/download?crop=300,400. There are several more parameters that you can use for your images.
119
+ For example, if you want to crop an image (with width as 300 and height as 400), you simply need to append query parameters at the end of the image URL, such as, https://images.contentstack.io/v3/download?crop=300,400. There are several more parameters that you can use for your images.
120
120
 
121
121
  [Read Image Delivery API documentation](https://www.contentstack.com/docs/apis/image-delivery-api/).
122
122
 
data/SECURITY.md ADDED
@@ -0,0 +1,27 @@
1
+ ## Security
2
+
3
+ Contentstack takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations.
4
+
5
+ If you believe you have found a security vulnerability in any Contentstack-owned repository, please report it to us as described below.
6
+
7
+ ## Reporting Security Issues
8
+
9
+ **Please do not report security vulnerabilities through public GitHub issues.**
10
+
11
+ Send email to [security@contentstack.com](mailto:security@contentstack.com).
12
+
13
+ You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message.
14
+
15
+ Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
16
+
17
+ * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
18
+ * Full paths of source file(s) related to the manifestation of the issue
19
+ * The location of the affected source code (tag/branch/commit or direct URL)
20
+ * Any special configuration required to reproduce the issue
21
+ * Step-by-step instructions to reproduce the issue
22
+ * Proof-of-concept or exploit code (if possible)
23
+ * Impact of the issue, including how an attacker might exploit the issue
24
+
25
+ This information will help us triage your report more quickly.
26
+
27
+ [https://www.contentstack.com/trust/](https://www.contentstack.com/trust/)
@@ -3,16 +3,24 @@ require 'net/http'
3
3
  require 'active_support'
4
4
  require 'active_support/json'
5
5
  require 'open-uri'
6
-
6
+ require 'util'
7
7
  module Contentstack
8
8
  class API
9
- def self.init_api(api_key, delivery_token, environment,host)
9
+ using Utility
10
+ def self.init_api(api_key, delivery_token, environment, host, branch, live_preview)
10
11
  @host = host
11
12
  @api_version = '/v3'
12
13
  @environment = environment
13
14
  @api_key = api_key
14
15
  @access_token = delivery_token
16
+ @branch = branch
15
17
  @headers = {environment: @environment}
18
+ @live_preview = live_preview
19
+ end
20
+
21
+ def self.live_preview_query(query= {})
22
+ @live_preview[:content_type_uid] = query[:content_type_uid]
23
+ @live_preview[:live_preview] = query[:live_preview]
16
24
  end
17
25
 
18
26
  def self.fetch_content_types(uid="")
@@ -25,13 +33,23 @@ module Contentstack
25
33
  end
26
34
 
27
35
  def self.fetch_entries(content_type, query)
28
- path = "/content_types/#{content_type}/entries"
29
- send_request(path, query)
36
+ if @live_preview[:enable] && @live_preview[:content_type_uid] == content_type
37
+ path = "/content_types/#{content_type}/entries"
38
+ send_preview_request(path, query)
39
+ else
40
+ path = "/content_types/#{content_type}/entries"
41
+ send_request(path, query)
42
+ end
30
43
  end
31
44
 
32
45
  def self.fetch_entry(content_type, entry_uid, query)
33
- path = "/content_types/#{content_type}/entries/#{entry_uid}"
34
- send_request(path, query)
46
+ if @live_preview[:enable] && @live_preview[:content_type_uid] == content_type
47
+ path = "/content_types/#{content_type}/entries/#{entry_uid}"
48
+ send_preview_request(path, query)
49
+ else
50
+ path = "/content_types/#{content_type}/entries/#{entry_uid}"
51
+ send_request(path, query)
52
+ end
35
53
  end
36
54
 
37
55
  def self.get_assets(asset_uid=nil)
@@ -53,12 +71,35 @@ module Contentstack
53
71
 
54
72
  query = "?" + q.to_query
55
73
  # puts "Request URL:- #{@host}#{@api_version}#{path}#{query} \n\n"
56
-
57
- ActiveSupport::JSON.decode(URI.open("#{@host}#{@api_version}#{path}#{query}",
58
- "api_key" => @api_key,
59
- "access_token"=> @access_token,
60
- "user_agent"=> "ruby-sdk/#{Contentstack::VERSION}",
61
- "x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}").read)
74
+ params = {
75
+ "api_key" => @api_key,
76
+ "access_token"=> @access_token,
77
+ "user_agent"=> "ruby-sdk/#{Contentstack::VERSION}",
78
+ "x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}"
79
+ }
80
+ if !@branch.nil? && !@branch.empty?
81
+ params["branch"] = @branch
82
+ end
83
+ ActiveSupport::JSON.decode(URI.open("#{@host}#{@api_version}#{path}#{query}", params).read)
84
+ end
85
+
86
+ def self.send_preview_request(path, q=nil)
87
+ q ||= {}
88
+
89
+ q.merge!({live_preview: (!@live_preview.key?(:live_preview) ? 'init' : @live_preview[:live_preview]),})
90
+
91
+ query = "?" + q.to_query
92
+ preview_host = @live_preview[:host]
93
+ params = {
94
+ "api_key" => @api_key,
95
+ "authorization" => @live_preview[:management_token],
96
+ "user_agent"=> "ruby-sdk/#{Contentstack::VERSION}",
97
+ "x-user-agent" => "ruby-sdk/#{Contentstack::VERSION}"
98
+ }
99
+ if !@branch.nil? && !@branch.empty?
100
+ params["branch"] = @branch
101
+ end
102
+ ActiveSupport::JSON.decode(URI.open("#{preview_host}#{@api_version}#{path}#{query}",params).read)
62
103
  end
63
104
  end
64
105
  end
@@ -1,7 +1,9 @@
1
+ require 'util'
1
2
  module Contentstack
2
3
 
3
4
  # Asset class to fetch file details on Conentstack server.
4
5
  class Asset
6
+ using Utility
5
7
  attr_reader :uid, :content_type, :filename, :file_size, :tags, :url
6
8
 
7
9
  # @!attribute [r] uid
@@ -1,8 +1,10 @@
1
1
  require 'contentstack/asset'
2
+ require 'util'
2
3
 
3
4
  module Contentstack
4
5
  # Asset class to fetch details of files on Conentstack server.
5
6
  class AssetCollection
7
+ using Utility
6
8
  attr_reader :assets
7
9
 
8
10
  def initialize(assets_array=nil)
@@ -2,14 +2,18 @@ require 'contentstack/api'
2
2
  require 'contentstack/content_type'
3
3
  require 'contentstack/asset_collection'
4
4
  require 'contentstack/sync_result'
5
+ require 'util'
5
6
  module Contentstack
6
7
  class Client
8
+ using Utility
7
9
  attr_reader :region, :host
8
10
  # Initialize "Contentstack" Client instance
9
11
  def initialize(api_key, delivery_token, environment, options={})
10
12
  @region = options[:region].nil? ? Contentstack::Region::US : options[:region]
11
13
  @host = options[:host].nil? ? get_default_region_hosts(@region) : options[:host]
12
- API.init_api(api_key, delivery_token, environment, @host)
14
+ @live_preview = !options.key?(:live_preview) ? {} : options[:live_preview]
15
+ @branch = options[:branch].nil? ? "" : options[:branch]
16
+ API.init_api(api_key, delivery_token, environment, @host, @branch, @live_preview)
13
17
  end
14
18
 
15
19
  def content_types
@@ -28,6 +32,9 @@ module Contentstack
28
32
  Asset.new(uid)
29
33
  end
30
34
 
35
+ def live_preview_query(query={})
36
+ API.live_preview_query(query)
37
+ end
31
38
 
32
39
  # Syncs your Contentstack data with your app and ensures that the data is always up-to-date by providing delta updates
33
40
  #
@@ -41,9 +48,9 @@ module Contentstack
41
48
  #
42
49
  # Stack.sync({'init': true, 'type': 'entry_published'}) // Use the type parameter to get a specific type of content.Supports 'asset_published', 'entry_published', 'asset_unpublished', 'entry_unpublished', 'asset_deleted', 'entry_deleted', 'content_type_deleted'.
43
50
  #
44
- # Stack.sync({'pagination_token': '<btlsomething>'}) // For fetching the next batch of entries using pagination token
51
+ # Stack.sync({'pagination_token': '<pagination>'}) // For fetching the next batch of entries using pagination token
45
52
  #
46
- # Stack.sync({'sync_token': '<btlsomething>'}) // For performing subsequent sync after initial sync
53
+ # Stack.sync({'sync_token': '<sync>'}) // For performing subsequent sync after initial sync
47
54
  #
48
55
  # @param params [Hash] params is an object that supports ‘locale’, ‘start_date’, ‘content_type_uid’, and ‘type’ queries.
49
56
  def sync(params)
@@ -1,7 +1,9 @@
1
1
  require 'contentstack/query'
2
+ require 'util'
2
3
 
3
4
  module Contentstack
4
5
  class ContentType
6
+ using Utility
5
7
  [:title, :uid, :created_at, :updated_at, :attributes].each do |method_name|
6
8
  if [:created_at, :updated_at].include?(method_name)
7
9
  define_method method_name do
@@ -1,7 +1,9 @@
1
1
  require 'active_support/core_ext'
2
+ require 'util'
2
3
 
3
4
  module Contentstack
4
5
  class Entry
6
+ using Utility
5
7
  attr_reader :fields, :content_type, :uid, :owner, :query, :schema, :content_type
6
8
  def initialize(attrs, content_type_uid=nil)
7
9
  setup(attrs, content_type_uid)
@@ -152,6 +154,19 @@ module Contentstack
152
154
  self
153
155
  end
154
156
 
157
+ # Include the branch for publish content.
158
+ #
159
+ # Example
160
+ #
161
+ # @entry = @stack.content_type('product').entry(entry_uid)
162
+ # @entry.include_branch
163
+ #
164
+ # @return [Contentstack::Entry]
165
+ def include_branch(flag=true)
166
+ @query[:include_branch] = flag
167
+ self
168
+ end
169
+
155
170
  # Include Embedded Objects (Entries and Assets) along with entry/entries details.
156
171
  #
157
172
  # Example
@@ -1,7 +1,9 @@
1
1
  require 'contentstack/entry'
2
+ require 'util'
2
3
 
3
4
  module Contentstack
4
5
  class EntryCollection
6
+ using Utility
5
7
  attr_reader :entries, :count, :content_type, :schema
6
8
 
7
9
  def initialize(json, content_type_uid=nil)
@@ -1,8 +1,10 @@
1
1
  require 'contentstack/entry_collection'
2
+ require 'util'
2
3
 
3
4
  module Contentstack
4
5
  # A class that defines a query that is used to query for Entry instance.
5
6
  class Query
7
+ using Utility
6
8
  # @!attribute [r] query
7
9
  # Attribute which has all the information about the query which will be executed against Contentstack API
8
10
 
@@ -287,7 +289,7 @@ module Contentstack
287
289
  end
288
290
 
289
291
  # This method provides only the entries matching the specified value.
290
- #
292
+ # @deprecated since version 0.5.0
291
293
  # @param [String] text value used to match or compare
292
294
  #
293
295
  # Example
@@ -516,6 +518,19 @@ module Contentstack
516
518
  self
517
519
  end
518
520
 
521
+ # Include the branch for publish content.
522
+ #
523
+ # Example
524
+ #
525
+ # @query = @stack.content_type('product').query
526
+ # @query.include_branch
527
+ #
528
+ # @return [Contentstack::Entry]
529
+ def include_branch(flag=true)
530
+ @query[:include_branch] = flag
531
+ self
532
+ end
533
+
519
534
  # Include Embedded Objects (Entries and Assets) along with entry/entries details.
520
535
  #
521
536
  # Example
@@ -1,3 +1,3 @@
1
1
  module Contentstack
2
- VERSION = "0.4.2"
2
+ VERSION = "0.5.1"
3
3
  end
data/lib/contentstack.rb CHANGED
@@ -4,8 +4,6 @@ require "contentstack/version"
4
4
  require "contentstack/client"
5
5
  require "contentstack/region"
6
6
  require "contentstack_utils"
7
- require "util"
8
-
9
7
 
10
8
  # == Contentstack - Ruby SDK
11
9
  # Contentstack is a content management system that facilitates the process of publication by separating the content from site-related programming and design.
@@ -17,6 +15,8 @@ require "util"
17
15
  # @stack = Contentstack::Client.new("site_api_key", "delivery_token", "enviroment_name", {"region": Contentstack::Region::EU })
18
16
  # == Initialize the Stack for custom host
19
17
  # @stack = Contentstack::Client.new("site_api_key", "delivery_token", "enviroment_name", {"host": "https://custom-cdn.contentstack.com" })
18
+ # == Initialize the Stack for EU region
19
+ # @stack = Contentstack::Client.new("site_api_key", "delivery_token", "enviroment_name", {"branch":"branch_name" })
20
20
  # == Usage
21
21
  # ==== Get single entry
22
22
  # @stack.content_type('blog').entry('<entry_uid_here>').fetch
data/lib/util.rb CHANGED
@@ -1,107 +1,111 @@
1
- class Hash
2
- def to_query(namespace = nil)
3
- collect do |key, value|
4
- value.to_query(namespace ? "#{namespace}[#{key}]" : key)
5
- end.sort * '&'
6
- end
7
-
8
- def symbolize_keys
9
- new_hash = {}
10
- self.each do |key,value|
11
- if [Hash, Array].include?(value.class)
12
- new_hash[key.to_sym] = value.symbolize_keys
13
- else
14
- new_hash[key.to_sym] = value
1
+ module Contentstack
2
+ module Utility
3
+ refine Hash do
4
+ def to_query(namespace = nil)
5
+ collect do |key, value|
6
+ value.to_query(namespace ? "#{namespace}[#{key}]" : key)
7
+ end.sort * '&'
8
+ end
9
+
10
+ def symbolize_keys
11
+ new_hash = {}
12
+ self.each do |key,value|
13
+ if [Hash, Array].include?(value.class)
14
+ new_hash[key.to_sym] = value.symbolize_keys
15
+ else
16
+ new_hash[key.to_sym] = value
17
+ end
18
+ end
19
+ new_hash
20
+ end
21
+ end
22
+
23
+ refine Array do
24
+ def to_query(key)
25
+ prefix = "#{key}[]"
26
+ collect { |value| value.to_query(prefix) }.join '&'
27
+ end
28
+
29
+ def symbolize_keys
30
+ collect do |entry|
31
+ if entry.class == Hash
32
+ entry.symbolize_keys
33
+ else
34
+ entry
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ refine String do
41
+ def to_query(key)
42
+ require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
43
+ "#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}"
44
+ end
45
+
46
+ def to_param
47
+ to_s
48
+ end
49
+ end
50
+
51
+ refine Symbol do
52
+ def to_query(key)
53
+ to_s.to_query(key)
54
+ end
55
+
56
+ def to_param
57
+ to_s
58
+ end
59
+ end
60
+
61
+ refine NilClass do
62
+ def to_query(key)
63
+ to_s.to_query(key)
64
+ end
65
+
66
+ def to_param
67
+ to_s
68
+ end
69
+ end
70
+
71
+ refine TrueClass do
72
+ def to_query(key)
73
+ to_s.to_query(key)
74
+ end
75
+
76
+ def to_query(val)
77
+ "#{CGI.escape(val.to_param)}=#{CGI.escape(to_s)}"
15
78
  end
16
79
  end
17
- new_hash
18
- end
19
- end
20
-
21
- class Array
22
- def to_query(key)
23
- prefix = "#{key}[]"
24
- collect { |value| value.to_query(prefix) }.join '&'
25
- end
26
-
27
- def symbolize_keys
28
- collect do |entry|
29
- if entry.class == Hash
30
- entry.symbolize_keys
31
- else
32
- entry
80
+
81
+ refine FalseClass do
82
+ def to_query(key)
83
+ to_s.to_query(key)
84
+ end
85
+
86
+ def to_query(val)
87
+ "#{CGI.escape(val.to_param)}=#{CGI.escape(to_s)}"
33
88
  end
34
89
  end
35
- end
36
- end
37
-
38
- class String
39
- def to_query(key)
40
- require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
41
- "#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}"
42
- end
43
-
44
- def to_param
45
- to_s
46
- end
47
- end
48
-
49
- class Symbol
50
- def to_query(key)
51
- to_s.to_query(key)
52
- end
53
-
54
- def to_param
55
- to_s
56
- end
57
- end
58
-
59
- class NilClass
60
- def to_query(key)
61
- to_s.to_query(key)
62
- end
63
-
64
- def to_param
65
- to_s
66
- end
67
- end
68
-
69
- class TrueClass
70
- def to_query(key)
71
- to_s.to_query(key)
72
- end
73
-
74
- def to_query(val)
75
- "#{CGI.escape(val.to_param)}=#{CGI.escape(to_s)}"
76
- end
77
- end
78
-
79
- class FalseClass
80
- def to_query(key)
81
- to_s.to_query(key)
82
- end
83
-
84
- def to_query(val)
85
- "#{CGI.escape(val.to_param)}=#{CGI.escape(to_s)}"
86
- end
87
- end
88
-
89
- class Integer
90
- def to_query(key)
91
- to_s.to_query(key)
92
- end
93
-
94
- def to_query(val)
95
- "#{CGI.escape(val.to_param)}=#{CGI.escape(to_s)}"
96
- end
97
- end
98
-
99
- class Numeric
100
- def to_query(key)
101
- to_s.to_query(key)
102
- end
103
-
104
- def to_query(val)
105
- "#{CGI.escape(val.to_param)}=#{CGI.escape(to_s)}"
106
- end
90
+
91
+ refine Integer do
92
+ def to_query(key)
93
+ to_s.to_query(key)
94
+ end
95
+
96
+ def to_query(val)
97
+ "#{CGI.escape(val.to_param)}=#{CGI.escape(to_s)}"
98
+ end
99
+ end
100
+
101
+ refine Numeric do
102
+ def to_query(key)
103
+ to_s.to_query(key)
104
+ end
105
+
106
+ def to_query(val)
107
+ "#{CGI.escape(val.to_param)}=#{CGI.escape(to_s)}"
108
+ end
109
+ end
110
+ end
107
111
  end