Global Ruby Methods on Rail Models

I have methods in all my models that look like this:

def formatted_start_date start_date ? start_date.to_s(:date) : nil end 

I would like to have something that automatically writes such a method for each datetime field in each model, what is the best way to do this?

-C

+6
ruby-on-rails activerecord model
source share
3 answers

I just had to answer this because it is a fun Ruby exercise.

Adding methods to a class can be done in many ways, but one of the easiest ways is to use some Ruby reflection and evaluation functions.

Create this file in the lib folder as lib / date_methods.rb

 module DateMethods def self.included(klass) # get all dates # Loop through the class column names # then determine if each column is of the :date type. fields = klass.column_names.select do |k| klass.columns_hash[k].type == :date end # for each of the fields we'll use class_eval to # define the methods. fields.each do |field| klass.class_eval <<-EOF def formatted_#{field} #{field} ? #{field}.to_s(:date) : nil end EOF end end end 

Now just plug it into any models he needs

  class CourseSection < ActiveRecord::Base include DateMethods end 

When enabled, the module will look at any date columns and generate formatted_ methods for you.

Find out how this Ruby works. It is very funny.

However, you should ask yourself if necessary. I donโ€™t think itโ€™s personal, but again it was fun to write.

-b -

+16
source share

This is more like something for an assistant. Try this in your help:

 def formatted_date(date) date ? date.to_s(:date) : nil end 

Formatting is not something that really belongs to the model (precisely for the reason that you discovered ... placing such common code in each model is annoying)

If you really want to do what you say, then what you could do is monkeypatch the ActiveRecord superclass and add a function there. It will be available for all your models. Remember that monkeypatching can lead to unpredictable and undefined behavior and use at your own risk! This is also pretty negligent :)

 class ActiveRecord::Base def formatted_start_date start_date ? start_date.to_s(:date) : nil end end 

Just stick to what will run earlier than anything else in your application, and it will dynamically add a method to the base class of your models, making it available for use.

Or you can create a mixin for all of your models, but that seems a bit redundant for a single method.

+11
source share

Answer to your comment: You can extract the general code / functionality into the modules that you include in the class (I believe what is called mixin?), Or you can go to subclasses. I do not think that a subclass is the way to go, when its just general functionality you want to get into your objects, and not the real situation of inheritance.

Take a look for more information on modules and Ruby .

0
source share

All Articles