Open judofyr opened 10 years ago
I kinda sidetracked there.
The API for resolving a link will look something like this:
resource = service.resolve(link)
It's crucial that links are just data. link.resolve
will never happen; a link will never have access to the service it was fetched from.
This is actually more tricky than I realized: Do you attach a link to a resource or to a type?
I'm going to postpone this task until I have a specific usecase.
@judofyr IMO, the answer has to be found in the concept of 'representation' that seems to be missing in tipi so far.
Don't you attach URLs, hence links, to resources, even if various representations of them may lead to different 'types' ? (what do you mean by type
anyway?)
I'm unsure if I'm using all of these words correctly. Are /users
and /users/1
two different resources, even though they return pretty much same data ([User]
vs User
)? I want a User returned either from /users
or /users/1
to have the same links attached.
As I understand RESTful, yes, these are different resources, because they have different URLs. Now, I've never seen anyone talking about resource types. Maybe /users/1
and /users/2
have same resource type, and /users/
a very similar one?
I guess you could say they are two different resources that return the same representation type?
/users and /users/1 are two different resources, which share a representation, and may contain similar entities.
Every URL points at a distinct resource.
An entity is the thing in your database.
A representation is a media type.
In Fielding, a resource is a relation over time between one or more entities. They can only be acceded through a representation.
Random Programmer tends to conflate 'resources' and entities, imagining those as 'end points' to the same 'resource'. Which is wrong.
Does that make sense?
Thanks, 'entity' is the word I was missing!
So, where does one attach links? Eventually they end up in a representation, but I guess it makes sense that the same entity also have the same links regardless of the resources they come from.
Links only appear in representations. But they're generated based on the state of your application.
Imagine your app as a state machine. Resources are the states, links are the transitions.
Sent from my iPhone
On Mar 30, 2014, at 12:37 PM, Magnus Holm notifications@github.com wrote:
Thanks, 'entity' is the word I was missing!
So, where does one attach links? Eventually they end up in a representation, but I guess it makes sense that the same entity also have the same links regardless of the resources they come from.
\ Reply to this email directly or view it on GitHub.
@steveklabnik is there any kind of formal definition/model of all of this? Because I'm kind of lost here:
Entity, Resource, Representation, Thing, in a Database, State, Transition, Links, Resource contain entities, Links appear in representation, resource is relation over time between entities. Looks like random words to me.
I don't thing maths are always needed in programming, but sometimes, a formal model is the only stuff that is clear enough to build something IMO.
fielding's thesis, chapter 5.— Sent from Mailbox for iPhone
On Sun, Mar 30, 2014 at 12:48 PM, Bernard Lambeau notifications@github.com wrote:
@steveklabnik is there any kind of formal definition/model of all of this? Because I'm kind of lost here: Entity, Resource, Representation, Thing, in a Database, State, Transition, Links, Resource contain entities, Links appear in representation, resource is relation over time between entities. Looks like random words to me.
I don't thing maths are always needed in programming, but sometimes, a formal model is the only stuff that is clear enough to build something IMO.
Reply to this email directly or view it on GitHub: https://github.com/judofyr/tipi/issues/3#issuecomment-39037104
I guess there are different types of links. Some links are dependent on the state (next
, prev
) while others are directly connected to the entity (a link to a user's posts).
Some context here: I'm trying to figure out where links should be attached in this system. Right now you build up objects (that's your representation) that Tipi automatically converts to JSON. Should you insert links when you build up your objects, or should you be able to tell Tipi what links belongs to each object?
# Solution 1
User.new(name: …, links: {posts: router.users[id].posts})
# Solution 2
links_for User do |router|
{posts: router.users[id].posts}
end
User.new(name: …)
The advantage of the second solution is that it means you can decouple your URL structure from your representation. I care about this mostly from a Ruby point-of-view (no need to have a global route
object).
This obviously only works for links that are strictly connected to the entity (relationships). There still needs to be a way to add links that's strictly related to the resource.
I would imagine links belong on resources, because links are always from a resource to a resource.— Sent from Mailbox for iPhone
On Sun, Mar 30, 2014 at 12:50 PM, Magnus Holm notifications@github.com wrote:
I guess there are different types of links. Some links are dependent on the state (
next
,prev
) while others are directly connected to the entity (a link to a user's posts). Some context here: I'm trying to figure out where links should be attached in this system. Right now you build up objects (that's your representation) that Tipi automatically converts to JSON. Should you insert links when you build up your objects, or should you be able to tell Tipi what links belongs to each object?# Solution 1 User.new(name: …, links: {posts: router.users[id].posts}) # Solution 2 links_for User do |router| {posts: router.users[id].posts} end User.new(name: …)
The advantage of the second solution is that it means you can decouple your URL structure from your representation. I care about this mostly from a Ruby point-of-view (no need to have a global
route
object).This obviously only works for links that are strictly connected to the entity (relationships). There still needs to be a way to add links that's strictly related to the resource.
Reply to this email directly or view it on GitHub: https://github.com/judofyr/tipi/issues/3#issuecomment-39037182
At the same time I'd like to avoid duplication. I don't want to write the same code for attaching links for both the /users
and /users/:id
resource.
Meh, I realize that maybe I don't have enough information/experience to solve this issue. I don't know how I want use links. Top-level next
/prev
links are easy. It's the moment when I need a link deep down into the representation tree that things become tricky.
Oh well, there's a reason this has been tagged as "Later".
Thanks for the clarifications though; very much appreciated.
I agree with @steveklabnik - Putting the links into the model seems like tight coupling. And in some cases you might even want the same model objects to link differently based on the context in the api.
I like the idea of a resource type that can be attached to resources tho, and it might be the right place for links as well, while allowing reuse for both /users
and /users/:id
.
After we have #2 in place we can introduce links:
A link is a reference to a resource (not an action) and contains the path in two possible ways: The internal chain of Ruby methods (
[[:articles], [:find, 123], [:assets]]
) and a URL path (/articles/123/assets
).The idea is that you can resolve a link and fetch more data. This will work regardless whether you talk to an HTTP backend or access the Ruby classes directly.
Some concerns:
Right now resources don't keep track of where in the tree they are. If you run
root.articles[123].assets
all you have is anAssets
-instance with a state where thearticle
key is set. This is suboptimal in two ways: (1) There's no way to generate a relative path and (2) if you're fetching links which shares parents you will have to redo a lot of queries.I'm not really concerned about (2), but (1) is pretty important because it means we'll have to change the conventions for how the Resource-classes are structured. I really like how the current Resource requires little code to nest into another Resource: