Rails Best Practice: Keep model logic in models or concerns
Signs
The general sign is to watch for the repetitive appearance of one or more variables inside one particular controller action. In the example below, the account
variable appears 6 times in one action which indicates that whatever logic it is doing should not belong in this controller.
The common mistake a developer often makes is the tendency of moving the repetitive code into the model immediately, not seeing where it truly belongs first. They can belong to a Concern, Service, Presenter, etc… We think that we are organizing code, but it’s only sweeping under the carpet and causing much maintenance work later on when the models getting bigger in size.
In this case, we also see the ‘subject’ variable user
is calling accounts...
. Further investigation shows that user be of an restaurant_owner
or a consumer
, therefore, this code should belong to both of these models; and that indicates that it should belong to a Rails Concern (other cases may indicate the code should be moved into a Service)
Before
def create
@account = @user.accounts.first
if !@account
@account = @user.accounts.new( account_save_params )
elsif !@account.accessible
@account.attributes = account_save_params
end if @account.save
render ‘show’
else
render json: { error: “Account Data Invalid” }, status: :unprocessable_entity
end
end
And after!
def create
@account = @user.build_or_update_account(account_save_params)
if @account.save
render :show
else
render json: { error: ‘Account Data Invalid’ }, status: :unprocessable_entity
end
end
The created concern:
module Accountable
extend ActiveSupport::Concern def build_or_update_account(account_save_params)
account ||= Account.new(account_save_params)
account.attributes = account_save_params unless account.accessible
account
end
end
It feels good to see your things clean and organized, doesn’t it? What are you waiting for, let’s give your much loved code a clean-up job today!