简体   繁体   中英

Better way of writing multiple methods with similar definition ruby

How could I improve this code so there is no duplicate code and it would allow me to add new similar methods dynamically?

  def fabric_ids=(property_name)
    @fabric_ids = [] if @fabric_ids.blank?
    @fabric_ids << $property_values[property_name]
  end

  def work_ids=(property_name)
    @work_ids = [] if @work_ids.blank?
    @work_ids << $property_values[property_name]
  end

  def type_ids=(property_name)
    @type_ids = [] if @type_ids.blank?
    @type_ids << $property_values[property_name]
  end

You can define your methods dynamically, using Module#define_method , like this:

%w(fabric_ids work_ids type_ids).each do |name|
  define_method("#{name}=") do |property_name|
    instance_variable_set(name, []) if instance_variable_get(name).blank?
    instance_variable_get(name) << $property_values[property_name]
  end
end

You might want to consider organizing this as hash. Here's one way to do that.

Code

ITEMS = [:fabric, :work, :kind]

class MyClass
  attr_accessor :ids

  def initialize
    @ids = Hash.new { |h,k| h[k] = [] }
  end

  ITEMS.each do |item|
    define_method("#{item.to_s}_properties") { properties_by_key(item) }
    define_method("add_#{item.to_s}_properties") { |*property_names|
      add_properties_by_key(item, *property_names) }  
  end

  private

  def add_properties_by_key(key, *property_names)
    property_names.each { |name| self.ids[key] << $property_values[name] }
  end

  def properties_by_key(key)
    self.ids[key]
  end
end

p MyClass.instance_methods(false)
  # [:ids, :ids=,
  #  :fabric_properties, :add_fabric_properties,
  #  :work_properties,   :add_work_properties,
  #  :kind_properties,   :add_kind_properties]

Example

$property_values = { color: "blue", weight: "heavy", cost: "average" }

my_class = MyClass.new

my_class.add_fabric_properties(:color, :weight, :cost)
my_class.add_work_properties(:weight, :cost)
my_class.add_kind_properties(:color)

p my_class.fabric_properties #=> ["blue", "heavy", "average"]
p my_class.work_properties   #=> ["heavy", "average"]
p my_class.kind_properties   #=> ["blue"]

my_class.add_kind_properties(:cost)
p my_class.kind_properties   #=> ["blue", "average"]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM