Domanda

Sono davvero molto Rails (anche se sono generalmente Restless), e mi piace Rubino essere molto OO. Eppure, la tendenza a realizzare enormi sottoclassi ActiveRecord e controller enormi è del tutto naturale (anche se si utilizza un controller per risorsa). Se si dovesse creare mondi degli oggetti più profondi, dove mettereste le classi (e moduli, suppongo)? Sto chiedendo di vista (nelle aiutanti se stessi?), I controller e modelli.

Lib è a posto, e ho trovato alcune soluzioni per farlo ricaricare in un ambiente dev , ma mi piacerebbe sapere se c'è un modo migliore per fare questa roba. Sono davvero solo preoccupati per le classi che crescono troppo grande. Inoltre, per quanto riguarda motori e come si inseriscono in?

È stato utile?

Soluzione

A causa Rails fornisce la struttura in termini di MVC, è naturale per finire con solo i contenitori modello, View, Controller e che sono forniti per voi. L'idioma tipico per i principianti (e anche alcuni programmatori intermedi) è di stipare ogni logica in app nel modello (classe di database), controller o vista.

A un certo punto, qualcuno sottolinea il "modello di grasso, magro-regolatore" paradigma, e gli sviluppatori intermedi fretta accise di tutto, dai loro controllori e gettarlo nel modello, che inizia a diventare un nuovo cestino per la logica dell'applicazione.

controllori Skinny sono, infatti, una buona idea, ma il corollario -. Mettere tutto nel modello, non è davvero il miglior piano

In Ruby, di avere un paio di buone opzioni per rendere le cose più modulare. Una risposta abbastanza popolare è quella di utilizzare solo moduli (di solito stashed in lib) che fissano i gruppi di metodi, e quindi includono i moduli in classi appropriate. Questo aiuta nei casi in cui si hanno categorie di funzionalità che si desidera riutilizzare in più classi, ma in cui la funzionalità è ancora teoricamente attaccato alle classi.

Ricordate, quando si include un modulo in una classe, i metodi diventano metodi della classe dell'istanza, quindi è ancora finire con una classe che contiene un ton di metodi, sono solo organizzate ben in più file.

Questa soluzione può funzionare bene in alcuni casi - in altri casi, si sta andando a voler pensare di utilizzare le classi nel codice che sono non modelli, visualizzazioni o controllori.

Un buon modo per pensare a questo proposito è il "principio di responsabilità singolo," che dice che una classe dovrebbe essere responsabile di un singolo (o piccolo numero) delle cose. I suoi modelli sono responsabili per la persistenza dei dati dalla vostra applicazione al database. I suoi controllori sono responsabili per la ricezione di una richiesta e la restituzione di una risposta valida.

Se si dispone di concetti che non rientrano esattamente in quelle scatole (persistenza, richiesta / risposta di gestione), probabilmente avrete bisogno di pensare a come si sarebbe modello l'idea in questione. È possibile memorizzare le classi non-modello in app / classi, o in qualsiasi altro luogo, e aggiungere quella directory al vostro percorso di carico facendo:

config.load_paths << File.join(Rails.root, "app", "classes")

Se stai usando passeggero o JRuby, probabilmente anche da aggiungere il vostro cammino verso i percorsi di carico ansiosi:

config.eager_load_paths << File.join(Rails.root, "app", "classes")

La linea di fondo è che una volta che si arriva a un punto in Rails in cui vi trovate con questa domanda, è il momento di rinforzare i riff di Ruby e iniziare a classi di modellazione che non sono solo le classi MVC che Rails si dà da predefinito.

Aggiornamento:. Questa risposta vale per Rails 2.xe superiore

Altri suggerimenti

Aggiorna : L'uso di preoccupazioni sono state confermato come il nuovo default in Rails 4 .

In realtà dipende dalla natura del modulo stesso. Io di solito metto le estensioni del controller / modello in una cartella / preoccupazioni all'interno di app.

# concerns/authentication.rb
module Authentication
  ...
end    

# controllers/application_controller.rb
class ApplicationController
  include Authentication
end



# concerns/configurable.rb
module Configurable
  ...
end    

class Model 
  include Indexable
end 

# controllers/foo_controller.rb
class FooController < ApplicationController
  include Indexable
end

# controllers/bar_controller.rb
class BarController < ApplicationController
  include Indexable
end

/ lib è la mia scelta preferita per le librerie di uso generale. Ho sempre un namespace progetto in lib dove ho messo tutte le librerie specifiche per l'applicazione.

/lib/myapp.rb
module MyApp
  VERSION = ...
end

/lib/myapp/CacheKey.rb
/lib/myapp/somecustomlib.rb

estensioni fondamentali rubino / Rails si svolgono in inizializzatori config modo che le librerie vengono caricati solo una volta sulle rotaie boostrap.

/config/initializer/config.rb
/config/initializer/core_ext/string.rb
/config/initializer/core_ext/array.rb

Per frammenti di codice riutilizzabili, spesso crea (micro) plugin in modo che posso riutilizzare in altri progetti.

i file di supporto di solito detiene metodi di supporto e, talvolta, le classi quando l'oggetto è destinato ad essere utilizzato dai collaboratori (ad esempio Form Costruttori).

Questa è una panoramica molto generale. Si prega di fornire maggiori dettagli su esempi specifici se si vuole ottenere suggerimenti più personalizzati. :)

  

... la tendenza a fare enormi   sottoclassi ActiveRecord e enorme   controller è del tutto naturale ...

"enorme" è una parola preoccupante ...; -)

Come sono i controller diventano enormi? Questo è qualcosa che si dovrebbe guardare: idealmente, i controllori devono essere sottili. Raccogliendo una regola empirica dal nulla, io suggerirei che se avete regolarmente più di, diciamo, 5 o 6 righe di codice per il metodo di controllo (azione), poi i controller sono probabilmente troppo grasso. C'è duplicazioni che potrebbero trasferirsi in una funzione di supporto o di un filtro? C'è logica di business che potrebbe essere spinto verso il basso nei modelli?

Come i vostri modelli di arrivare a essere enorme? Se siete alla ricerca di modi per ridurre il numero delle responsabilità in ogni classe? Ci sono comportamenti comuni è possibile estrarre in mixins? Oppure aree di funzionalità è possibile delegare a classi di supporto?

EDIT: Cercando di espandere un po ', si spera non distorcere qualcosa di troppo male ...

Helpers: vivere in app/helpers e sono per lo più utilizzati per rendere più semplice vista. Sono entrambi i controller specifici (disponibile anche per tutte le viste per tale controller) o generalmente disponibili (module ApplicationHelper in application_helper.rb).

Filtri: Diciamo che avete la stessa riga di codice in diverse azioni (molto spesso, il recupero di un oggetto utilizzando params[:id] o simili). La duplicazione può essere estratta primo a un metodo separato e poi su azioni interamente dichiarando un filtro nella definizione della classe, come before_filter :get_object. Vedere la sezione 6 nel Guida ActionController Rails Sia programmazione dichiarativa essere tuo amico.

modelli di refactoring è un po 'più di una cosa religiosa. Discepoli di zio Bob si suggeriscono, per esempio, che si seguono le cinque ordini di SOLID . Joel e Jeff può raccomandare un ehm, approccio più "pragmatico", anche se hanno fatto sembrano essere un po 'più riconciliato successivamente. Trovare uno o più metodi di una classe che operano su un sottoinsieme ben definito dei suoi attributi è un modo per cercare di identificare le classi che potrebbero essere refactoring dal vostro modello di ActiveRecord-derivato.

Rotaie modelli non devono essere sottoclassi di ActiveRecord :: Base, tra l'altro. O, per dirla in altro modo, un modello non deve essere un analogo di un tavolo, o anche correlate a qualsiasi informazione archiviata a tutti. Ancora meglio, fino a quando il nome del tuo file in app/models secondo le convenzioni Rails' (chiamata #underscore sul nome della classe per scoprire cosa Rails cercherà), Rails la troverà senza alcun require s sia necessario.

Ecco un ottimo post blog su di refactoring i modelli di grasso che sembrano derivare dalla filosofia "controllo sottile":

http: / /blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/

messaggio di base è "Non estrarre Mixin da modelle Fat", classi di servizio utilizzato, in alternativa, l'autore fornisce 7 modelli di farlo

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top