Home > Back-end >  Ruby on Rails Route Model Binding
Ruby on Rails Route Model Binding

Time:08-29

I’ve semi-recently begun working with Ruby/Rails. As a frequent user of Laravel (and Spring), I’ve been delighted to find that Rails follows a similar convention, and supports many of the features I’ve come to love in Laravel. One feature that I have not been able to get a concise answer on though, is if Rails allows for what Laravel defines as “Route Model Binding”. Essentially, you define your route to your controller, and in your controller’s rest methods, you can do something like:

public function put(Account $account, Account $accountData)
{
  $this->validateParms($accountData);
  $account.save($accountData);
}

Even when using Spring, Jaxson allows for similar automagic object serialization in method routing

@PutMapping("/account/{id}")
public ResponseEntity<?> updateAccount(@PathVariable int accountId, @RequestBody AccountDto accountDto) 
{
  ...
  Account account = mapper.map(accountDto, Account.class);
  accountService.updateAccount(account);
  ...
} 

So I'm essentially wondering if Rails offers some sort of similar automagic sugar, without having to do a before_action hook

class AccountController < ApplicationController
  before_action :getModel

  def getModel
    @current_account = Account.find_by_id(params[:id])
  end

  def update_account(account_data)
    @current_account.update(account_data)
  end
end 

CodePudding user response:

Ruby on Rails doesn't support something like this automatically out of the box. Rails convention is to use a callback method as you already described. When you use a generator to create a controller for you, it would generate a callback method like this:

class AccountController < ApplicationController
  before_action :set_account, only: [:show, :edit, :update, :destroy]

  def update
    if @account.update(account_params)
      redirect_to @account, notice: 'Account was successfully updated.'
    else
      render :edit
    end
  end

  private 

  def set_account
    @account = Account.find(params[:id])
  end

  def account_params
    params.require(:account).permit(...)
  end
end

You could certainly add a generic callback to your AccplicationController that dynamically sets an instance variable and guesses the correct name from the controller's name. But I would argue that such a generic callback doesn't improve the readability and maintainability of the controllers.

I suggest using Ruby on Rails' generators instead.

  • Related