Ich erstelle ein Ruby-Gem und möchte ActiveRecord::Migration mit meinen eigenen Hilfsprogrammen erweitern, um die erforderlichen Spalten zu erstellen. (Das ist ähnlich wie bei Devise, wenn sie Migrationen für ihre verschiedenen Authentifizierungsstrategien erstellen.) Mir ist bewusst, dass die Funktionalität, die ich hinzufüge, selbst ziemlich trivial ist und es wahrscheinlich bessere/effizientere Möglichkeiten gibt, dies zu tun - ich versuche dies als Lernerfahrung, nicht als etwas mit praktischem Nutzen. Ich möchte einfach verstehen, wie man etwas so tiefgreifendes wie das Hinzufügen neuer Migrationseigenschaften in Rails macht.
Was ich bisher erstellt habe, baut erfolgreich in ein Gem ein und installiert sich, aber wenn ich versuche, eine Migration wie folgt auszuführen:
class CreatePosts < ActiveRecord::Migration
def self.up
create_table :posts do |t|
t.string :name
t.string :title
t.text :content
t.hideable
t.tracks_hidden_at
t.timestamps
end
end
end
... schlägt es fehl und sagt, dass hideable nicht definiert ist.
Ich habe mir angesehen, wie Devise das gemacht hat, und ich muss zugeben, dass ich ein wenig verloren bin, aber ich habe versucht, mich durchzuarbeiten. Ich habe Folgendes gemacht:
Erweitert ActiveRecord mit meinen neuen Modell-Ergänzungen und eine Methode erstellt, um die Schema-Änderungen basierend auf meinen neuen Migrationsmethoden anzuwenden
require 'orm_adapter/adapters/active_record'
module HiddenRecord
module Orm
# Diese Modul enthält einige Hilfsprogramme und behandelt das Schema (Migrationen):
#
# create_table :accounts do |t|
# t.hideable
# t.tracks_hidden_timestamp
# end
#
module ActiveRecord
module Schema
include HiddenRecord::Schema
# Sagt, wie Schema-Methoden angewendet werden.
def apply_hiddenrecord_schema(name, type, options={})
column name, type.to_s.downcase.to_sym, options
end
end
end
end
end
ActiveRecord::Base.extend HiddenRecord::Models
ActiveRecord::ConnectionAdapters::Table.send :include, HiddenRecord::Orm::ActiveRecord::Schema
ActiveRecord::ConnectionAdapters::TableDefinition.send :include, HiddenRecord::Orm::ActiveRecord::Schema
Ein Schema-Modul ähnlich dem Schema.rb von Devise erstellt, das die Methoden definiert, die ich in der Migration verwenden möchte, und eine Methode aufruft, um das Schema anzuwenden
module HiddenRecord
# Enthält die Schema-Definition für die Optionen des hiddenrecord-Modells.
module Schema
# Legt das Modell als Zeilen mit der Eigenschaft 'versteckbar' fest
#
# == Optionen
# * :null - Wenn true, erlaubt es, dass die versteckte Zeilenflagge null ist
# * :default - Wird verwendet, um den Standardstatus auf true festzulegen. Wenn nicht gesetzt, ist der Standardwert falsch (Zeilen sind nicht versteckt)
def hideable(options={})
null = options[:null] || false
default = options[:default] || false
apply_hiddenrecord_schema :hiddenrecord_is_row_hidden, Boolean, :null => null, :default => default
end
# Legt das Modell so fest, dass der Zeitstempel aufgezeichnet wird, wenn eine Zeile versteckt wurde
def tracks_hidden_timestamp()
apply_hiddenrecord_schema :hiddenrecord_hidden_at, DateTime
end
end
end
Methoden für die Modelle hinzugefügt, um die neuen Felder zu unterstützen
module HiddenRecord
module Models
# Dieses Modul implementiert die API für 'versteckbar'
module Hideable
def self.included(base)
base.class_eval do
extend ClassMethods
end
end
scope :sichtbar, where(:hiddenrecord_is_row_hidden => true)
def hidden?
return hiddenrecord_is_row_hidden || false
end
def hide
hiddenrecord_is_row_hidden = true
end
def hide!
hiddenrecord_is_row_hidden = true
save!
end
def unhide
hiddenrecord_is_row_hidden = false
end
def unhide!
hiddenrecord_is_row_hidden = false
save!
end
end
end
end
Das Schema- und Modelldateien laden und im Hauptmodul des Gems inkludieren
module HiddenRecord
autoload :Schema, 'hiddenrecord/schema'
autoload :Models, 'hiddenrecord/models'
...
end
require 'hiddenrecord/models/hideable'
require 'hiddenrecord/models/tracks_hidden_timestamp'
Noch einmal, wissend, dass dies hauptsächlich eine Lernerfahrung ist, hoffe ich, dass mir jemand den richtigen Weg zeigen kann, wie man das macht. Ich versuche dies auf Rails 3.
0 Stimmen
Übrigens, wenn Sie dies verwenden, um Code in Migrationen zu trocknen, kann es auf einen Code-Geruch hinweisen, da Sie Felder in Ihrem Datenmodell wiederholen. Dies könnte darauf hindeuten, dass Sie Ihr Datenmodell normalisieren sollten, um Redundanzen zu reduzieren.