Skip to content

Conversation

@chaunce
Copy link

@chaunce chaunce commented Aug 29, 2016

I added to this pull request a number of times while developing with the gem. I believe that this very closely matches the current documentation while keeping all existing functionality and adding new functionality.

resources_list = []
nodes.each{|n| resources_list << n.name.to_sym}
return resources_list
@resources ||= Nokogiri::XML(@resources_res.get.body).xpath('/prestashop/api/*').collect { |resource| resource.name.to_sym }
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was mostly merged into one line to make it more clear that no get or parsing is done if @resoures is already set.

stub_request(:any, @url_regex).to_return body: xml
end

def test_get_resources
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I now see that this works differently than the original documentation, but matches the functionality of the code before my pull request. I can revert the test changes and fix the code if this preferable, let me know.

xml_product = @resources_res["products/#{id}"].get.body
product = Product.xml2hash xml_product
products << product
@resources ||= Nokogiri::XML(@resources_res.get.body).xpath('/prestashop/api/*').collect { |resource| resource.name.to_sym }
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was mostly merged into one line to make it more clear that no get or parsing is done if @resoures is already set.

Copy link
Owner

@amatriain amatriain Sep 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Problem with memoization of @resources is that permissions assigned to an API key can be changed dynamically from the Prestashop administration. If an Api instance remembers the @resources array forever, this makes it necessary to get a new instance of the class after a change in permissions. I'd prefer if the list of resources accessible by the API key was not memoized, so that clients can get an up to date list of accessible resources at any time.

This would introduce a performance issue, however. You're using the @resources list in method_missing to see if the method being invoked matches an accessible resource. In this case we do want to get the memoized list of resources, so we don't make an extra HTTP call every time. Perhaps it would be best to create a new public get_resources method, that does an HTTP request every time, and make the resources method (that invokes get_resources only if @resources still has no value) private.

Copy link
Owner

@amatriain amatriain left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really good stuff. Thanks for your interest! Also sorry for the delay in responding but I wanted to review it thoroughly.

I made some comments, could you take a look at them? Also some yard docs for the new methods would be nice.

def method_missing(method, *args, &block)
if method.to_s.match(/^get_/)
resource = method.to_s.sub(/^get_/,'').pluralize.to_sym
raise RestClient::MethodNotAllowed, 'You do not have access to this resource' unless resources.include?(resource)
Copy link
Owner

@amatriain amatriain Sep 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the gem raising RestClient errors. The fact that the gem uses RestClient to make HTTP calls should be an implementation detail transparent to an app that uses it.

On the other hand creating a hierarchy of errors only for this gem is overkill. I'm unsure about the best way to do it.

ids.uniq.sort.collect { |id| get_resource(resource, id) }.compact
end

def collect_ids_for_resource(args)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps it would be better to call this method collect_id_for_resource, seeing that it validates and returns the ID of a single resource being requested :)

Nokogiri::XML(@resources_res[resource].get.body).xpath("/prestashop/#{resource}/*/@id").collect(&:value)
end

def get_resource(resource, id, raise_not_found_exception = false)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What use is the raise_not_found_exception argument? The method is always invoked passing a true to this argument. Also there is no equivalent argument in get_resources method.


begin
response = Nokogiri::XML(@resources_res[resource][id].get.body).remove_namespaces!.xpath("/prestashop/#{resource.to_s.singularize}")
JSON.parse(Hash.from_xml(response.to_s).values.first.to_json, object_class: resource_class)
Copy link
Owner

@amatriain amatriain Sep 17, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't a require 'active_support/json' necessary? Otherwise I think we'll get an undefined method error trying to invoke Hash.from_xml(response.to_s).values.first.to_json

end

def get_resources(resource, ids)
ids.uniq.sort.collect { |id| get_resource(resource, id) }.compact
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the sort step really necessary?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants