At the moment I store each option in its own class attribute but this leads to hard to read code when I need to access the passed options from instance methods.
For example if I pass a column name as an option I have to use self.send(self.class.path_finder_column)
to get the column value from an instance method.
Notice I have prefixed the class attribute with the name of my plugin to prevent name clashes.
Here is a simple code example of a plugin which is passed an option, column
, which is then accessed from the instance method set_path
. Can the getters/setters be simplified to be more readable?
# usage: path_find :column => 'path'
module PathFinder
def path_finder(options = {})
send :include, InstanceMethods
# Create class attributes for options
self.cattr_accessor :path_finder_column
self.path_finder_column = options[:column]
module InstanceMethods
def set_path
# setter
self.send(self.class.path_finder_column + '=', 'some value')
# getter
self.send(self.class.path_finder_column)
end
end
end
end
ActiveRecord::Base.send :extend, PathFinder
You can generate all those methods at runtime.
module PathFinder
def path_finder(options = {})
# Create class attributes for options
self.cattr_accessor :path_finder_options
self.path_finder_options = options
class_eval <<-RUBY
def path_finder(value)
self.#{options[:column]} = value
end
def path_finder
self.#{options[:column]}
end
RUBY
end
end
ActiveRecord::Base.send :extend, PathFinder
Unless you need to store the options, you can also delete the lines
self.cattr_accessor :path_finder_options
self.path_finder_options = options
Note that my solution doesn't need a setter and a getter as long as you always use path_finder
and path_finder=
.
So, the shortest solution is (assuming only the :column option and no other requirements)
module PathFinder
def path_finder(options = {})
# here more logic
# ...
class_eval <<-RUBY
def path_finder(value)
self.#{options[:column]} = value
end
def path_finder
self.#{options[:column]}
end
RUBY
end
end
ActiveRecord::Base.send :extend, PathFinder
This approach is similar to the one adopted by acts_as_list
and acts_as_tree
.