DEV Community

loading...

pass a block to parent Controller in Rails

n350071 profile image n350071πŸ‡―πŸ‡΅ ・1 min read

Overview

I have 3 classes. They are the STI structured classes.
( I believe this way is useful even if you don't use STI. The following explains is just an example of using block. )

class Medium < ApplicationRecord; end
class Photo < Medium; end
class Video < Medium; end

And then, I've got 3 classes of the controllers.

class MediaController < ApplicationController; end
class PhotosController < MediaController; end
class VideoController < MediaController; end

The code could be like this.(but I don't like it.)

class MediaController < ApplicationController; end

class PhotosController < MediaController
  def update
    @photo = Photo.find(photo_params[:id])
    if @photo.update(name: photo_params[:name])
      render json: @photo, status: :ok
    else
      render json: @photo.errors, status: :unprocessable_entity
    end
  end

  private
  def photo_params
    params.require(:photo).permit(:id, :name, :album_id, :file)
  end
end

class VideoController < MediaController
  # 😭 There should be ALMOST SAME code with PhotosController in here πŸ˜“
end

We have the block and it's enabled in ControllersπŸ‘

So, We can write it, like this.
Thanks, Gods(Rails committers) It's Useful!!

class MediaController < ApplicationController
  def update
    @medium, medium_params = yield
    if @medium.update(name: medium_params[:name])
      render json: @medium, status: :ok
    else
      render json: @medium.errors, status: :unprocessable_entity
    end
  end
end

class PhotosController < MediaController
  def update
    super do
      [Photo.find(photo_params[:id]), photo_params]
    end
  end

  private
  def photo_params
    params.require(:photo).permit(:id, :name, :album_id, :file)
  end
end

class VideoController < MediaController
  #  πŸŽ‰ There should be only the code which is difference from PhotosController
end

This idea is from ...

Discussion (0)

pic
Editor guide