I am trying to get better with Rails and nesting resources. A User has many Event (and vice versa) through UserEvent join table. I also want a User to Comment on an Event. So far, Event is nested under User in my resources. How would you nest Comment? Would that be nested under Event so there are two successively nested resources under User? How would that work?
I think this would be my suggested nested approach:
resources :users
resources :events do
resources :comments
end
In a many-to-many relationship, it doesn't usually make sense to nest one under the other because neither has a stronger containment relationship.
In your scenario, a user doesn't belong to one event and an event doesn't belong to one user, so having your routes represent it like that doesn't quite model the relationship. Your URLs would look like /events/1/users/2. That sort of implies that User 2 only exists in Event 1.
I think it would make sense that your User and Event are top-level resources. Comments, on the other hand, do have some ownership which makes sense to nest. More than likely, a Comment will be associated with the Event in regards to context. The User is simply the person responsible for it. Nesting comments under the user would give you easy URLs to display all the comments for a user, but I'm betting you're more likely to display all the comments for an Event. With that in mind, I would suggest nesting Comments under Events.
This also makes sense if you were to delete the user and nullify the user_id in the Comment model. You could still have a URL for the comment. If you delete the Event, the comments likely aren't useful anymore anyway, so you could simply destroy them.
Related
I have user model and boat model. User has many boats. Boat belongs to user. What i wonder is that, even though i did not nest the resources i am able to create a boat to logged in user. So my url becomes ..../boats.new2 (2 as user id) and it actually saves to user with an id number 2.
But as far as i know if i have nested resources it would become something like .../user/2/boats/1. Isn't it?.
I have not tried to #edit action any of the cases so not sure which one to use and their effects, is there any other advantages using any of them, or not nesting is wrong?
Nesting routes is not necessary in Rails. You can maintain the relationship between boats and users as long as you have the active record belongs_to and has_many methods defined in the model, along with the foreign keys in the db.
In general, you should nest resources if there is an obvious relationship between the objects, such as users and posts (or boats). It just makes more sense of your users and as an API structure.
In some cases, you might want to nest the relationship under something different, like a category name. For instance, your uri pattern could look like /sailboats/boats/1 or powerboats/boat/2. Bottom line is you should structure routes in a way that logical for the project's users and developers.
I have a rails app that works almost like a blog, and I use a tagging system to categorize the posts.
I need to add to some of the posts something similar to a "related posts" feature.
So for example if post 1 is related to post 4, at the end of the show action for post one I want to render an image of post 4 and at the same time at the end of post 4 an image of post 1.
My idea is to create a "link" model that has a HABTM relations with the post model, but I'm not sure if a "post" has many "links" trough "linkings" would be better.
Both of the ideas seem to have the same result, so which approach should I prefer?
HABTM is by nature very simple, with just a table of foreign key pairs joining models.
Typically has_many through is used when you need to add additional attributes to that join relation, and/or when you need to treat the joins as their own model.
In your case, for example, you might want the links to appear in the order that they were created. For this to happen you'd need to store the create timestamp on the relationship. For this, the simple HABTM join table is not enough, so you switch to has_many through and create a Linking model to encapsulate the join.
To continue the example, you might also make Linking a first-class resource, and have a page where you can edit/add/remove them separately from either linked Post.
Personally I've always used has_many through in the majority of cases. It just feels cleaner to me (no auto-naming table magic to accept or override, and the linking is more visible), and I find that very often, join relationships do deserve to be first class citizens.
I have a project going on right now that is really big data model wise. I am trying to figure out the best way to handle inter-model relationships.
For the sake of brevity:
Car
has_many :passengers
has_many :items
or
Team
has_one :head_coach
has_many :coaches
has_many :players
belongs_to :owner
So from the show page I would see who is in the car and what items are in the car. I have some co-workers who think we should have a controller action called manage where they would click a link on the show page to manage the relationship between the other models
So the Team controller would have this
class TeamController < ApplicationController
# ... magic ...
def manage_players
#signed_players = Player.signed_players
#free_agents = Player.free_agents
end
end
The manage_players view would just have links to the actual RESTful actions on the appropriate controller to remove relationships etc...
Anyone have thoughts on how this should be accomplished?
That's an overly complicated approach, and the good news is, it's way simpler than you think.
Save yourself some trouble. The quick answer to your question is to use nested resources: you can have a single form that handles the Car and all the associated passengers/items, or the Team and its coach, players, etc.
The action/view you're describing would just be the edit action on the Car/Team. The manage action name is a nice idea and all, but the action you're really taking is an edit (nothing special, by what you're describing), so why confuse what's going on when the default is to call it edit?
If you want a live example of something that takes advantage of nested routes, check out rpglogger.com (it's my site). When you play around with it, notice the routes/URLs in the address bar.
It's also open source. Specifically relevant to your question is:
see the routes.rb file, and note how I define resources on sections twice - this actually gives me two different versions of the routes - one that's scoped to the LogBook, and one that's scoped to the objects in a section
see the world_object_form.haml (haml also rocks, FYI), which is both my new and edit form - yet it's short, rather uncomplicated, and pretty easy to read/undestand given what it does.
Ok, so I've got a weird pattern here that I can't figure out.
I have an STI set with CallList as the base model, and City & State inherited. A city belongs to a state (and a state has many cities).
A campaign has many call lists, so I want to display them all. I loop over campaign.call_lists and sometimes get Cities, sometimes States. When I want to link to them I do
link_to call_list.name, call_list
which works fine if I have these routes:
resources :cities, :states
When I nest cities inside states, however, the link_to helper can't figure out the appropriate route. Is there a simple way to do this, or am I going to have to do some manual path helper construction?
you need to check for kind of call_list and then use proper route..it can not be directly as route is nested..
link_to call_list.name, call_list.is_a?(City) ? call_list : state_city_path(call_list)
I'm looking for guidelines on when to know when a RESTful approach to a model and it's associations is proper, and when it's not. Perhaps it's the nature of my current application, but I'm finding that simple models with no associations work well with REST, but complex models with many has_many assocations really seem to complicate the view and the setup required in the controller. form_for calls start to become especially complicated.
Or perhaps it's my neophyte understanding. I've been doing Rails for over three years now, but REST and form helpers together seem to mystify me.
Make a resource of each top-level model in your system. By top-level, I mean models that are independent and have meaning outside of the associated model. Generally, that's most models. In the following example Position and Candidate are top-level. You could consider Candidate to be composed of PastEmployment and positions to which she has applied. Applications to positions and prior work history can be accessed through the Candidate resource, since they don't exist on their own.
Models
class Position
has_many :candidate_positions
has_many :candidates, :through => :candidate_positions
end
class Candidate
has_many :candidate_positions
has_many :positions, :through => :candidate_positions
has_many :past_employments
accepts_nested_attributes_for :past_employments
accepts_nested_attributes_for :candidate_positions
end
class PastEmployment
belongs_to :candidate
end
class CandidatePosition
belongs_to :candidate
belongs_to :position
end
Routes
map.resources :positions
map.resources :candidates
Use a non-resourceful controller for interactions with the user that span models. For example, if you wanted to have a HomeController that shows available positions as well as recent candidates, that would be a new, plain controller. If you want to edit any of the information on this controller, cool! You already have controllers available to handle the form posts, that will automatically be wired with <% form_for #candidate %>. You can render your collection of positions with <%= render #positions %>, and because you've made them a resource, Rails will know to look in views/positions/_position.html.erb for the appropriate partial.
The end result should be that you're never writing logic to handle the persistence of an object in more than one place. That's when controllers get complex and forms get out of hand. It also means that Rails and external systems know where to retrieve and store objects. Same URL, same controller, just a different format.
You might check out this series of Railscasts, which talks about has-many relationships and forms in the context of REST:
Complex Forms Part 1
Complex Forms Part 2
Complex Forms Part 3
I don't know RoR, so I will make generate statements on REST.
REST and ROI treats the URLs as series of nouns, and it uses HTTP methods like GET, POST, PUT, and DELETE as the verbs. This model works for CRUD, and even for models with multiple associations. Since URLs represent resources, associated objects can be expressed as list of URLs.
However if your system requires more fine-grain verbs like validate, move, copy, honk, read, write etc. it may not suit REST.
disclaimer: I know rails, but I still am pretty much a newbie.
Short Answer: REST and form helpers are completely different areas.
Long answer:
As I understand it,Representational State Transfer is only loosely related to the actual rendering of forms and views.
REST really has to do with controllers, and to a certain extend models. The idea is that instead of trying to think about an entire conversation with a client, you write a webapp to respond in specific, predictable ways to individual client messages.
i.e., if a client GETs a model, you just retrieve it, format it for them, send it to them, and forget about it.
if a client POSTS an update of some sort, you change the webapps state to reflect that, send back any response, and then forget about it. Any future GET or POST will look at the new state, but not the message that created it.
So, really, whether or not an application is RESTful depends not really on how complicated the model is, but on how users interact with it. An app meant to be at least somewhat client-agnostic, that is data-centric, is a good candidate for REST. Something that relies heavily on sessions, and interacting with a specific user, and is process-centric, might not be such a good candidate.
On the other hand, you have Rails form helpers. These are great for scaffolding, but sometimes can be frustrating when you try to use them in more complicated ways.
So, what is your main question? Do you have a specific question about rails form helpers? about rails controllers? or something specific to REST?