Tworzę klejnotu Ruby i chciałbym rozszerzyć ActiveRecord :: Migration przy pomocy moich własnych pomocników do tworzenia niezbędnych kolumn. (Jest to podobne do tego, co tworzy Devise podczas tworzenia migracji dla ich różnych strategii uwierzytelniania.) Zdaję sobie sprawę, że dodawana przeze mnie funkcjonalność jest dość trywialna i prawdopodobnie istnieją lepsze/bardziej wydajne sposoby robienia tego - próbuję tego jako uczenie się, a nie jako coś praktycznego zastosowania. Chcę tylko zrozumieć, jak zrobić coś tak inwazyjnego, jak dodanie nowych możliwości migracji w Railsach.Jak rozszerzyć ActiveRecord :: Migration za pomocą dodatkowych metod?
Co mam dotąd buduje się gem pomyślnie i instaluje, ale gdy próbuję uruchomić migrację takiego:
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
... to zawiedzie mówiąc, że hideable nie jest zdefiniowana.
Zajrzałem do tego, w jaki sposób Devise to zrobił i muszę przyznać, że jestem trochę zagubiony, ale próbowałem się z tym pogodzić. Zrobiłem następujący:
Rozszerzone ActiveRecord z moich nowych modeli dodatkami i stworzył metodę, aby zastosować zmiany schematu opartego na moich nowych metod migracji
require 'orm_adapter/adapters/active_record'
module HiddenRecord
module Orm
# This module contains some helpers and handle schema (migrations):
#
# create_table :accounts do |t|
# t.hideable
# t.tracks_hidden_timestamp
# end
#
module ActiveRecord
module Schema
include HiddenRecord::Schema
# Tell how to apply schema methods.
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
Utworzono moduł schematu podobnego do opracowania-tych schema.rb który definiuje metody chcę użyć w migracji i wywołuje metodę zastosować schemat
module HiddenRecord
# Holds schema definition for hiddenrecord model options.
module Schema
# Sets the model as having hidable rows
#
# == Options
# * :null - When true, allows the hidden row flag to be null
# * :default - Used to set default hidden status to true. If not set, default is false (rows are not hidden)
def hideable(options={})
null = options[:null] || false
default = options[:default] || false
apply_hiddenrecord_schema :hiddenrecord_is_row_hidden, Boolean, :null => null, :default => default
end
# Sets the model to record the timestamp when a row was hidden
def tracks_hidden_timestamp()
apply_hiddenrecord_schema :hiddenrecord_hidden_at, DateTime
end
end
end
Dodano metody modeli w celu wspierania nowych pól
module HiddenRecord
module Models
# This module implements the hideable API
module Hideable
def self.included(base)
base.class_eval do
extend ClassMethods
end
end
scope :visible, 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
załadować pliki schematów i modeli oraz w głównym module gem
module HiddenRecord
autoload :Schema, 'hiddenrecord/schema'
autoload :Models, 'hiddenrecord/models'
...
end
require 'hiddenrecord/models/hideable'
require 'hiddenrecord/models/tracks_hidden_timestamp'
Ponownie, uznając, że jest to przede wszystkim uczenie się, mam nadzieję, że ktoś może wskazać mi właściwy kierunek, jak to zrobić. Próbuję to na Rails 3.
Nawiasem mówiąc, jeśli używasz tego do DRY up kodu w migracji, może zwrócić uwagę na zapach kodu, ponieważ powtarzają pola w całym modelu danych.Może to oznaczać, że powinieneś znormalizować swój model danych, aby ograniczyć duplikowanie. – BlueFish