Рефакторинг с некоторым динамическим программированием? - PullRequest
0 голосов
/ 26 декабря 2008

У меня есть фрагмент кода, который я действительно мог бы использовать с помощью рефакторинга. Мне нужны разные методы для добавления реляционных данных в форму в рельсах. Код взят из http://railscasts.com/episodes/75-complex-forms-part-3, Моя проблема в том, что мне нужно иметь методы как для модели Материал, так и для модели Ответ. Поэтому мне нужен один и тот же код дважды с заменой «материалов» на «ответов».

Кажется, это нужно решить с помощью динамического программирования? Но у меня нет никакого опыта с этим.

Как это решается?

after_update :save_materials
after_update :save_answers  

def new_material_attributes=(material_attributes)
  material_attributes.each do |attributes|
    materials.build(attributes)
  end
end

def existing_material_attributes=(material_attributes)
  materials.reject(&:new_record?).each do |material|
    attributes = material_attributes[material.id.to_s]
    if attributes
      material.attributes = attributes
    else
      materials.delete(material)
    end
  end
end

def save_materials
  materials.each do |material|
    material.save(false)
  end
end

Ответы [ 2 ]

5 голосов
/ 26 декабря 2008

Вы также можете посмотреть на этом сайте:

http://refactormycode.com/

1 голос
/ 26 декабря 2008

Если я вас правильно понял, вы хотите использовать те же методы для answers, что и для materials, но с дублированием наименьшего кода. Способ сделать это - абстрагировать некоторые частные методы, которые будут работать для answers или materials, и вызывать их с соответствующей моделью из методов, специфичных для этих моделей. Я дал образец ниже. Обратите внимание, что я ничего не делал с save_ методами, потому что я чувствовал, что они были достаточно короткими, и их абстракция действительно не сильно экономила.

after_update :save_materials
after_update :save_answers  

// Public methods

def new_material_attributes=(material_attributes)
  self.new_with_attributes(materials, material_attributes)
end

def new_answer_attributes=(answer_attributes)
  self.new_with_attributes(answers, answer_attributes)
end

def existing_material_attributes=(material_attributes)
  self.existing_with_attributes(materials, material_attributes)
end

def existing_answer_attributes=(answer_attributes)
  self.existing_with_attributes(answers, answer_attributes)
end

def save_materials
  materials.each do |material|
    material.save(false)
  end
end

def save_answers
  answers.each do |answer|
     answer.save(false)
  end
end

// Private methods    

private
def new_with_atttributes(thing,attributes)
    attributes.each do |attribute|
       thing.build(attribute)
    end
end

def existing_with_attributes=(things, attributes)
  things.reject(&:new_record?).each do |thing|
    attrs = attributes[thing.id.to_s]
    if attrs
      thing.attributes = attrs
    else
      things.delete(thing)
    end
  end
end
...