0

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?

Vikram Sharma
  • 448
  • 4
  • 11

4 Answers4

2

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
spickermann
  • 81,597
  • 8
  • 83
  • 112
  • Apparently permit can be used once. I modified your code a bit. def params_with_seo_attributes [seo_attributes: [:id, :title, :meta_description, :etc]] end in my post controller def post_params permitted_params = [:foo, :bar] + params_with_seo_attributes params.require(:post).permit(permitted_params) end – Vikram Sharma Sep 21 '19 at 05:27
0

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

Jason Carty
  • 1,217
  • 1
  • 13
  • 17
0

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

Vishal
  • 751
  • 4
  • 18
0

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
user3775217
  • 4,057
  • 1
  • 17
  • 33