# Controller Concerns



> With so many options, it might be good to think about reusability across controllers. Your current setup is flexible and if you anticipate using similar logic in other controllers, then having it in a concern makes it easily reusable.  - ChatGPT (regarding :index's QueryParamsProcessor)

***

[**Concerns**](../../topics) in Rails are a way to make large models or controllers more organized by extracting reusable pieces of functionality into mixable modules. This technique is particularly beneficial when you have methods or functionalities that are shared across multiple models or controllers.

Here's a more detailed breakdown:

#### 1. **Purpose**:

* **DRY (Don't Repeat Yourself)**: If there's code shared across multiple models or controllers, concerns help centralize that code.
* **Organization**: Concerns allow you to split large models or controllers into smaller, more focused pieces, making them easier to understand and maintain.

#### 2. **ActiveSupport::Concern**:

* `ActiveSupport::Concern` is a module provided by Rails that gives some additional functionalities over standard Ruby modules. It offers a more natural way to declare class-level methods and includes shared code.

#### 3. **Usage**:

To use a concern:

1. Create it in the `models/concerns` directory for model concerns or `controllers/concerns` for controller concerns.
2. Start the module with `extend ActiveSupport::Concern`.
3. Inside the concern, you can define regular methods which will become instance methods of the class including the concern.
4. To add class methods, you can use the `class_methods` block.
5. To execute code when the module is included in a class, use the `included` block.

#### 4. **Example**:

Let's say you have methods related to "taggable" functionality that you want to share across different models.

```ruby
# app/models/concerns/taggable.rb
module Taggable
  extend ActiveSupport::Concern

  included do
    has_many :tags
  end

  def list_tags
    tags.pluck(:name).join(", ")
  end

  class_methods do
    def top_tags(limit = 10)
      # some class method logic here
    end
  end
end

# In your model:
class Article < ApplicationRecord
  include Taggable
end

class Product < ApplicationRecord
  include Taggable
end
```

In the above example, both `Article` and `Product` will have the `list_tags` instance method and the `top_tags` class method. Additionally, when the module is included, the `has_many :tags` association is set up due to the `included` block.

#### 5. **Things to Keep in Mind**:

* **Granularity**: It can be tempting to move lots of code into concerns. However, avoid making them too granular. If something is used only in one model, it may not make sense to put it in a concern.
* **Overuse**: Avoid using concerns just for the sake of using them. It should make logical sense to extract functionality into a concern.
* **Naming**: Name the concern in a way that clearly indicates its responsibility. For example, `Taggable` makes it evident that it's about tagging functionality.

In summary, concerns in Rails provide a structured way to share functionality across models or controllers and help in keeping the codebase DRY and organized.
