Zamiast tym zaniepokojenie w każdym modelu, którą proponujemy stworzenie ActiveRecord
submodule i przedłużyć ActiveRecord::Base
z nim, a następnie dodać metodę w tym modułem (słownie include_importable
), który robi to w tym. Następnie można podać nazwę pola jako argument tej metody, a także w sposobie definiowania zmiennej instancji i akcesor (powiedzmy na przykład importable_field
), aby zapisać nazwę pola dla odniesienia w swoim Importable
klasy i metody instancji.
Więc coś takiego:
module Importable
extend ActiveSupport::Concern
module ActiveRecord
def include_importable(field_name)
# create a reader on the class to access the field name
class << self; attr_reader :importable_field; end
@importable_field = field_name.to_s
include Importable
# do any other setup
end
end
module ClassMethods
# reference field name as self.importable_field
end
module InstanceMethods
# reference field name as self.class.importable_field
end
end
Będziesz wtedy trzeba przedłużyć ActiveRecord
z tego modułu, powiedzmy, umieszczając tę linię do inicjowania (config/initializers/active_record.rb
):
ActiveRecord::Base.extend(Importable::ActiveRecord)
(Jeśli problem dotyczy Twojego config.autoload_paths
, więc nie powinieneś tego wymagać, patrz komentarze poniżej.)
Następnie w swoich modelach, yo U obejmowałyby Importable
takiego:
class MyModel
include_importable 'some_field'
end
a czytelnik imported_field
zwróci nazwę pola:
MyModel.imported_field
#=> 'some_field'
W swojej InstanceMethods
można następnie ustawić wartość pola importowanego w instancji metody przekazując nazwę pola do write_attribute
i uzyskać wartość używając read_attribute
:
m = MyModel.new
m.write_attribute(m.class.imported_field, "some value")
m.some_field
#=> "some value"
m.read_attribute(m.class.importable_field)
#=> "some value"
Nadzieję, że pomaga. To tylko moje osobiste zdanie na ten temat, istnieją jednak inne sposoby, aby to zrobić (i byłbym zainteresowany, aby o nich usłyszeć).
Wielkiej odpowiedź, dziękuję. To wszystko ma sens. Spróbuję tego, co zasugerowałeś jutro i nagrodzisz rozwiązanie po tym. – Col
Wszystko działa, ale mam mały problem. Otrzymuję następujący błąd, chyba że specjalnie wymagam "dotyczy/importable" na górze każdego pliku modelu. NameError: niezdefiniowana zmienna lokalna lub metoda 'include_importable” dla # Dodałem katalog obawy do autoload_path tak: config.autoload_paths + = Dir [ "# {config.root}/app/models/**/"] To nie jest duży problem, ale wolałbym nie wymagać go wszędzie. Jakieś sugestie? –
Col
Problemem jest linia 'ActiveRecord :: Base.extend (Importable :: ActiveRecord)', która musi zostać wywołana * przed * twoje modele są ładowane, aby ActiveRecord miał metodę 'includes_importable'. Automatyczne ładowanie nie działa, ponieważ rzeczywista nazwa modułu "Importable" nie jest wymieniona w kodzie modelu. Istnieje kilka sposobów na rozwiązanie tego problemu. Najłatwiej jest utworzyć inicjator w 'config/initializers/active_record.rb' i przenieść tam linię' extend' z 'require 'concern/importable'' at szczyt. Wtedy nie będziesz musiał tego wymagać w swoich modelach. –