I have 4 common functions in every Model:
#Returns TRUE or FALSE depending on whether the column could be null or not
def self.null?(column)
columns_hash[column].null
end
#Custom delete function to change a state (deleted is a field)
def custom_delete
deleted = true
save
end
def str_created_at(format = "%d/%m/%Y %I:%M %p")
return created_at.in_time_zone.strftime(format)
end
def str_updated_at(format = "%d/%m/%Y %I:%M %p")
return updated_at.in_time_zone.strftime(format)
end
I tried to move these 4 functions (1 of them is abstract: null?) to a single module with no luck:
#config/application.rb
config.autoload_paths += Dir["#{config.root}/lib/**/"]
#app/models/post.rb
class Post < ActiveRecord::Base
include BaseModel
default_scope where(:deleted => false)
end
#lib/base_model.rb
module BaseModel
def self.included(base)
base.extend ClassMethods
end
module InstanceMethods
def custom_delete
deleted = true
save
end
def str_created_at(format = "%d/%m/%Y %I:%M %p")
return created_at.in_time_zone.strftime(format)
end
def str_updated_at(format = "%d/%m/%Y %I:%M %p")
return updated_at.in_time_zone.strftime(format)
end
end
module ClassMethods
include BaseModel::InstanceMethods
def self.null?(column)
columns_hash[column].null
end
end
end
In Rails console:
> Post.null?("title")
> NoMethodError: undefined method 'null?' for #<Class:0x3f075c0>
> post = Post.first
> post.str_created_at
> NoMethodError: undefined method 'str_created_at' for #<Post:0x2975190>
Is there any way to get these functions working fine? I found this code here on Stackoverflow but seems to be not working, at least not Rails3
I’d like to have the possibility to add these functions with only 1 line:
include BaseModel
So I can add it to other models as well.
Concerns are the solution. It’s really important to be able to modularize your application, both for rails apps that for libraries. Note that this approach can be pretty cool also when hanging with Engines.
Concerns must be placed in the concern folder, both for models and controllers. Just be careful to not use them too much. You must use it mainly when you share functionalities between your classes and when you want to make your model skinny. In the last case wait for it to be really big, otherwise concerns will become a trash directory and you’ll lose its effect.
Configure application.rb
Here you can see how to organize your model and controller concerns.
Creating concerns
You can define your concern using
ActiveSupport::Concernclass. It simplify the ‘including’ phase (you you do not have to usebaseas prefix) and it automatically load the class methods that are inside of module ClassMethod.Here an example of what change.
Here you can find a nice article that explain them much more in details.