6

Based on my current understanding, if I had to describe how the various components of a rails app work together to respond to requests, I would say the following:

1) Routes determine which request URLs map to which controller methods.

2) Controller methods obtain information from the models and pass that information (in the form of global variables) to corresponding view templates.

3) View templates use the data stored in the global variables to construct the final response.

In the above explanation, the relationships between several components are clear and undeniable; namely:

1) routes and controller methods

2) controller methods and view templates

In fact, the above relationships are 1-to-1.

However, the relationship of the model classes to their adjacent component type (i.e. controllers) is not as clear. Yes, the controllers retrieve information from the models, but consider the following:

1) A controller does not necessarily need to retrieve information from a model, as would be the case for a static website.

2) A controller could retrieve information from multiple model classes.

Therefore, would it be accurate to say that models exist slightly more separately from the other components? Would it be accurate to say that, taken together, the model classes make up the back-end of the back-end of your application, whereas the other components (i.e. routes, controller methods, and view templates) compose a tightly-coupled, linear mechanism wherein the controllers dip into the model classes as necessary? And more specifically, would it be accurate to say that, at least in the context of how the rails components actually fit together, there is no natural relationship between any given controller and any given model (e.g. UserController and User)?

Yes, I know rails comes with the "resources" keyword for use in the routes file to generates RESTful routes and that things are often done in a RESTful way in rails. You could say that rails lends itself to the development of RESTful web applications. And in the context of a RESTful application, the model and controller are implicitly related to each other. But that's a description of the REST architectural style. I'm asking about rails. It seems to me that in rails itself, models are only related to controllers to the extent that the model is used in the implementation of the controller's methods - and because code organization in software is arbitrary, those relationships are arbitrary.

I'm thinking about these things because I want to add a way for users to view their own profiles. I already have a User model and a controller and views for displaying information about users. The profile page would display information from the User model, but I don't want to use the same controller or views for the user's own profile as I do for displaying information about other users. So, I plan to create a new controller and views for the profile, but use the User model to retrieve the information that gets displayed. It's an arbitrary decision, much like other arbitrary decisions made when building an app. But it wouldn't be a valid decision if for some reason models and controllers were supposed to remain tightly coupled (e.g. 1-to-1) in rails.

Can anyone confirm or refute what I'm saying?

  • A model represents a database table, and the controller orchestrates between the model and the view. There's no specific reason nor restriction that the relationship is one-to-one. In fact, it probably isn't in most of any but the simplest apps, although it's often a reasonable place to start when developing, which is why Rails will construct a new app that way. – lurker Dec 29 '14 at 22:26

2 Answers2

0

Creating independent controllers is fine. You could also create a route that points to your UsersController#show action and handle the case when the user is viewing his or her own profile there.

In a non-trivial app you will end up with controllers that do not match resources and models that do not have a controller and that's ok.

In your case, maybe all you want is a different route (ex: www.example.com/me), that doesn't mean the action logic can't be in the UsersController. In the end, it's all about keeping similar logic in one place so that it's easier to maintain.

mbillard
  • 38,386
  • 18
  • 74
  • 98
  • Thank you for your response. Your response touches on another question I have: under what circumstances is it appropriate to create a new controller? To put it another way, what does a controller class logically represent? The real relationships are between the routes and the methods defined within controller class. An app could have only one controller and work perfectly fine. So far, I've seen different controllers being used for different models (e.g. a UsersController for User, a PostsController for Posts, etc.). Which sort of brings me back to the original question I posed on this page. – lostinthecloud Dec 30 '14 at 00:43
0

For a great explanation of MVC, check out Jeff Atwood's post: http://blog.codinghorror.com/understanding-model-view-controller/

Now as for your app, one controller is just fine for displaying User's profile pages. What you should do to ensure security is that for the UsersController#show action (profile page) you should validate that it is the current user, otherwise redirect, or show error message, or show the editable page, etc.

@user = User.find(params[:id])
if current_user != @user
  render :show
else 
  render :self_profile
end

Another method you could use is:

@user = User.find(params[:id])
if current_user != @user
  @authenticated_user = true
end
render :show

Then in your view template, you can have a conditional:

<% if @authenticated_user %>
  #Edit button here, takes you to the settings page
<% else %>
  #Follow button here
<% end %>

current_user should be a helper_method defined in the application controller.

aaron-coding
  • 2,571
  • 1
  • 23
  • 31
  • Thank you for your response. It know it would be "just fine," but I'm not convinced it would be ideal. For instance, how would your solution handle displaying other user's profile pages? And how would your solution handle displaying the current user's profile page as another user would see it? – lostinthecloud Dec 30 '14 at 00:37
  • Good questions. I've updated my answer. Take a look at, for example, GitHub. Visit your own profile page, and you see the same page as someone else, but instead of a "follow" button, you have an "edit profile" button. It's unlikely that they would use a different controller for a nearly identical page. You can then have an "Edit" action which directs you to your settings, but there you can redirect someone a potentially malicious user, rather than show a modified version. As far as when to create a controller: http://stackoverflow.com/questions/8049837/when-to-create-a-new-controller-in-rails – aaron-coding Dec 30 '14 at 16:10
  • Thanks again for your response. I've come to the rlztn that the page I want to create would more accrtly be rfrred to as an "Account Dashboard" than a user prfile. Moreover, I've rlzed that inherent in the cncpt of a user profile is the assmption that it's intended to be viewed by someone other than the user himself. A user would only ever view his own prfle to see what anthr user would see. What a user needs to mnge the info dsplyed on his prfle is a dshbrd of some kind. So, I think I will use the UsersController's show action for user profile pages and make a separate account dashboard page. – lostinthecloud Dec 30 '14 at 20:24
  • Yes exactly. You got it. The account dashboard page can be the "edit" action on the users controller. This is fairly common. The reason this makes sense is because it follows RESTful architecture. Your "resource" is the User. A dashboard page exists only to edit "User" you are not editing anything else. That's my recommendation, hope that helps. – aaron-coding Dec 30 '14 at 23:45
  • Thanks again for responding. It crossed my mind to use the "edit" action in the UsersController for the "account dashboard" page, but the account dashboard page that I'm envisioning will be a starting point for many different actions a user will be able to take via the website. Editing the information that appears on his profile is just one of those actions. So, I still see the need for a dashboards controller, where the dashboard will link to the page used for editing the user's information (generated via the UsersController's edit action). What do you think about that approach? – lostinthecloud Dec 31 '14 at 01:30
  • The approach is up to you, in the final analysis. You seem to like the approach and it may work just fine. Whether or not you make a new controller, the App will probably work exactly the same in terms of user interaction. It also depends on really how many different things you want to edit on that dashboard page. It might make sense to do it the way you are describing. I don't have enough context to make the decision, but I would probably just keep it as User edit, for any User settings. If you are changing settings for many models (not just User), a Dashboard controller could be warranted. – aaron-coding Dec 31 '14 at 02:19