Search code examples
ruby-on-railsrubymodulemodelcontroller

Where to store 'concerns' in a Ruby on Rails project? (Rails 5.2+)


I am fairly new to RoR. I have spent the afternoon reading about modules (used as concerns). I have yet to find a good article which describes the file path that using include or extend methods looks up (if include and extend are methods?).

The most specific example I have found was here: Ruby On Rails - Using concerns in controllers. This makes me feel that if I wanted to include the 'Bar' module in my Foo model I would create a concerns/ directory in my models/ directory, and create a 'Bar' module file in this folder.

# in models/concerns/bar.rb
modlue Bar
  # do I need this???
  extend ActiveSupport::Concern

  def speak_bar
    puts "model module bar!"
  end
end

# in models/foo.rb
class Foo < ApplicationRecord
  include Bar
end

# I could then perform:
Foo.new.speak_bar
=> "model module bar!"

And if I wanted to include a Bar module in my Foo controller I would do:

# in controllers/concerns/bar.rb
modlue Bar
  # Again, do I need this???
  extend ActiveSupport::Concern

  def speak_bar
    return "controller module bar!"
  end
end

# in controllers/foo.rb
class FoosController < ApplicationController
  include Bar

  def make_bar
    @bar = speak_bar
  end
end

# I could then use @bar in my views (anywhere else?) as <%= @bar %> and get it to output 
=> "controller module bar!"

Summary of questions:

Is this understanding set out above correct in terms of the file paths?

And do I need to use the extend ActiveSupport::Concern line in order to use this path system?

Are include and extend methods?

Thank you for your help.


Solution

  • the file path that using include or extend Rails does some magic when starting to autoload a lot of things so you don't have to worry later when you call "Bar". This talk is really helpfull to understand WHY you can just do include Bar inside a rails model without much thinking https://www.youtube.com/watch?v=I0a5zv7uBHw

    Usually, you want model related concerns inside /app/models/concerns and controller related concerns inside /app/controllers/concerns, but that's just for organization purposes, rails will autoload them even if you use /app/whatever/concerns, so be carefull about name collisions.

    You DO need to extend ActiveSupport::Concern if you want to use the syntax sugar that Concerns provide, but at the end they are just modules that can be included. https://api.rubyonrails.org/classes/ActiveSupport/Concern.html check this examples, concerns are just a way to write modules to share behaviour with a more friendly syntax for common rails patterns.

    extend is a method of Object https://docs.ruby-lang.org/en/2.6.0/Object.html#method-i-extend include is a method of Module https://docs.ruby-lang.org/en/2.6.0/Module.html#method-i-include (and Module inherits extend from Object)