2008-12-26 5 views
0

J'ai un morceau de code ici que je pourrais vraiment utiliser une aide avec le refactoring. J'ai besoin des différentes méthodes pour ajouter des données relationnelles sous forme de rails. Le code est pris de http://railscasts.com/episodes/75-complex-forms-part-3, mon problème est que j'ai besoin d'avoir les méthodes à la fois le modèle matériel et le modèle de réponse. J'ai donc besoin du même code deux fois avec "matériaux" remplacés par "réponses".Refactor avec une programmation dynamique?

Il semble que cela devrait être résolu avec une programmation dynamique? Mais je n'ai aucune expérience avec ça.

Comment cela est-il résolu?

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 

Répondre

1

Si je vous ai bien compris, vous voulez avoir les mêmes méthodes pour answers que pour materials, mais dupliquer le moins de code. La façon de procéder est de faire abstraction de certaines méthodes privées qui fonctionneront pour answers ou materials et de les appeler avec le modèle approprié à partir des méthodes spécifiques à ces modèles. J'ai donné un exemple ci-dessous. Notez que je n'ai rien fait avec les méthodes save_ parce que je pensais qu'elles étaient suffisamment courtes pour que les abstractions ne les épargnent pas vraiment.

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 
Questions connexes