First off, I'm following the practice found here for Rails concerns (great idea!): https://gist.github.com/1014971
I'm getting an error though:
undefined method `search' for #<Class:0x5c25ea0>
app/controllers/accessories_controller.rb:6:in `index'
I DO have my /app/models/concerns/ directory loaded in /config/application.rb. So the "concern" modules ARE being loaded. Just wanted to point that out.
Here is my code:
/app/models/concerns/searchable.rb
module Searchable
extend ActiveSupport::Concern
# Add a "search" scope to the models
def self.search (search)
if search
where('name LIKE ?', "%#{search}%")
else
scoped
end
end
end
/app/models/accessory.rb
class Accessory < ActiveRecord::Base
include Searchable
...
end
/app/controllers/accessories_controller.rb
class AccessoriesController < ApplicationController
def index
@accessories = Accessory.search(params[:search])
...
end
end
A Rails Concern is a module that extends the ActiveSupport::Concern module. Concerns allow us to include modules with methods (both instance and class) and constants into a class so that the including class can use them.
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.
People use Rails concern for mainly for two things: First, to reduce the size of a model that could be separated into several models, and therefore reducing the size. Second, to avoid declaring the same class over and over again.
Using extend ActiveSupport::Concern tells Rails that we are creating a concern. The code within the included block will be executed wherever the module is included. This is best for including third party functionality. In this case, we will get an error if the before_action is written outside of the included block.
Well, with a little more toying around I figured out what is wrong!
When you're wanting to directly modify the Model from within the Module (concern), you need to wrap the functionality inside an included block.
I've changed my concern module to the following:
module Searchable
extend ActiveSupport::Concern
included do
# Add a "search" scope to the models
def self.search (search)
if search
where('name LIKE ?', "%#{search}%")
else
scoped
end
end
end
end
That is it! Hopefully this will help someone else with the same quesion!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With