Render z modelu

Oczywiście wiem, że w modelu nie można wywoływać metody render ale …

Tworzę aplikację pełniącą funkcje zbliżone do CPanel. Akcje create, update i destroy dla zasobów (dns_zone, webdomain itp.) wykonane z powodzeniem powinny generować plik “zlecenia”. Jest to plik xml tworzony metodą render_to_string (plik generuje prywatna metoda kontroler make_order).
Wszystko działa OK dopóki zarządzanie zasobami odbywa się za pośrednictwem kontrolerów. Jeśli jednak chciałbym usunąć użytkownika to powinny zostać usunięte również wszystkie zasoby do niego należące. W modelu User mam:

class User < ActiveRecord::Base has_many :dns_zones, :dependent => :destroy has_many :dns_records, :dependent => :destroy has_many :sites, :dependent => :destroy (...)
Ale to zapewnia mi to jedynie usunięcie danych z bazy danych natomiast zasoby nadal pozostaną w systemie bo nie ma “zleceń”.

W jaki sposób wygenerować “zlecenia” przy takim “masowym” kasowaniu zasobów?

Możesz przerzucić generowanie zleceń do modelu i wykorzystać callbacki takie jak np. after_destroy, after_create czy after_save: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html

To, że są callback-i to ja wiem :slight_smile:

Metoda make_order np. dla stref dns wygląda tak:

[code=ruby]class DnsZonesController < ApplicationController
(…)
private
def make_order
zone = render_to_string “zone”, :formats=>[:xml]
filename = Rails.root.join(“servers”,@server.name,“o#{Time.now.to_i}.xml”)
File.open(filename, ‘w’) {|f| f.write(zone) }
end

end[/code]
Jak coś takiego zrealizować z poziomu np. befor_destroy?

Zrób sobie klasę do zarządzania plikami zleceń, coś w stylu (duży skrót myślowy):

[code=ruby]class DNSZone < AR::Base
after_create { |zone| OrderFileManager.new(zone).generate }
before_destroy { |zone| OrderFileManager.new(zone).destroy }
end

class OrderFileManager

def initialize(resource)
@resource = resource

end

def generate(options={})
zone = renderer.render_to_string :partial =>“path/to/partial”, :locals => {:zone => @resource}, :formats=>[:xml]
filename = Rails.root.join(“servers”, from_params,“o#{Time.now.to_i}.xml”)
File.open(filename, ‘w’) {|f| f.write(zone) }
end

private
def renderer
@renderer ||= ActionController::Base.new()
end[/code]
Równie dobrze można będzie tego użyć w kontrolerze (jeśli np do stworzenia pliku potrzeba doddatkowych danych), np:

[code=ruby]class DnsZonesController < ApplicationController
(…)
private
def make_order
OrderFileManager.new(@zone).generate(:server_name => @server.name)
end

end[/code]

Dziękuje za tą podpowiedź. Wprawdzie nie wykorzystałem callback-ów tylko observer ale zasada się sprawdza :slight_smile: