ho studiato come versione un'API e trovato diversi modi per farlo. Ho deciso di provare il suggerimento peter williams' e ho creato nuovi tipi di mime del fornitore per specificare la versione e il formato. Non sono riuscito a trovare un resoconto definitivo per fare ciò seguendo "il modo delle rotaie", quindi ho ricostruito le informazioni da più punti. Sono stato in grado di farlo funzionare, ma c'è un po 'goofiness nel modo in cui i renderer gestiscono l'istanza di Widget array vs Widget in respond_with
.
passi di base & problema:
ho registrato tipi MIME e renderer per la versione 1 aggiunto in XML e JSON per ApplicationController, i renderer chiamano to_myproj_v1_xml
e to_myproj_v1_json
metodi nel modello. respond_with(@widget)
funziona bene ma respond_with(@widgets)
lancia un HTTP/1.1 500 Internal Server Error
dicendo che "Il modello è mancante".
Soluzione:
"Template manca" significa che non render è stato chiamato e esiste alcun modello di corrispondenza. per caso, ho scoperto che sta cercando un metodo di classe ... quindi ho trovato il codice sotto il quale funziona, ma non ne sono davvero contento. Il goofiness è per lo più in e relativo a xml = obj.to_myproj_v1_xml(obj)
e la duplicazione nel modello.
La mia domanda è: qualcuno ha fatto qualcosa di simile in modo leggermente più pulito?
- = codice aggiornato = -
config/inizializzatori/mime_types.rb:
Mime::Type.register 'application/vnd.com.mydomain.myproj-v1+xml', :myproj_v1_xml
Mime::Type.register 'application/vnd.com.mydomain.myproj-v1+json', :myproj_v1_json
app/controllers/application_controller.rb:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :authenticate
ActionController.add_renderer :myproj_v1_xml do |obj, options|
xml = obj.to_myproj_v1_xml
self.content_type ||= Mime::Type.lookup('application/vnd.com.mydomain.myproj-v1+xml')
self.response_body = xml
end
ActionController.add_renderer :myproj_v1_json do |obj, options|
json = obj.to_myproj_v1_json
self.content_type ||= Mime::Type.lookup('application/vnd.com.mydomain.myproj-v1+json')
self.response_body = json
end
end
app/models/widget.rb:
class Widget < ActiveRecord::Base
belongs_to :user
V1_FIELDS = [:version, :model, :description, :name, :id]
def to_myproj_v1_xml
self.to_xml(:only => V1_FIELDS)
end
def to_myproj_v1_json
self.to_json(:only => V1_FIELDS)
end
def as_myproj_v1_json
self.as_json(:only => V1_FIELDS)
end
end
app/controller/widgets_controller.rb:
class WidgetsController < ApplicationController
respond_to :myproj_v1_xml, :myproj_v1_json
def index
@widgets = @user.widgets
respond_with(@widgets)
end
def create
@widget = @user.widgets.create(params[:widget])
respond_with(@widget)
end
def destroy
@widget = @user.widgets.find(params[:id])
respond_with(@widget.destroy)
end
def show
respond_with(@widget = @user.widgets.find(params[:id]))
end
...
end
config/inizializzatori/monkey_array.rb
class Array
def to_myproj_v1_json(options = {})
a = []
self.each { |obj| a.push obj.as_myproj_v1_json }
a.to_json()
end
def to_myproj_v1_xml(options = {})
a = []
self.each { |obj| a.push obj.as_myproj_v1_json } # yes this is json instead of xml. as_json returns a hash
a.to_xml()
end
end
UPDATE:
Trovato un'altra soluzione che si sente meglio ma ancora un po 'strana (non sono ancora del tutto a mio agio con le patch della scimmia), probabilmente ok ... in pratica ho spostato i dati di risposta dal metodo di classe to_myproj_v1_json
a una patch di scimmia su Array. In questo modo quando c'è una matrice di widget, chiama il metodo di istanza as_myproj_v1_json
su ciascun widget e restituisce l'intera matrice come formato desiderato.
Una nota:
- as_json non ha nulla a che fare con il formato JSON, crea solo un hash. Aggiungi la formattazione personalizzata a as_myproj_v1_json (o una sovrascrittura di as_json se non usi tipi mime personalizzati), quindi to_json cambierà un hash in una stringa json.
Ho aggiornato il seguente codice per essere quello che è attualmente utilizzato, quindi la domanda originale potrebbe non avere senso. se qualcuno vuole la domanda originale e il codice mostrato come era e il codice fisso in una risposta posso farlo.
Hai una domanda? Non capisco ... – Anton
Ho trovato difficile trovare la domanda in questo post, ma alla fine l'ho trovata. Tuttavia, se si è arrivati a una soluzione da soli, si prega di inviare come risposta piuttosto (e contrassegnare come accettato) di aggiornare la domanda. – Kev
@jay, direi che devi essere più attento a modificare i tuoi post in futuro - arrivando alla tua domanda un visitatore è ora salutato con "AGGIORNAMENTO: trovato un'altra soluzione ..." che è molto confuso. – Ben