Rails Model, View, Controller, and Helper: what go

2019-01-08 03:05发布

In Ruby on Rails Development (or MVC in general), what quick rule should I follow as to where to put logic.

Please answer in the affirmative - With Do put this here, rather than Don't put that there.

10条回答
我欲成王,谁敢阻挡
2楼-- · 2019-01-08 03:12

Do put stuff related to authorization/access control in the controller.

Models are all about your data. Validation, Relationships, CRUD, Business Logic

Views are about showing your data. Display and getting input only.

Controllers are about controlling what data goes from your model to your view (and which view) and from your view to your model. Controllers can also exist without models.

I like to think of the controller as a security guard/receptionist who directs you the customer(request) to the appropriate counter where you ask a teller (view) a question. The teller (view) then goes and gets the answer from a manager (model), who you never see. You the request then go back to the security guard/receptionist (controller) and wait until you are directed to go another teller (view) who tells you the answer the manager (model) told them in response to the other teller's (view) question.

Likewise if you want to tell the teller (view) something then largely the same thing happens except the second teller will tell you whether the manager accepted your information. It is also possible that the security guard/receptionist (controller) may have told you to take a hike since you were not authorized to tell the manager that information.

So to extend the metaphor, in my stereotyped and unrealistic world, tellers (views) are pretty but empty-headed and often believe anything you tell them, security guard/receptionists are minimally polite but are not very knowledgeable but they know where people should and shouldn't go and managers are really ugly and mean but know everything and can tell what is true and what isn't.

查看更多
beautiful°
3楼-- · 2019-01-08 03:14

To add to pauliephonic's answer:

Helper: functions to make creating the view easier. For example, if you're always iterating over a list of widgets to display their price, put it into a helper (along with a partial for the actual display). Or if you have a piece of RJS that you don't want cluttering up the view, put it into a helper.

查看更多
爱情/是我丢掉的垃圾
4楼-- · 2019-01-08 03:17

The MVC pattern is really only concerned with UI and nothing else. You shouldn't put any complex business logic in the controller as it controls the view but not the logic. The Controller should concern itself with selecting the proper view and delegate more complex stuff to the domain model (Model) or the business layer.

Domain Driven Design has a concept of Services which is a place you stick logic which needs to orchestrate a number of various types of objects which generally means logic which doesn't naturally belong on a Model class.

I generally think of the Service layer as the API of my applications. My Services layers usually map pretty closely to the requirements of the application I'm creating thus the Service layer acts as a simplification of the more complex interactions found in the lower levels of my app, i.e. you could accomplish the same goal bypassing the Service layers but you'd have to pull a lot more levers to make it work.

Note that I'm not talking about Rails here I'm talking about a general architectural style which addresses your particular problem.

查看更多
ら.Afraid
5楼-- · 2019-01-08 03:17

One thing that helps separate properly is avoiding the "pass local variables from controller to view" anti-pattern. Instead of this:

# app/controllers/foos_controller.rb:
class FoosController < ApplicationController

  def show
    @foo = Foo.find(...)
  end

end

#app/views/foos/show.html.erb:
...
<%= @foo.bar %>
...

Try moving it to a getter that is available as a helper method:

# app/controllers/foos_controller.rb:
class FoosController < ApplicationController

  helper_method :foo

  def show
  end

  protected

  def foo
    @foo ||= Foo.find(...)
  end

end

#app/views/foos/show.html.erb:
...
<%= foo.bar %>
...

This makes it easier to modify what gets put in "@foo" and how it is used. It increases separation between controller and view without making them any more complicated.

查看更多
聊天终结者
6楼-- · 2019-01-08 03:19

The Rails way is to have skinny controllers and fat models.

查看更多
SAY GOODBYE
7楼-- · 2019-01-08 03:21

Testing, Testing ... Put as much logic as possible in the model and then you will be able to test it properly. Unit tests test the data and the way it is formed by testing the model, and functional tests test the way it is routed or controlled by testing the controllers, so it follows that you can't test the integrity of the data unless it is in the model.

j

查看更多
登录 后发表回答