# Helping devs understand concerns faster

**URL:** <https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619>\
**Category:** A May Of WTFs\
**Created:** [May 8, 2020, 6:21pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619 "2020-05-08T18:21:01Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![wwahammy](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/wwahammy/32/1493_2.png) [@wwahammy](https://discuss.rubyonrails.org/u/wwahammy)\
**Post date:** [May 8, 2020, 6:21pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/1 "2020-05-08T18:21:01Z")

</div>

One thing that took me a while to wrap my head around is concerns. Part of that is just that I hadn’t really used them before and they’re more of a Ruby (and Rails) thing that with other languages. At the same time, they’re SUPER powerful and helpful. It feels like people could see the power of Rails better if they understood Rails and concerns.

There are a set of things that could help with this:

- Putting a concern focused guide together on [guides.rubyonrails.org](http://guides.rubyonrails.org). There are a number of places where concerns are mentioned but they don’t really explain why you’d use a concern, how to use them, how concerns are already used in Rails and which concerns (and what they do) are available in Rails already for use by developers
- Have a generator for concerns. Concerns, like other parts of a rails application, belong in a particular place in the file hierarchy `app/*/concerns`, should have a particular name and structure and should be in the `concerns` subdirectory of the part of the application they relate to, i.e. a controller concern should be in `app/controllers/concerns` not `app/models/concerns`.

---

<div class="post-metadata">

**Author:** ![ghiculescu](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/ghiculescu/32/1145_2.png) [@ghiculescu](https://discuss.rubyonrails.org/u/ghiculescu)\
**Post date:** [May 8, 2020, 7:15pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/2 "2020-05-08T19:15:21Z")

</div>

Really agree with this. I’ve been writing Rails nearly 8 years. I’m not convinced I understand how to use Concerns correctly. As a result, I don’t recommend them to colleagues/Rails newbies.

ps. I know it’s not really a Rails problem, but Concerns don’t play nicely with `sorbet` at all. Which also makes them hard to recommend, since we’ve really fallen in love with `sorbet`.

---

<div class="post-metadata">

**Author:** ![Noel\_Rappin](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/noel_rappin/32/1133_2.png) [@Noel\_Rappin](https://discuss.rubyonrails.org/u/Noel_Rappin)\
**Post date:** [May 8, 2020, 7:17pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/3 "2020-05-08T19:17:03Z")

</div>

+1 on adding a generator for concerns, that seems worth doing.

I found the DHH coding videos pretty eye-opening as to how concerns are used in a very concern-friendly environment.

---

<div class="post-metadata">

**Author:** ![ghiculescu](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/ghiculescu/32/1145_2.png) [@ghiculescu](https://discuss.rubyonrails.org/u/ghiculescu)\
**Post date:** [May 8, 2020, 7:18pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/4 "2020-05-08T19:18:36Z")

</div>

do you have a link to those videos?

---

<div class="post-metadata">

**Author:** ![Noel\_Rappin](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/noel_rappin/32/1133_2.png) [@Noel\_Rappin](https://discuss.rubyonrails.org/u/Noel_Rappin)\
**Post date:** [May 8, 2020, 7:31pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/5 "2020-05-08T19:31:51Z")

</div>

Looks like the preferred home is [The Getting Real Basecamp YouTube channel](https://www.youtube.com/channel/UCdx5Dk3EWTe2i8YDA7bfl6g).

---

<div class="post-metadata">

**Author:** ![joallard](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/joallard/32/990_2.png) [@joallard](https://discuss.rubyonrails.org/u/joallard)\
**Post date:** [May 8, 2020, 9:32pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/6 "2020-05-08T21:32:01Z")

</div>

On the other side, I’ve been on Rails for about the same duration, and I couldn’t imagine my life without them. I will break out into `concerning :X do; end` at the snap of fingers.

There really seems to be an information gap here   
as there is one with Git 👀

---

<div class="post-metadata">

**Author:** ![ghiculescu](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/ghiculescu/32/1145_2.png) [@ghiculescu](https://discuss.rubyonrails.org/u/ghiculescu)\
**Post date:** [May 8, 2020, 9:48pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/7 "2020-05-08T21:48:03Z")

</div>

Hah, I thought this thread was about [ActiveSupport::Concern](https://api.rubyonrails.org/classes/ActiveSupport/Concern.html)

TIL about [Module::Concerning](https://api.rubyonrails.org/classes/Module/Concerning.html)

---

<div class="post-metadata">

**Author:** ![wwahammy](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/wwahammy/32/1493_2.png) [@wwahammy](https://discuss.rubyonrails.org/u/wwahammy)\
**Post date:** [May 8, 2020, 9:52pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/8 "2020-05-08T21:52:41Z")

</div>

I was thinking of ActiveSupport::Concern but Module::Concerning is also part of this too.

---

<div class="post-metadata">

**Author:** ![joallard](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/joallard/32/990_2.png) [@joallard](https://discuss.rubyonrails.org/u/joallard)\
**Post date:** [May 8, 2020, 10:41pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/9 "2020-05-08T22:41:35Z")

</div>

Well, yes, Module::concerning does create a module extending ActiveSupport::Concern.

They’re all concerns, which are basically just fancy modules.

---

<div class="post-metadata">

**Author:** ![fxn](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/fxn/32/12956_2.png) [@fxn](https://discuss.rubyonrails.org/u/fxn)\
**Post date:** [May 8, 2020, 11:24pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/10 "2020-05-08T23:24:12Z")

</div>

IMO, the problem with concerns, is that they are really nothing special, they are just plain Ruby modules. But the fact that a new word was introduced creates an expectation that you’re missing something. Which is something I totally understand.

A _concern_ is a module that you extract to split the implementation of a class or module in coherent chunks, instead of having one big class body. The API surface is the same one, they just help organize the code. A concern is a regular Ruby mixin, there’s nothing else, it is not a new concept. It is plain Ruby.

So, when you extract pricing-related API from a `Hotel` class, you typically do something like this:

```ruby
# app/models/hotel.rb
class Hotel
  include Pricing
end

# app/models/hotel/pricing.rb
module Hotel::Pricing
  # Hotel pricing-related logic.
end

```

There, `Hotel::Pricing` is a concern. But that idiom is not Rails-specific, this is vanilla Ruby programming.

Directories like `app/models/concerns` are meant for mixins that can be reused, in this case, in the model layer.

On the other hand, `AS::Concern` is orthogonal. A concern is a Ruby module used in a certain way (vs used as a namespace, say). Ruby has the `included` callback that gets fired when a module is included somewhere, and you receive the enclosing class or module as argument, that allows you to decorate it, for example. Well, the `included` DSL macro is essentially the same thing, except that the decoration looks prettier. It is a DSL for mixins that want to decorate their enclosing classes or modules.

But, perhaps surprisingly, a mixin does not need to extend `AS::Concern` to be a concern. Or to call `concerning`. A concern is a Ruby module with a certain purpose, as explained above, and whether you use those DSLs or not is irrelevant.

And you see the problem, concerns are so simple that they do not deserve a full guide. Concerns are mixins, if you are a Ruby programmer, you already know what a mixin is and their use case to modularize APIs.

But at the same time, a post like this is needed to explain that they are just that!

That means there is something to address here, I believe we are missing a _definition_, but don’t know exactly how to fix it.

---

<div class="post-metadata">

**Author:** ![wwahammy](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/wwahammy/32/1493_2.png) [@wwahammy](https://discuss.rubyonrails.org/u/wwahammy)\
**Post date:** [May 8, 2020, 11:52pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/11 "2020-05-08T23:52:04Z")

</div>

> [@fxn](#):
>
> And you see the problem, concerns are so simple that they do not deserve a full guide. Concerns are mixins, if you are a Ruby programmer, you already know what a mixin is and their use case to modularize APIs.

I think there’s a lot of Rails users that don’t know this. I think there’s a decent number of Ruby devs who know vaguely about mixins but they don’t use it because they don’t understand it. If you combine teaching folks how to use and create concerns properly and documenting the concerns that are already in Rails that folks can use, I think there might be enough for a guide.

I still think there’s value in a generator or something sort of assistance for helping people use concerns in a consistent way with a convention.

---

<div class="post-metadata">

**Author:** ![fxn](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/fxn/32/12956_2.png) [@fxn](https://discuss.rubyonrails.org/u/fxn)\
**Post date:** [May 9, 2020, 12:05am UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/12 "2020-05-09T00:05:24Z")

</div>

> [@wwahammy](#):
>
> I think there’s a lot of Rails users that don’t know this. I think there’s a decent number of Ruby devs who know vaguely about mixins but they don’t use it because they don’t understand it.

Maybe, but you have to draw the line somewhere, in my view it is out of the scope of Rails documentation to teach you Ruby. As a Ruby programmer, you need to learn Ruby.

As I said above, I believe there’s something to address, this thread is a proof of that, and I’ve seen others like this. But I don’t know how.

Regarding a generator, which usage have you in mind? How does the command look like? What does it generate?

---

<div class="post-metadata">

**Author:** ![wwahammy](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/wwahammy/32/1493_2.png) [@wwahammy](https://discuss.rubyonrails.org/u/wwahammy)\
**Post date:** [May 9, 2020, 12:17am UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/13 "2020-05-09T00:17:08Z")

</div>

> [@fxn](#):
>
> Maybe, but you have to draw the line somewhere, in my view it is out of the scope of Rails documentation to teach you Ruby. As a Ruby programmer, you need to learn Ruby.

I mean, if we’re here to talk about getting folks up to speed on using Rails properly I don’t think this is a great attitude to have. I get the concern (no pun intended) but I wouldn’t exclude it as something the community should evaluate.

> [@fxn](#):
>
> Regarding a generator, which usage have you in mind? How does the command look like? What does it generate?

My first though is something like this: `rails generate concern name_of_concern type_of_concern --class_methods class_method_names --included_methods included_method_names` where `type_of_concern` is model/controller/job/mailer/etc

This would:

- Place them into the `app/type_of_concern/concerns` directory
- Create a test for the concern which includes stubbed tests for each of the class methods and each of the included methods. It would also include a stubbed version of the model/controller/job/etc for including and testing the concern.

---

<div class="post-metadata">

**Author:** ![Adam\_Lassek](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/adam_lassek/32/726_2.png) [@Adam\_Lassek](https://discuss.rubyonrails.org/u/Adam_Lassek)\
**Post date:** [May 9, 2020, 12:49am UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/14 "2020-05-09T00:49:53Z")

</div>

> [@fxn](#):
>
> A concern is a regular Ruby mixin, there’s nothing else, it is not a new concept. It is plain Ruby.

The dependency-resolution between modules goes beyond mere syntactic sugar, IMO.

---

<div class="post-metadata">

**Author:** ![fxn](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/fxn/32/12956_2.png) [@fxn](https://discuss.rubyonrails.org/u/fxn)\
**Post date:** [May 9, 2020, 7:07am UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/15 "2020-05-09T07:07:01Z")

</div>

> [@Adam\_Lassek](#):
>
> The dependency-resolution between modules goes beyond mere syntactic sugar, IMO.

A _concern_ does not have syntatic sugar per se, like the `Hotel::Pricing` module above. The syntatic sugar is a feature of `AS::Concern`, different.

---

<div class="post-metadata">

**Author:** ![Betsy\_Haibel](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/betsy_haibel/32/1092_2.png) [@Betsy\_Haibel](https://discuss.rubyonrails.org/u/Betsy_Haibel)\
**Post date:** [May 9, 2020, 2:48pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/16 "2020-05-09T14:48:42Z")

</div>

@Adam_Lassek @fxn When I read the tone of your comments it seems like you’re arguing. When I read the content of your comments it seems like you’re loudly agreeing with each other (but maybe not realizing it because you’re each grabbing at a different part of the elephant.)

I’d like to summarize what I think you’re both saying, so that the “argument tone” doesn’t wind up confusing newbies who might struggle a little more to understand the content.

> The “Concern” pattern is another name for using Ruby modules as mixins. There’s nothing special about concerns when they’re done as PORMs.
> 
> However, when a module is created using `concerning` or by extending `ActiveSupport::Concern`, there’s some special dependency resolution logic that happens that is Rails-specific.

Does this feel like an accurate summary?

---

<div class="post-metadata">

**Author:** ![fxn](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/fxn/32/12956_2.png) [@fxn](https://discuss.rubyonrails.org/u/fxn)\
**Post date:** [May 9, 2020, 3:43pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/17 "2020-05-09T15:43:31Z")

</div>

There is no argument, Betsy.

This is a technical conversation about a technical topic.

---

<div class="post-metadata">

**Author:** ![Betsy\_Haibel](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/betsy_haibel/32/1092_2.png) [@Betsy\_Haibel](https://discuss.rubyonrails.org/u/Betsy_Haibel)\
**Post date:** [May 9, 2020, 3:56pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/18 "2020-05-09T15:56:30Z")

</div>

My experience is that it is often difficult, especially on the internet where tone doesn’t convey, to tell the difference between finely grained technical corrections and arguments. See also the [Social rules - Recurse Center](https://www.recurse.com/social-rules) section on “well, actuallys.”

I’d like us to be extremely careful about this within this forum, because it’s intended as a welcoming space for people to bring things that confuse them. If they feel well-actuallyed, particularly by a core team member, that shuts conversation down and we lose the data about the Rails experience that they would otherwise bring to the table.

My summary was intended as a way to add context to your discussion. If a newbie googles about concerns, then a topic on the official Rails forum called “helping devs understand concerns faster” is going to have a lot of SEO juice. I’d like any newbies reading this to come away with the correct technical impression, and I was afraid that that was getting lost within the back-and-forth.

---

<div class="post-metadata">

**Author:** ![Betsy\_Haibel](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/betsy_haibel/32/1092_2.png) [@Betsy\_Haibel](https://discuss.rubyonrails.org/u/Betsy_Haibel)\
**Post date:** [May 9, 2020, 6:00pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/19 "2020-05-09T18:00:16Z")

</div>

All that said, I fundamentally agree with @fxn’s point that PORM mixins are a Ruby basic that Rails developers need to learn about to be proficient.

I think the binary between “no help” and “smothering levels of handholding” is a false one though. Maybe we can find some solution in between?

I think the Rust compiler threads a similar needle well. Its errors are extremely helpful in guiding you away from stupid pointer mistakes. However, in order to fix those mistakes a developer will need to learn to understand pointers, the stack, and the heap; and the Rust compiler does not pretend otherwise.

I don’t think an error-oriented approach is the right one here, I think “I don’t understand what this is for” demands something more proactive. I have no idea what, but I’m hoping someone else does.

---

<div class="post-metadata">

**Author:** ![kaspth](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/kaspth/32/734_2.png) [@kaspth](https://discuss.rubyonrails.org/u/kaspth)\
**Post date:** [May 9, 2020, 6:32pm UTC](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619/20 "2020-05-09T18:32:33Z")

</div>

Yes, concerns are just modules, yet they’re also more than that. They’re also about a style of project organization. So they’re really doing a lot of work, and no wonder it’s confusing! And just like it’s not always obvious that app/models can contain POROs or other non-db backed models, it’s not obvious that app/models/concerns isn’t really where you’d put most concerns.

I’m extracting from [DHHs screencast](https://www.youtube.com/watch?v=hkmrfjex7jI) here.

We have an Active Record model that includes a concern, here expressed as just a `module`, which wraps a PORO for a nicer call API. All namespaced within `User::` and `app/models/user`. This is how the vast majority of models at Basecamp look, for instance.

Note: this is about the organization, not so much the content within, in the real app there’d be more code in these pieces.

```ruby
# app/models/user.rb
class User < ApplicationRecord
  include Notifiee
end

# app/models/user/notifiee.rb
module User::Notifiee
  # Philosophically a concern, i.e. a role a model can play, but:
  # extend ActiveSupport::Concern is not needed without included/class_methods calls.

  def notifications
    @notifications ||= User::Notifications.new(self)
  end
end

# app/models/user/notifications.rb
class User::Notifications
  attr_reader :user
  delegate :person, to: :user

  def initialize(user)
    @user = user
  end
end

```

I totally wish we had some more documentation or tooling that could push you in this direction or make it more obvious how this could work — perhaps in guides or generators.

[Next page](https://discuss.rubyonrails.org/t/helping-devs-understand-concerns-faster/74619.md?page=2)
