skip to Main Content

I have a model named “seo”

class Seo < ApplicationRecord
    belongs_to :seoable, polymorphic: true
    # more code
  end

Many models in my application has_one seo. For example

 class Post < ApplicationRecord
    has_one :seo, as: :seoable
    accepts_nested_attributes_for :seo, dependent: :destroy
    # more code
  end

My question is, what is the best way to keep params in my controllers dry. For example I have the following code in my posts_controller

def post_params
  params.require(:post).permit(seo_attributes: [:id, :title, :meta_description, :etc])
end

Every model will repeat the above. How do I keep this DRY?

4

Answers


  1. You could make one controller that has that post_params method, and then the rest of the controllers that need to use it, can inherit from that controller

    Login or Signup to reply.
  2. So if the has_one :seo, as: :seoable and accepts_nested_attributes_for :seo, dependent: :destroy are repeated in multiple models then you can use Rails Concerns for it.

    If you want to learn how to make concerns see this question

    Login or Signup to reply.
  3. You can have a base controller like the follows

    class ResourceController < ApplicationController
            private
            def resource_params
                params.require(resource_name).permit(seo_attributes: [:id, :title, :meta_description, :etc])
            end
    end
    

    And in post controller you can use them as dry like this

    class PostController < ResourceController    
                def resource_name
                    :post
                end
    end
    

    And again use in any other controller like Blog as follows

    class BlogController < ResourceController    
                    def resource_name
                        :blog
                    end
        end
    
    Login or Signup to reply.
  4. I think this is an example where you could use a concern:

    # in app/models/concern/seoable.rb
    require 'active_support/concern'
    
    module Seoable
      extend ActiveSupport::Concern
      included do
        has_one :seo, as: :seoable
        accepts_nested_attributes_for :seo, dependent: :destroy
      end
    end
    
    # in your models
    class Post < ApplicationRecord
      include Seoable
    end
    

    And for the controllers, you could add a method into AplicationController that allows simplified the call:

    # in the application_controller
    def params_with_seo_attributes(namespace)
      params.require(namespace).permit(seo_attributes: [:id, :title, :meta_description, :etc])
    end
    
    # and use it in your controllers like this
    def post_params
      params_with_seo_attributes(:post)
    end
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search