Rails refactoring story learned in the field

Story learned in the field

It's a general architecture that we are aware of when developing Rails.

A memorandum note that you are conscious of not becoming a fat controller or fat model. Since it is a random sentence, I will correct it as appropriate.

The controller is simple! !!

Ultimately, I think the responsibility of having the controller follow is as follows.

** "Create an instance, execute a method on it, and return a response" **

only this.

This is the worst thing to say.

ruby:example.contoroller.rb



There is no such action

def index
  @most_funded_projects = []
    most_funded_projects = Project.most_funded.includes(:main_image)
    most_funded_projects.each do |most_funded_project|
      break if @most_funded_projects.count >= 3
      if @site_project_descriptions[most_funded_project.id].present?
        @most_funded_projects << most_funded_project
      end
    end
    if @most_funded_projects.count < 4
      current_site.published_projects.order(updated_at: :desc).each do |project|
        break if @most_funded_projects.count >= 3
        @most_funded_projects << project
    end
  end 
end


Gorigori's business logic is written on the controller. I used to write such a controller, and I was careful. If you make a controller with scafold, you can make a controller with the following simple shape, but basically it is ideal to make it according to this feeling.

example.rb



def index
  @friends = Friend.all

  respond_to do |format|
    format.html # index.html.erb
    format.json { render json: @friends }
  end
end

In short, the following is the basic form

@hoge = Hoge.new
@hoge.hoge
Returns a response

If the controller swells, go to the model first! !!

In the controller, it was important to have an image of creating an instance associated with the model and executing a method on it. So once you think about putting all your business logic into the model. However, since there is another problem in putting everything together, the image of putting things in the model is mainly ** things related to persistence and business logic ** that is completed by operating a single model. is.

The patterns to be implemented in the model are generally as follows.

--Get record of table associated with model (ActiveRecord operation) --Data acquisition including related tables based on the table associated with the model --Update the data of the table associated with the model --Other business logic linked to a single model

I think that simple processing such as simple update of a single table is mainly applicable, and other than that, business logic that is completed with a single model.

Utilization of service class

Processes such as multiple model operations and file operations are cut out as a service layer as a unit of atomic business logic.

Basically, create a normal class that is not tied to ActiveRecord (it is not tied to the table one-to-one) in the following form. It's like creating a class and separating complex logic across multiple models from an existing model. It's simple to use, just create an instance of the class and execute the methods you've created for it.

exmple.rb


class ExampleService
  def initialize
    ....
  end

  def example
    ....
  end
end

Cut consern and namespace and create a class under the models directory

Even with the method introduced, if the model or service class becomes fat, cut the namespace under the models directory, create a simple class that is not one-to-one with the table, and the model or service that became fat there. There is also a technique to prevent the model and service class from becoming fat by transferring the methods that can be used for general purposes in the class. You can also use consern to combine redundant things into one. For example, it is an image that creates models / {table name} / {use case} .rb and cuts out the process. For better visibility, define instance variables in Controller.

Summary of sharing of Controller / Service / Model

--The Controller and Service layers basically perform only procedure processing *. * Procedure processing is to call a function or perform processing related to CRUD. --The Controller and Service layers only use the returned data and are not involved in logic or data processing. --The Service layer makes good use of the methods that grow in multiple models when the processing in the Controller spans multiple Models, creates methods in the service class, and mainly uses them for instances. For example, in processing that spans multiple models, the instance method that originally exists in each model that is supposed to straddle is used in the service class, the method is created in the service class, and the instance of the service class is created in the controller. Then, it takes the form of executing a method using it as a receiver. --I don't want the service class to be fat as much as possible, so if the business logic is bulky, I would like to cut the consern and namespace and create another class under the models directory. Create models / {table name} / {use case} .rb and cut out the process. In order to improve the visibility, instance variables should be defined in Controller. --Be sure to process logic and data with Model

Recommended Posts

Rails refactoring story learned in the field
The story when the test folder was not created in Rails
About the symbol <%%> in Rails erb
Asynchronous communication in the interactive comment field
The story of AppClip support in Anyca
The story of writing Java in Emacs
[Rails] Reset the database in the production environment
Rails6: Extract the image in Action Text
[Order method] Set the order of data in Rails
The story of low-level string comparison in Java
The story of making ordinary Othello in Java
[Rails Struggle/Rails Tutorial] What you learned in Rails Tutorial Chapter 6
A story about the JDK in the Java 11 era
I tried to organize the session in Rails
[Rails Struggle/Rails Tutorial] What you learned in Rails Tutorial Chapter 3
The story of learning Java in the first programming
[Rails] Show multi-level categories in the breadcrumb trail
Group_by in Rails
Implement the Like feature in Ajax with Rails.
Refactoring in JUnit
How to check Rails commands in the terminal
[Rails] I learned about the difference between resources and resources
How to set the display time to Japan time in Rails
[Ruby on Rails Tutorial] Error in the test in Chapter 3
Decimal numbers are dangerous in programming, right? The story.
The story of an Illegal State Exception in Jetty.
[Ruby / Rails] Set a unique (unique) value in the class
[Rilas] What I learned in implementing the pagination function.
[Rails Struggle/Rails Tutorial] What you learned in Rails Tutorial Chapters 4 and 5
Questions about implementing the Like feature (Ajax) in Rails
SSL in the local environment of Docker / Rails / puma
[Rails] How to display an image in the view
The story that .java is also built in Unity 2018
Ruby on Rails 5 quick learning practice guide that can be used in the field Summary
Model association in Rails
Adding columns in Rails
Disable turbolinks in Rails
CSRF measures in Rails
^, $ in Rails regular expression
Use images in Rails
Understand migration in rails
Click the [rails] button to create a random alphanumeric password and enter it in the password field
Split routes.rb in Rails6
Master the [Rails] scope!
Implement markdown in Rails
Launch the Rails app locally in production mode (API Server)
[Ruby on Rails] Quickly display the page title in the browser
The story of throwing BLOB data from EXCEL in DBUnit
A story I was addicted to in Rails validation settings
[Rails] Where to be careful in the description of validation
[Docker] The story that an error occurred in docker-compose up
Use your own classes in the lib directory with Rails6
[Rails] How to display information stored in the database in view