2012-03-15 19 views
10

Sto cercando di astrarre parte della logica necessaria per ritagliare le immagini in un modulo in modo che non faccia male ai miei modelli. Il codice si basa su http://railscasts.com/episodes/182-cropping-imagesruby ​​include vs extend

module CroppableImage 
    def croppable_image(*image_names) 
    image_names.each do |image_name| 

     define_method "#{image_name}_sizes" do 
     { :cropped => read_attribute("#{image_name}_size").to_s, :large => "800x800>" } 
     end 

     define_method "#{image_name}_geometry" do |style| 
     style ||= :original 
     @geometry ||= {} 
     @geometry[style] ||= Paperclip::Geometry.from_file(eval "#{image_name}.path(style)") 
     end 

     define_method "#{image_name}_aspect_ratio" do 
     width, height = read_attribute("#{image_name}_size").split("x") 
     width.to_f/height.to_f 
     end 

     private 

     define_method "reprocess_#{image_name}" do 
      eval "#{image_name}.reprocess!" 
     end 

    end 
    end 

end 

Per includere questo nel mio modello sembra che devo usare estendere. Pensavo che l'estensione fosse per includere i metodi di classe. Vengo da uno sfondo java - pensavo che usando ext si basasse fondamentalmente il metodo statico sulla classe.

class Website < ActiveRecord::Base 
    extend CroppableImage 
    croppable_image :logo, :footer_image 

- questo funziona

Sembra allora che quello che sto veramente voglia è quella di creare metodi di istanza.

class Website < ActiveRecord::Base 
    include CroppableImage 
    croppable_image :logo, :footer_image 

- Questo genera l'errore "metodo non definito` croppable_image' per #"

Qualcuno può spiegare cosa sta succedendo e se dovrei usare includere o ampliare in questo caso. Grazie ragazzi

+1

'extend' aggiunge i metodi come metodi di classe, mentre' include' aggiunge i metodi come metodi di istanza. – zeacuss

risposta

13

extend M è internamente simili a class << self; include M; end - extend include modulo nella classe singleton di un oggetto (e rende i metodi del modulo di istanza per essere un metodo di una classe singleton si estende).

Nel tuo caso si chiamano croppable_imagenel contesto di una definizione di classe e quindi croppable_image dovrebbe essere un metodo di istanza di una classe o di un metodo Class Singleton di Website di classe.

Questo è il motivo si dovrebbe estendere Website classe con un modulo CroppableImage utilizzando estendono CroppableImage - aggiunge metodo di istanza croppable_image come metodo di Singleton Website di classe.

+0

Penso di averlo finalmente capito. croppable_image è un metodo di classe ma i metodi definiti con define_method diventano metodi di istanza. Ho appena letto http://stackoverflow.com/questions/302789/can-i-fine-method-in-rails-models e ora tutto ha molto più senso. Grazie per il tuo aiuto – Nick

+0

@Nick, Sì, 'define_method' è eseguito sulla classe' Website' e 'define_method' aggiunge * metodi di istanza * della classe' Website'. –

7

è possibile utilizzare entrambe le combinazioni. Ruby ha callback per estendere e comprendono Esempio di utilizzo della richiamata incluso

module CroppableImage 
    def self.included(base) 
    base.extend(ClassMethods) 
    end 

    module ClassMethods 
    def bar 
     puts 'class method' 
    end 
    end 

    def foo 
    puts 'instance method' 
    end 
end 
+0

un modo perfetto per farlo;) – Aghyad