Skip to content
This repository

adding shortcut: find(x) = find(:one, :from => x) when x is a url #7

Open
wants to merge 1 commit into from

5 participants

Seth Faxon Jeremy Kemper Markus Schwed Arun Agrawal Guillermo Iguaran
Seth Faxon

No description provided.

Seth Faxon

I would really appreciate any feedback on this. This is a very early part of an idea to decouple URL generation from ActiveResource. It seems more 'RESTful' to store the URL of a resource rather than an arbitrary ID. Eventually I think it would be useful to use a finder like this when dealing with associations as well. For example:

class Post < ActiveResource::Base
  self.site = "http://localhost:3000"
  has_many :comments
end

class Comment < ActiveResource::Base
  belongs_to :post
end

p = Post.find('http://localhost:3000/posts/1')
GET http://localhost:3000/posts/1 delivers:

{ title: "Post Title",
body: "Awesome post.",
comments_url: "http://localhost:3000/posts/1/comments"
comment_count: 1000 }

Calling p.comments could use Comments.find(p.comments_url), rather than being generated by ActiveResource.

A better example is probably pagination. Github uses the Link header for their pagination. It would be great to see ActiveResource eventually support something like this.

class GitHubRepos < ActiveResoure::Base
  self.site = "https://api.github.com/repos"
  self.paginator = GitHubPaginator.new
end

This probably introduces some problems with parsing paginated results and index actions as well, but it would make ActiveResource a lot more useful for my needs.

thanks

Jeremy Kemper
Owner

I like this direction, too: working with URLs and Link headers. Navigating an API.

Markus Schwed
Collaborator
SweeD commented

I like the idea, too. +1 from me.

Markus Schwed
Collaborator
SweeD commented

Some more feedback or just merge?

/cc @arunagw @guilleiguaran

Arun Agrawal
Collaborator

@SweeD thanks for mention. :+1: from my side.

Jeremy Kemper
Owner

The implementation feels bolted on. I think working with URIs natively needs deeper consideration.

Parsing every id as a URI will be surprising in many cases, too: Person.find(params[:id]) is now vulnerable to someone passing http://badsite.com/fakeperson/1 as the id param.

Seth Faxon

I agree that it feels bolted on. Currently the find method works the way it did in ActiveRecord, using the first param to find out what sort of search it should be doing. Is there a better way do find overall?

Jeremy Kemper
Owner

Checking for a URI instance could work, rather than accepting strings and parsing.

Guillermo Iguaran
Owner

I would love

GitHubRepos.find(params[:id], :site => "https://api.github.com/repos")
Markus Schwed
Collaborator
SweeD commented

@guilleiguaran

There is already a option for that:

GitHubRepos.find(params[:id], from: "https://api.github.com/repos")

Or did you mean especially the site attribute or haven't i got your question at all? :smile:

Markus Schwed
Collaborator
SweeD commented

@jeremy said:

Checking for a URI instance could work, rather than accepting strings and parsing.

Sounds like a goog idea to me.

What do you guys think?
/cc @guilleiguaran @arunagw

Guillermo Iguaran
Owner

@SweeD right, I mean the site :smile:

Jeremy Kemper
Owner

@sfaxon thoughts on checking scope.is_a?(URI) instead?

Markus Schwed
Collaborator

@sfaxon What do you think about jeremy's idea?

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

Showing 1 unique commit by 1 author.

Apr 11, 2012
Seth Faxon sfaxon adding shortcut: find(x) = find(:one, :from => x)
  x can be a full url
88d7360
This page is out of date. Refresh to see the latest.
3  lib/active_resource/base.rb
@@ -953,8 +953,9 @@ def find_one(options)
953 953 end
954 954 end
955 955
956   - # Find a single resource from the default URL
  956 + # Find a single resource from the default URL, or use the given url
957 957 def find_single(scope, options)
  958 + return find_one(options.merge(:from => scope)) if URI.parse(scope.to_s).scheme
958 959 prefix_options, query_options = split_options(options[:params])
959 960 path = element_path(scope, prefix_options, query_options)
960 961 instantiate_record(format.decode(connection.get(path, headers).body), prefix_options)
1  test/abstract_unit.rb
@@ -100,6 +100,7 @@ def setup_response
100 100
101 101 ActiveResource::HttpMock.respond_to do |mock|
102 102 mock.get "/people/1.json", {}, @matz
  103 + mock.get "http://37s.sunrise.i:3000/people/1", {}, @matz
103 104 mock.get "/people/1.xml", {}, @matz_xml
104 105 mock.get "/people/2.xml", {}, @david
105 106 mock.get "/people/5.xml", {}, @marty
6 test/cases/finder_test.rb
@@ -17,6 +17,12 @@ def test_find_by_id
17 17 assert_equal "Matz", matz.name
18 18 assert matz.name?
19 19 end
  20 +
  21 + def test_find_by_url
  22 + matz = Person.find("#{Person.site}people/1")
  23 + assert_kind_of Person, matz
  24 + assert_equal "Matz", matz.name
  25 + end
20 26
21 27 def test_find_by_id_with_custom_prefix
22 28 addy = StreetAddress.find(1, :params => { :person_id => 1 })

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.