dato 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +42 -5
- data/.travis.yml +1 -0
- data/Gemfile +1 -1
- data/Rakefile +2 -2
- data/bin/console +3 -3
- data/bin/rspec +6 -6
- data/dato.gemspec +1 -1
- data/exe/dato +3 -3
- data/lib/dato.rb +8 -8
- data/lib/dato/account/client.rb +2 -2
- data/lib/dato/api_client.rb +39 -43
- data/lib/dato/api_error.rb +10 -13
- data/lib/dato/cli.rb +18 -18
- data/lib/dato/dump/dsl/add_to_data_file.rb +1 -1
- data/lib/dato/dump/dsl/create_data_file.rb +1 -1
- data/lib/dato/dump/dsl/create_post.rb +1 -1
- data/lib/dato/dump/dsl/directory.rb +4 -4
- data/lib/dato/dump/dsl/root.rb +7 -7
- data/lib/dato/dump/format.rb +3 -3
- data/lib/dato/dump/format/json.rb +1 -1
- data/lib/dato/dump/format/toml.rb +6 -6
- data/lib/dato/dump/format/yaml.rb +3 -3
- data/lib/dato/dump/operation/add_to_data_file.rb +4 -4
- data/lib/dato/dump/operation/create_data_file.rb +3 -3
- data/lib/dato/dump/operation/create_post.rb +5 -6
- data/lib/dato/dump/operation/directory.rb +1 -1
- data/lib/dato/dump/runner.rb +5 -5
- data/lib/dato/dump/ssg_detector.rb +18 -20
- data/lib/dato/json_api_deserializer.rb +15 -16
- data/lib/dato/json_api_serializer.rb +30 -21
- data/lib/dato/json_schema_relationships.rb +19 -23
- data/lib/dato/json_schema_type.rb +47 -0
- data/lib/dato/local/entities_repo.rb +3 -3
- data/lib/dato/local/field_type/color.rb +11 -7
- data/lib/dato/local/field_type/file.rb +18 -24
- data/lib/dato/local/field_type/gallery.rb +1 -1
- data/lib/dato/local/field_type/global_seo.rb +4 -7
- data/lib/dato/local/field_type/lat_lon.rb +1 -1
- data/lib/dato/local/field_type/seo.rb +1 -1
- data/lib/dato/local/field_type/structured_text.rb +4 -10
- data/lib/dato/local/field_type/theme.rb +2 -2
- data/lib/dato/local/field_type/upload_id.rb +5 -5
- data/lib/dato/local/field_type/video.rb +9 -15
- data/lib/dato/local/item.rb +13 -12
- data/lib/dato/local/items_repo.rb +12 -18
- data/lib/dato/local/json_api_entity.rb +4 -3
- data/lib/dato/local/loader.rb +30 -31
- data/lib/dato/local/site.rb +5 -4
- data/lib/dato/paginator.rb +4 -4
- data/lib/dato/repo.rb +23 -30
- data/lib/dato/site/client.rb +5 -5
- data/lib/dato/upload/create_upload_path.rb +7 -10
- data/lib/dato/upload/file.rb +3 -3
- data/lib/dato/upload/image.rb +1 -1
- data/lib/dato/utils/build_modular_block.rb +4 -4
- data/lib/dato/utils/favicon_tags_builder.rb +10 -10
- data/lib/dato/utils/locale_value.rb +1 -1
- data/lib/dato/utils/meta_tags/article_modified_time.rb +3 -3
- data/lib/dato/utils/meta_tags/article_publisher.rb +2 -2
- data/lib/dato/utils/meta_tags/base.rb +6 -6
- data/lib/dato/utils/meta_tags/description.rb +4 -4
- data/lib/dato/utils/meta_tags/image.rb +4 -5
- data/lib/dato/utils/meta_tags/og_locale.rb +2 -2
- data/lib/dato/utils/meta_tags/og_site_name.rb +2 -2
- data/lib/dato/utils/meta_tags/og_type.rb +3 -3
- data/lib/dato/utils/meta_tags/robots.rb +2 -2
- data/lib/dato/utils/meta_tags/title.rb +6 -6
- data/lib/dato/utils/meta_tags/twitter_card.rb +2 -2
- data/lib/dato/utils/meta_tags/twitter_site.rb +2 -2
- data/lib/dato/utils/seo_tags_builder.rb +12 -12
- data/lib/dato/version.rb +1 -1
- metadata +7 -6
@@ -4,14 +4,7 @@ module Dato
|
|
4
4
|
module Local
|
5
5
|
module FieldType
|
6
6
|
class Video
|
7
|
-
attr_reader :url
|
8
|
-
attr_reader :thumbnail_url
|
9
|
-
attr_reader :title
|
10
|
-
attr_reader :width
|
11
|
-
attr_reader :height
|
12
|
-
attr_reader :provider
|
13
|
-
attr_reader :provider_url
|
14
|
-
attr_reader :provider_uid
|
7
|
+
attr_reader :url, :thumbnail_url, :title, :width, :height, :provider, :provider_url, :provider_uid
|
15
8
|
|
16
9
|
def self.parse(value, _repo)
|
17
10
|
value && new(
|
@@ -22,7 +15,7 @@ module Dato
|
|
22
15
|
value[:height],
|
23
16
|
value[:provider],
|
24
17
|
value[:provider_url],
|
25
|
-
value[:provider_uid]
|
18
|
+
value[:provider_uid],
|
26
19
|
)
|
27
20
|
end
|
28
21
|
|
@@ -47,15 +40,16 @@ module Dato
|
|
47
40
|
end
|
48
41
|
|
49
42
|
def iframe_embed(width = self.width, height = self.height)
|
50
|
-
# rubocop:disable
|
51
|
-
|
43
|
+
# rubocop:disable Layout/LineLength
|
44
|
+
case provider
|
45
|
+
when "youtube"
|
52
46
|
%(<iframe width="#{width}" height="#{height}" src="//www.youtube.com/embed/#{provider_uid}?rel=0" frameborder="0" allowfullscreen></iframe>)
|
53
|
-
|
47
|
+
when "vimeo"
|
54
48
|
%(<iframe src="//player.vimeo.com/video/#{provider_uid}?title=0&byline=0&portrait=0" width="#{width}" height="#{height}" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>)
|
55
|
-
|
49
|
+
when "facebook"
|
56
50
|
%(<iframe src="//www.facebook.com/plugins/video.php?href=#{url}&width=#{width}&show_text=false&height=#{height}" width="#{width}" height="#{height}" style="border:none;overflow:hidden;width:100%;" scrolling="no" frameborder="0" allowTransparency="true" allow="encrypted-media" allowFullScreen="true"></iframe>)
|
57
51
|
end
|
58
|
-
# rubocop:enable
|
52
|
+
# rubocop:enable Layout/LineLength
|
59
53
|
end
|
60
54
|
|
61
55
|
def to_hash(*_args)
|
@@ -67,7 +61,7 @@ module Dato
|
|
67
61
|
height: height,
|
68
62
|
provider: provider,
|
69
63
|
provider_url: provider_url,
|
70
|
-
provider_uid: provider_uid
|
64
|
+
provider_uid: provider_uid,
|
71
65
|
}
|
72
66
|
end
|
73
67
|
end
|
data/lib/dato/local/item.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
3
|
+
require "forwardable"
|
4
|
+
require "active_support/inflector/transliterate"
|
5
|
+
require "active_support/hash_with_indifferent_access"
|
6
|
+
require "dato/utils/locale_value"
|
7
7
|
|
8
|
-
Dir[File.dirname(__FILE__)
|
8
|
+
Dir["#{File.dirname(__FILE__)}/field_type/*.rb"].sort.each do |file|
|
9
9
|
require file
|
10
10
|
end
|
11
11
|
|
@@ -15,6 +15,7 @@ module Dato
|
|
15
15
|
extend Forwardable
|
16
16
|
|
17
17
|
attr_reader :entity
|
18
|
+
|
18
19
|
def_delegators :entity, :id, :meta
|
19
20
|
|
20
21
|
def initialize(entity, items_repo)
|
@@ -45,7 +46,7 @@ module Dato
|
|
45
46
|
|
46
47
|
def attributes
|
47
48
|
fields.each_with_object(
|
48
|
-
ActiveSupport::HashWithIndifferentAccess.new
|
49
|
+
ActiveSupport::HashWithIndifferentAccess.new,
|
49
50
|
) do |field, acc|
|
50
51
|
acc[field.api_key.to_sym] = read_attribute(field.api_key, field)
|
51
52
|
end
|
@@ -88,7 +89,7 @@ module Dato
|
|
88
89
|
id: id,
|
89
90
|
item_type: item_type.api_key,
|
90
91
|
updated_at: updated_at,
|
91
|
-
created_at: created_at
|
92
|
+
created_at: created_at,
|
92
93
|
}
|
93
94
|
|
94
95
|
base[:position] = position if item_type.sortable
|
@@ -98,7 +99,7 @@ module Dato
|
|
98
99
|
base[:children] = children.map do |child|
|
99
100
|
child.to_hash(
|
100
101
|
max_depth,
|
101
|
-
current_depth + 1
|
102
|
+
current_depth + 1,
|
102
103
|
)
|
103
104
|
end
|
104
105
|
end
|
@@ -109,7 +110,7 @@ module Dato
|
|
109
110
|
result[field.api_key.to_sym] = if value.respond_to?(:to_hash)
|
110
111
|
value.to_hash(
|
111
112
|
max_depth,
|
112
|
-
current_depth + 1
|
113
|
+
current_depth + 1,
|
113
114
|
)
|
114
115
|
else
|
115
116
|
value
|
@@ -138,9 +139,9 @@ module Dato
|
|
138
139
|
"Warning: unrecognized field of type `#{field_type}`",
|
139
140
|
"for item `#{item_type.api_key}` and",
|
140
141
|
"field `#{method}`: returning a simple Hash instead.",
|
141
|
-
|
142
|
+
"Please upgrade to the latest version of the `dato` gem!",
|
142
143
|
]
|
143
|
-
puts warning.join(
|
144
|
+
puts warning.join(" ")
|
144
145
|
|
145
146
|
value
|
146
147
|
end
|
@@ -154,7 +155,7 @@ module Dato
|
|
154
155
|
super
|
155
156
|
end
|
156
157
|
rescue NoMethodError => e
|
157
|
-
if e.name
|
158
|
+
if e.name == method
|
158
159
|
message = []
|
159
160
|
message << "Undefined method `#{method}`"
|
160
161
|
message << "Available fields for a `#{item_type.api_key}` item:"
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require "active_support/core_ext/string"
|
4
|
+
require "dato/local/item"
|
5
|
+
require "dato/local/site"
|
6
6
|
|
7
7
|
module Dato
|
8
8
|
module Local
|
@@ -37,8 +37,8 @@ module Dato
|
|
37
37
|
|
38
38
|
def site
|
39
39
|
Site.new(
|
40
|
-
entities_repo.find_entities_of_type(
|
41
|
-
self
|
40
|
+
entities_repo.find_entities_of_type("site").first,
|
41
|
+
self,
|
42
42
|
)
|
43
43
|
end
|
44
44
|
|
@@ -47,7 +47,7 @@ module Dato
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def item_types
|
50
|
-
entities_repo.find_entities_of_type(
|
50
|
+
entities_repo.find_entities_of_type("item_type")
|
51
51
|
end
|
52
52
|
|
53
53
|
def single_instance_item_types
|
@@ -97,7 +97,7 @@ module Dato
|
|
97
97
|
end
|
98
98
|
|
99
99
|
if clashing_keys.include?(pluralized_api_key)
|
100
|
-
suffix = item_type.singleton ?
|
100
|
+
suffix = item_type.singleton ? "instance" : "collection"
|
101
101
|
method = "#{method}_#{suffix}"
|
102
102
|
end
|
103
103
|
|
@@ -119,9 +119,7 @@ module Dato
|
|
119
119
|
item = Item.new(item_entity, self)
|
120
120
|
method = item_type_methods[item_entity.item_type]
|
121
121
|
|
122
|
-
unless item_entity.item_type.singleton
|
123
|
-
@collections_by_type[method].push item
|
124
|
-
end
|
122
|
+
@collections_by_type[method].push item unless item_entity.item_type.singleton
|
125
123
|
|
126
124
|
@items_by_id[item.id] = item
|
127
125
|
|
@@ -144,9 +142,7 @@ module Dato
|
|
144
142
|
item[field].nil?
|
145
143
|
end
|
146
144
|
@collections_by_type[method] = valid_items.sort_by { |item| item[field] } + nil_items
|
147
|
-
if item_type.ordering_direction ==
|
148
|
-
@collections_by_type[method].reverse!
|
149
|
-
end
|
145
|
+
@collections_by_type[method].reverse! if item_type.ordering_direction == "desc"
|
150
146
|
end
|
151
147
|
end
|
152
148
|
end
|
@@ -156,16 +152,14 @@ module Dato
|
|
156
152
|
method = item_type_methods[item_type]
|
157
153
|
next unless item_type.singleton
|
158
154
|
|
159
|
-
item = if item_type.singleton_item
|
160
|
-
@items_by_id[item_type.singleton_item.id]
|
161
|
-
end
|
155
|
+
item = (@items_by_id[item_type.singleton_item.id] if item_type.singleton_item)
|
162
156
|
|
163
157
|
@collections_by_type[method] = item
|
164
158
|
end
|
165
159
|
end
|
166
160
|
|
167
161
|
def item_entities
|
168
|
-
entities_repo.find_entities_of_type(
|
162
|
+
entities_repo.find_entities_of_type("item")
|
169
163
|
end
|
170
164
|
|
171
165
|
def method_missing(method, *arguments, &block)
|
@@ -177,7 +171,7 @@ module Dato
|
|
177
171
|
rescue NoMethodError
|
178
172
|
message = []
|
179
173
|
message << "Undefined method `#{method}`"
|
180
|
-
message <<
|
174
|
+
message << "Available DatoCMS collections/items:"
|
181
175
|
message += collections_by_type.map do |key, _value|
|
182
176
|
"* .#{key}"
|
183
177
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "dato/local/json_api_meta"
|
4
4
|
|
5
5
|
module Dato
|
6
6
|
module Local
|
@@ -60,11 +60,12 @@ module Dato
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def dereference_linkage(linkage)
|
63
|
-
|
63
|
+
case linkage
|
64
|
+
when Array
|
64
65
|
linkage.map do |item|
|
65
66
|
data_source.find_entity(item[:type], item[:id])
|
66
67
|
end
|
67
|
-
|
68
|
+
when Hash
|
68
69
|
data_source.find_entity(linkage[:type], linkage[:id])
|
69
70
|
end
|
70
71
|
end
|
data/lib/dato/local/loader.rb
CHANGED
@@ -1,32 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "pusher-client"
|
4
4
|
|
5
|
-
require
|
6
|
-
require
|
5
|
+
require "dato/local/entities_repo"
|
6
|
+
require "dato/local/items_repo"
|
7
7
|
|
8
8
|
module Dato
|
9
9
|
module Local
|
10
10
|
class Loader
|
11
|
-
attr_reader :client
|
12
|
-
attr_reader :entities_repo
|
13
|
-
attr_reader :items_repo
|
14
|
-
attr_reader :preview_mode
|
11
|
+
attr_reader :client, :entities_repo, :items_repo, :preview_mode
|
15
12
|
|
16
|
-
PUSHER_API_KEY =
|
13
|
+
PUSHER_API_KEY = "75e6ef0fe5d39f481626"
|
17
14
|
|
15
|
+
# rubocop:disable Style/OptionalBooleanParameter
|
18
16
|
def initialize(client, preview_mode = false)
|
19
17
|
@client = client
|
20
18
|
@preview_mode = preview_mode
|
21
19
|
@entities_repo = EntitiesRepo.new
|
22
20
|
@items_repo = ItemsRepo.new(@entities_repo)
|
23
21
|
end
|
22
|
+
# rubocop:enable Style/OptionalBooleanParameter
|
24
23
|
|
25
24
|
def load
|
26
25
|
threads = [
|
27
26
|
Thread.new { Thread.current[:output] = site },
|
28
27
|
Thread.new { Thread.current[:output] = all_items },
|
29
|
-
Thread.new { Thread.current[:output] = all_uploads }
|
28
|
+
Thread.new { Thread.current[:output] = all_uploads },
|
30
29
|
]
|
31
30
|
|
32
31
|
results = threads.map do |t|
|
@@ -39,7 +38,7 @@ module Dato
|
|
39
38
|
end
|
40
39
|
|
41
40
|
def watch(&block)
|
42
|
-
site_id = client.get(
|
41
|
+
site_id = client.get("/site")["data"]["id"]
|
43
42
|
|
44
43
|
return if pusher && pusher.connected
|
45
44
|
|
@@ -69,11 +68,11 @@ module Dato
|
|
69
68
|
private
|
70
69
|
|
71
70
|
def bind_on_site_upsert(&block)
|
72
|
-
bind_on("site:upsert", block) do |
|
71
|
+
bind_on("site:upsert", block) do |_data|
|
73
72
|
threads = [
|
74
73
|
Thread.new { Thread.current[:output] = site },
|
75
74
|
Thread.new { Thread.current[:output] = all_items },
|
76
|
-
Thread.new { Thread.current[:output] = all_uploads }
|
75
|
+
Thread.new { Thread.current[:output] = all_uploads },
|
77
76
|
]
|
78
77
|
|
79
78
|
results = threads.map do |t|
|
@@ -86,16 +85,16 @@ module Dato
|
|
86
85
|
end
|
87
86
|
|
88
87
|
def bind_on_item_upsert(&block)
|
89
|
-
event_type = preview_mode ?
|
88
|
+
event_type = preview_mode ? "preview_mode" : "published_mode"
|
90
89
|
|
91
90
|
bind_on("item:#{event_type}:upsert", block) do |data|
|
92
91
|
payload = client.items.all(
|
93
92
|
{
|
94
|
-
|
95
|
-
version: item_version
|
93
|
+
"filter[ids]" => data[:ids].join(","),
|
94
|
+
version: item_version,
|
96
95
|
},
|
97
96
|
deserialize_response: false,
|
98
|
-
all_pages: true
|
97
|
+
all_pages: true,
|
99
98
|
)
|
100
99
|
|
101
100
|
@entities_repo.upsert_entities(payload)
|
@@ -103,10 +102,10 @@ module Dato
|
|
103
102
|
end
|
104
103
|
|
105
104
|
def bind_on_item_destroy(&block)
|
106
|
-
event_type = preview_mode ?
|
105
|
+
event_type = preview_mode ? "preview_mode" : "published_mode"
|
107
106
|
|
108
107
|
bind_on("item:#{event_type}:destroy", block) do |data|
|
109
|
-
@entities_repo.destroy_entities(
|
108
|
+
@entities_repo.destroy_entities("item", data[:ids])
|
110
109
|
end
|
111
110
|
end
|
112
111
|
|
@@ -114,10 +113,10 @@ module Dato
|
|
114
113
|
bind_on("upload:upsert", block) do |data|
|
115
114
|
payload = client.uploads.all(
|
116
115
|
{
|
117
|
-
|
116
|
+
"filter[ids]" => data[:ids].join(","),
|
118
117
|
},
|
119
118
|
deserialize_response: false,
|
120
|
-
all_pages: true
|
119
|
+
all_pages: true,
|
121
120
|
)
|
122
121
|
|
123
122
|
@entities_repo.upsert_entities(payload)
|
@@ -125,21 +124,21 @@ module Dato
|
|
125
124
|
end
|
126
125
|
|
127
126
|
def bind_on_upload_destroy(&block)
|
128
|
-
bind_on(
|
129
|
-
@entities_repo.destroy_entities(
|
127
|
+
bind_on("upload:destroy", block) do |data|
|
128
|
+
@entities_repo.destroy_entities("upload", data[:ids])
|
130
129
|
end
|
131
130
|
end
|
132
131
|
|
133
132
|
def bind_on_item_type_upsert(&block)
|
134
|
-
bind_on(
|
133
|
+
bind_on("item_type:upsert", block) do |data|
|
135
134
|
data[:ids].each do |id|
|
136
135
|
payload = client.item_types.find(id, {}, deserialize_response: false)
|
137
136
|
@entities_repo.upsert_entities(payload)
|
138
137
|
|
139
138
|
payload = client.items.all(
|
140
|
-
{
|
139
|
+
{ "filter[type]" => id },
|
141
140
|
deserialize_response: false,
|
142
|
-
all_pages: true
|
141
|
+
all_pages: true,
|
143
142
|
)
|
144
143
|
|
145
144
|
@entities_repo.upsert_entities(payload)
|
@@ -148,7 +147,7 @@ module Dato
|
|
148
147
|
end
|
149
148
|
|
150
149
|
def bind_on_item_type_destroy(&block)
|
151
|
-
bind_on(
|
150
|
+
bind_on("item_type:destroy", block) do |data|
|
152
151
|
data[:ids].each do |id|
|
153
152
|
@entities_repo.destroy_item_type(id)
|
154
153
|
end
|
@@ -174,19 +173,19 @@ module Dato
|
|
174
173
|
@pusher ||= PusherClient::Socket.new(
|
175
174
|
PUSHER_API_KEY,
|
176
175
|
secure: true,
|
177
|
-
auth_method: method(:pusher_auth_method)
|
176
|
+
auth_method: method(:pusher_auth_method),
|
178
177
|
)
|
179
178
|
end
|
180
179
|
|
181
180
|
def site
|
182
|
-
client.get(
|
181
|
+
client.get("/site", include: ["item_types", "item_types.fields"])
|
183
182
|
end
|
184
183
|
|
185
184
|
def all_items
|
186
185
|
client.items.all(
|
187
186
|
{ version: item_version },
|
188
187
|
deserialize_response: false,
|
189
|
-
all_pages: true
|
188
|
+
all_pages: true,
|
190
189
|
)
|
191
190
|
end
|
192
191
|
|
@@ -198,9 +197,9 @@ module Dato
|
|
198
197
|
|
199
198
|
def item_version
|
200
199
|
if preview_mode
|
201
|
-
|
200
|
+
"latest"
|
202
201
|
else
|
203
|
-
|
202
|
+
"published"
|
204
203
|
end
|
205
204
|
end
|
206
205
|
|
data/lib/dato/local/site.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
3
|
+
require "forwardable"
|
4
|
+
require "active_support/inflector/transliterate"
|
5
|
+
require "active_support/hash_with_indifferent_access"
|
6
|
+
require "dato/utils/locale_value"
|
7
7
|
|
8
8
|
module Dato
|
9
9
|
module Local
|
@@ -11,6 +11,7 @@ module Dato
|
|
11
11
|
extend Forwardable
|
12
12
|
|
13
13
|
attr_reader :entity
|
14
|
+
|
14
15
|
def_delegators :entity, :id, :name, :locales, :domain,
|
15
16
|
:internal_domain, :no_index, :frontend_url
|
16
17
|
|
data/lib/dato/paginator.rb
CHANGED
@@ -12,7 +12,7 @@ module Dato
|
|
12
12
|
items_per_page = 100
|
13
13
|
|
14
14
|
base_response = @client.get(
|
15
|
-
@base_endpoint, @filters.dup.merge(
|
15
|
+
@base_endpoint, @filters.dup.merge("page[limit]" => items_per_page)
|
16
16
|
)
|
17
17
|
|
18
18
|
extra_pages = (
|
@@ -23,9 +23,9 @@ module Dato
|
|
23
23
|
base_response[:data] += @client.get(
|
24
24
|
@base_endpoint,
|
25
25
|
@filters.dup.merge(
|
26
|
-
|
27
|
-
|
28
|
-
)
|
26
|
+
"page[offset]" => items_per_page * (page + 1),
|
27
|
+
"page[limit]" => items_per_page,
|
28
|
+
),
|
29
29
|
)[:data]
|
30
30
|
end
|
31
31
|
|