2014-12-30 34 views
7

Buduję Rest API przy użyciu rails-api i active-model-serializer w celu łatwego filtrowania wymaganych pól w JSON. Używam również skojarzenia has_one w tych serializerach. Chciałem tylko wiedzieć, jak określić inną nazwę klucza dla atrybutu has_one.Używanie innej nazwy klucza dla atrybutu powiązania w szynie api model szeregowy aktywnego modelu

Oznacza to, że mam dwa modele powiedzieć: Employee i Address, a tam jest has_one :address powiedzmy EmployeeSerializer. Reakcja, która pojawia się:

{ 
    id: 1, 
    address: { 
    street: "some_street", 
    city: "some_city" 
    } 
} 

Ale chciałbym uzyskać następującą odpowiedź:

{ 
    id: 1, 
    stays: { 
    street: "some_street", 
    city: "some_city" 
    } 
} 

Próbowałem za pomocą has_one :address, :key => :stays, ale to nie wydają się działać.

+0

Która wersja AMS używacie? Nie jestem dokładnie zaznajomiony z podstawą kodu, ale z szybkiego spojrzenia argument "key" wydaje się nie być uwzględniony we wszystkich nowszych. Aby obejść ten problem, spróbuj zdefiniować 'has_one: stays' wraz z' def stays; object.address; koniec'. – janfoeh

+0

@janfoeh Używam wersji 0.9.0.Również używam innego serializera dla skojarzenia. tj. 'has_one: address, key: 'status', serializer: MyAddressSerializer'. Przyjmuje atrybuty z 'MyAddressSerializer', ale kluczem atrybutu nadal jest' address' – swaroopsm

+0

Ah. Jeśli poprawnie przeczytałem [zmiany między 0.9.0 a 0.9.1] (https://github.com/rails-api/active_model_serializers/compare/v0.9.0...v0.9.1), argument ten był nazywany 'embed_key 'w 0.9.0, a nie' klucz'. – janfoeh

Odpowiedz

7

Można zdefiniować stays jako jeden z atrybutów, które chcesz mieć w swojej JSON.

Naturalnie, serializator przejdzie do instancji modelu i nie znajdzie atrybutu w modelu o tej nazwie. Tak więc będzie siedział tam, drapiąc się w głowę, jak na świecie powinna być wartość :stays.

To jest w porządku, ponieważ można zdefiniować metodę instancji w serializatorze, informując ją dokładnie, jaka powinna być ta wartość. W tej metodzie instancji otrzymujesz zmienną object, która jest obiektem przetwarzanym przez serializer. object.address będzie zatem Twoją instancją Address.

Po utworzeniu instancji adresu można utworzyć instancję szeregową, która będzie używać tej instancji do wyświetlania pól w niej opisanych. Wierzę, że root: false jest konieczne, ponieważ w przeciwnym razie atrybut :stays (lub jakikolwiek inny obiekt serializacyjny zwróci w tym przypadku) będzie wyświetlany wewnątrz innego atrybutu :stays.

Twój ostateczny serializer dla Employee powinien wyglądać następująco:

class EmployeeSerializer < ActiveModel::Serializer 
    attributes :id, :name, :stays 

    def stays 
    MyAddressSerializer.new(object.address, root: false) 
    end 

end 
+0

Dodaj opis, dlaczego będzie on wykonywał zadanie. Jest on bardzo niskiej jakości i nie pasuje do stylu SO Q & A bardzo dobrze i został oznaczony jako Post o niskiej jakości. – Cheesebaron

+0

@Cheesebaron jak to jest? :) – Kalman

+0

O wiele lepiej :) – Cheesebaron

3

@janfoeh jest tuż. I właśnie przetestowane w wersji 0.8 i to działa dobrze

  1. gem "active_model_serializers", "~> 0.8.0" w Gemfile
  2. zabić serwer
  3. $bundle install
  4. has_one :address, key: "stays"
  5. uruchomić serwer kopii zapasowych

Działa świetnie!

W dokumentacji gem mówi (here), „prawdopodobnie chcesz korzystać z wersji 0.8”

+0

Jeśli używam wersji '0.8.0',' MyAddressSerializer' nie działa w: 'has_one: adres, klucz: 'status', serializer: MyAddressSerializer' – swaroopsm

+0

@swaroopsm jest "Adres" zawsze jest serializowany za pomocą 'MyAddressSerializer'? Jeśli tak, możesz to zdefiniować na' Adres' przy pomocy 'def active_model_serializer; MyAddressSerializer; end'. – janfoeh