-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Collection representation #23
Comments
@Kris-LIBIS could you post your Representer? I'm assuming you have a block that looks something like this? link :self, toplevel: true do |options|
"/api/organizations?page=#{options[:page]}&per_page=#{options[:per_page]}"
end |
Top-level meta information should not be rendered on individual resource objects in the primary data array. Also tighten up wording in tests and documentation. Closes #23 Signed-off-by: Alex Coles <alex@alexbcoles.com>
Top-level meta information should not be rendered on individual resource objects in the primary data array. Also tighten up wording in tests and documentation. Closes #23 Signed-off-by: Alex Coles <alex@alexbcoles.com>
@myabc I might have something like that at a given point. In the mean time I worked around the meta problem by putting it in my Representer i.o. the user_options. But I still cannot work out the links part. I have fiddled around with my Representers so much, that I don't know anymore how I got the results above. But I have currently this: base.rb
item_list.rb
organization.rb
The reason I do it this way is because I have a lot of object types to represent and I want to keep as much as possible the object and api specific data out of the Representer. I do get the meta section on the top level only and I get the links on the top level too, but I cannot get the links :self and :all to appear on the individual objects anymore:
with the to_hash argument evaluation to:
Gives me:
Note that there is no links section on the I don't see what I am doing wrong here. Especially since it used to work at some point. |
@myabc I also looked at the code change you committed for #24. If I interpret that correctly you are stripping both the meta and user_options for the individual document rendering, right? I am afraid that stripping the user_options may break my code again, because the :base_url will not be available for the individual objects any more and would cause the :self and :all links to be broken. Since one can always use if clauses and differentiate with toplevel: true I do not see any harm in passing the user_options to the individual documents. Would you consider reverting that part of the change? |
I played a bit more with the Representer and discovered by accident that the :self and :all links appear again when I do not supply the :fields option in the to_hash argument. Is that a bug or is it intentional or am I doing something wrong? If it is a bug I'd gladly open a separate issue for it if you want me to. |
BTW the same happens when I add the :include option. |
I also have the problem with include: |
@twiduch Yes I did. I pathced ResourceCollection#to_hash like so: module Roar
module JSON
module JSONAPI
module ResourceCollection
def to_hash(options = {})
meta = options.delete(:meta)
document = super(to_a: options, user_options: options[:user_options]) # [{data: {..}, data: {..}}]
links = Renderer::Links.new.(document, options)
meta = render_meta(meta: meta)
included = []
document['data'].each do |single|
included += single.delete('included') || []
end
HashUtils.store_if_any(document, 'included',
Fragment::Included.(included, options))
HashUtils.store_if_any(document, 'links', links)
HashUtils.store_if_any(document, 'meta', meta)
document
end
end
end
end
end Note that I refrain from using relationships and include as they do not play nice with grape-swagger in my setup. So you luck may vary using my patch. |
@twiduch My patch is not that different from the code change 0063d6d. I only remove the :meta information from the options because I need the :user_options when processing the data section. Additionally, I created a special module for paginated collections: module Pagination
def for_pagination
for_collection.tap do |representer|
representer.class_eval do
def page_url(opts, page = nil, offset = nil)
url = opts[:this_url]
return url if page.nil? && offset.nil?
return url unless opts && opts[:pagination] && opts[:pagination][:total] > 1
page = (page || opts[:pagination][:page] rescue 1) + offset.to_i
uri = URI::parse(url)
uri.query_params['page'] = page
uri.to_s
end
def next_url(opts)
page_url(opts, nil, 1) if (opts[:pagination][:page] < opts[:pagination][:total] rescue false)
end
def prev_url(opts)
page_url(opts, nil, -1) if (opts[:pagination][:page] > 1 rescue false)
end
def first_url(opts)
page_url(opts, 1) if (opts[:pagination][:total] > 1 rescue false)
end
def last_url(opts)
page_url(opts, (opts[:pagination][:total] rescue 1)) if (opts[:pagination][:total] > 1 rescue false)
end
link(:self) {|opts| page_url(opts)}
link(:next) {|opts| next_url opts}
link(:prev) {|opts| prev_url opts}
link(:first) {|opts| first_url opts}
link(:last) {|opts| last_url opts}
# meta do
# property :current_page, exec_context: :decorator
# property :total_pages, exec_context: :decorator
# property :next_page, exec_context: :decorator
# property :prev_page, exec_context: :decorator
# property :total_count, exec_context: :decorator
# property :limit_value, as: :per_page, exec_context: :decorator
# end
#
# def current_page
# respresented.respond_to?(:current_page) ? represented.current_page : nil
# end
end
end
end
end I include the module in the representer and now use #for_pagination instead of #for_collection and supply the pagination info in the options hash with this code snippet: def pagination_hash(collection, default = {})
option_hash(default).tap do |h|
h[:user_options].merge!(
pagination: {
page: collection.current_page,
total: collection.total_pages,
per: declared(params).per_page
}
)
h.merge!(
meta: {
current_page: collection.current_page,
total_pages: collection.total_pages,
total_count: collection.total_count,
per_page: collection.limit_value
}
)
h[:meta][:next_page] = collection.next_page if collection.next_page
h[:meta][:prev_page] = collection.prev_page if collection.prev_page
end
end The option_hash() call supplies the basic options like :base_url and :this_url that I feed to any representer#to_hash call and is needed fo my code to work. |
I have some issues using the JSONAPI output for collections. I'm generating the collection output with:
The options generated by 'pagination_hash' looks like this:
The generated hash looks like this:
There are two issues with this:
The output I'm expecting is:
BTW: I'm using latest releases of grape, grape-roar, roar and roar-jsonapi on Ruby 2.3.1.
The text was updated successfully, but these errors were encountered: