chrisdow38
chrisdow38

Reputation: 15

rails helper method to find if article belongs to a certain category

I recently updated my knowledgebase app to have a pretty standard has_many through association. Previously articles belonged to a category and a category had many articles. Now it is situated as the following:

class Article < ApplicationRecord
  has_many :categorizations
  has_many :categories, :through => :categorizations

class Category < ApplicationRecord
  has_many :categorizations
  has_many :articles, :through => :categorizations, dependent: :destroy

class Categorization < ApplicationRecord
  belongs_to :article
  belongs_to :category

One of the categories I have is the "Internal" category. What I am trying to accomplish is a helper method that I can us to perform actions if a particular article has the Internal category set on it. Something like the following:

if @article.internal?
  do stuff
end

I am thinking it need to be in the articles_helper.rb file.

module ArticlesHelper

  def internal?
    figure out if @article has category "internal"
  end
end

I have the following but am thinking I am on the wrong track and could use some help:

def internal?
    @internal_cat = []
      @article.categories.each do |n|
        if (n.name == "Internal")
          @internal_cat = n.name
        end
      end
  end

Any help would be greatly appreciated!

Upvotes: 0

Views: 111

Answers (1)

max
max

Reputation: 102443

This is the wrong use case for a helper method. Helper methods are used to simplify and DRY your views, and occasionally controllers. For example the form helpers make it easier to create forms and bind models to inputs.

Helpers are modules that are mixed into the view context.

What you want here is just a plain old method on your model as it can act on self:

class Article < ApplicationRecord
  # ...
  def has_category?(name)
    categories.exists?(name: name)
  end

  def internal?
    has_category?("Internal")
  end
end

Later you can refactor this code into a module if needed but this is not the same thing as a helper. Rather its parallel inheritance through the mixin pattern.

module Categorized
  extend ActiveSupport::Concern
  included do
    has_many :categorizations, as: :resource
    has_many :categories, through: :categorizations
  end

  def has_category?(name)
    categories.exists?(name: name)
  end
end

class Article < ApplicationRecord
  include Categorized
end

class Video < ApplicationRecord
  include Categorized
end

You also want to set the dependent: :destroy option on the categorizations join table. The way you have set it up destroying an article will destroy the normalized row in categories!

class Article < ApplicationRecord
  has_many :categorizations, dependent: :destroy
  has_many :categories, through: :categorizations

class Category < ApplicationRecord
  has_many :categorizations, dependent: :destroy
  has_many :articles, through: :categorizations

Upvotes: 1

Related Questions