Rails'te to_json nasıl geçersiz kılınır?


94

Güncelleme:

Bu sorun doğru bir şekilde araştırılmadı. Asıl mesele içeride yatıyor render :json.

Orijinal sorudaki ilk kod yapıştırması beklenen sonucu verecektir. Ancak yine de bir uyarı var. Bu örneğe bakın:

render :json => current_user

ile aynı DEĞİLDİR

render :json => current_user.to_json

Yani, Kullanıcı nesnesiyle ilişkili yöntemi render :jsonotomatik olarak çağırmaz to_json. Aslında , model to_jsonüzerinde geçersiz kılınmışsa, aşağıda açıklananları üretecektir .Userrender :json => @userArgumentError

özet

# works if User#to_json is not overridden
render :json => current_user

# If User#to_json is overridden, User requires explicit call
render :json => current_user.to_json

Bunların hepsi bana aptalca geliyor. Görünüşe göre bu render, Model#to_jsontip :jsonbelirtildiğinde aslında arama olmadığını söylüyor . Biri burada gerçekte neler olduğunu açıklayabilir mi?

Bu konuda bana yardımcı olabilecek herhangi bir cin muhtemelen diğer sorumu yanıtlayabilir: Rails'te @ foo.to_json (seçenekler) ve @ bars.to_json (seçenekler) birleştirilerek nasıl bir JSON yanıtı oluşturulur?


Orijinal Soru:

SO'da başka örnekler de gördüm, ama hiçbiri aradığımı yapmıyorum.

Deniyorum:

class User < ActiveRecord::Base

  # this actually works! (see update summary above)
  def to_json
    super(:only => :username, :methods => [:foo, :bar])
  end

end

Ben alıyorum ArgumentError: wrong number of arguments (1 for 0)içinde

/usr/lib/ruby/gems/1.9.1/gems/activesupport-2.3.5/lib/active_support/json/encoders/object.rb:4:in `to_json

Herhangi bir fikir?


Örneğiniz modellerimden birinde çalışıyor. Herhangi birini yapın username, fooya da baryöntemler argümanlar bekliyoruz?
Jonathan Julian

Hayır, usernamebir yöntem olup foove baryöntemlerini gerektirmez. Hatanın nerede olduğunu göstermek için sorumu güncelledim.
maček

1.8.7 koşuyorum. Bu dosyayı açmanız ve neden sıfır bağımsız değişken bekleyen bir yönteme bir argüman geçirdiğini görmeniz gerekecek.
Jonathan Julian

Yanıtlar:


216

Sen alıyorsanız ArgumentError: wrong number of arguments (1 for 0)çünkü to_jsonihtiyaçlar tek parametre ile geçersiz kılınan olmak optionskarma.

def to_json(options)
  ...
end

Daha uzun açıklama to_json, as_jsonve render:

ActiveSupport 2.3.3'te, as_jsonkarşılaştığınız gibi sorunları gidermek için eklendi. Yaratılış json ayrı olmalı render json.

Şimdi, to_jsonbir nesnede herhangi bir zamanda as_jsonçağrılır, veri yapısını oluşturmak için çağrılır ve daha sonra bu karma ActiveSupport::json.encode,. Bu, tüm türlerde olur: nesne, sayısal, tarih, dize, vb (bkz. ActiveSupport kodu).

ActiveRecord nesneleri de aynı şekilde davranır. as_jsonTüm modelin özniteliklerini içeren bir hash oluşturan varsayılan bir uygulama vardır. İstediğiniz as_jsonJSON yapısını oluşturmak için Modelinizde geçersiz kılmalısınız . as_json, tıpkı eskisi gibi, to_jsonbildirimsel olarak dahil edilecek öznitelikleri ve yöntemleri belirtebileceğiniz bir seçenek karması alır.

def as_json(options)
  # this example ignores the user's options
  super(:only => [:email, :handle])
end

Denetleyicinizde render :json => obir dizeyi veya bir nesneyi kabul edebilir. Bir dizeyse, yanıt gövdesi olarak iletilir, eğer bir nesne to_jsonise, as_jsonyukarıda açıklandığı gibi tetiklenir .

Dolayısıyla, modelleriniz as_jsongeçersiz kılmalarla doğru şekilde temsil edildiği (veya gösterilmediği) sürece, bir modeli görüntülemek için denetleyici kodunuz şu şekilde görünmelidir:

format.json { render :json => @user }

Hikayenin ahlakı şudur: Doğrudan aramaktan kaçının to_json, renderbunu sizin için yapmasına izin verin. JSON çıktısını ayarlamanız gerekirse, arayın as_json.

format.json { render :json => 
    @user.as_json(:only => [:username], :methods => [:avatar]) }

@Jonathan Julian, bu çok yararlı bir açıklama as_json. ActiveRecord :: Serialization belgelerinde ( api.rubyonrails.org/classes/ActiveRecord/… ) görebileceğiniz gibi , bunun için çok az (yok) belge var. Bunu bir deneyeceğim :)
maček

1
@Jonathan Julian, buna 10 kez ek oy verebilseydim, yapardım. Doktorlar hangi as_jsoncehennemde! Tekrar teşekkürler :)
maček

71

Rails 3'te bununla ilgili sorun yaşıyorsanız, serializable_hashyerine geçersiz kılın as_json. Bu, XML biçimlendirmenizi de ücretsiz olarak alacaktır :)

Bunu anlamam sonsuza kadar sürdü. Umarım bu birine yardımcı olur.


1
Yöntem hakkında iyi yazılar bilen var mı serializable_hash? Bunu kullandığımda, sonraki xml çıktımı nesneyi adıyla sarmalamaktan (örneğin bir alıntı nesnesi için "alıntı") bunun yerine her zaman "<hash>" ile sarmaya değiştirir.
Tyler Collier

@TylerCollier ile aynı seçenekler olmalıdırto_xml
Sam Soffes

Bu çözüm için teşekkürler! Ruby2 / rails4 kullanıyorum ve as_json iç içe nesnelerle çalışmıyordu, geçersiz kılınan yöntem 'include' olarak çağrılmadı, serializable_hash ile çalışıyor!
santuxus

Bunun yerine serializable_hash'in neden geçersiz kılınması gerektiğine dair bir açıklama için robots.thoughtbot.com/better-serialization-less-as-json adresine bakın .
Topher Hunt

36

Kullanıcı seçeneklerini görmezden gelmek istemeyen ancak kendi seçeneklerini de eklemek isteyenler için:

def as_json(options)
  # this example DOES NOT ignore the user's options
  super({:only => [:email, :handle]}.merge(options))
end

Umarım bu herkese yardımcı olur :)


1
Bunu options= {}
yapmamın

4

To_json değil, as_json'ı geçersiz kılın. Ve as_json'dan istediğinizi arayın:

Bunu dene:

def as_json 
 { :username => username, :foo => foo, :bar => bar }
end

as_jsonSadece ActiveResource için değil mi?
Jonathan Julian

Görünüşe göre ActiveRecord :: Serialization'da as_json api.rubyonrails.org/classes/ActiveRecord/Serialization.html
glebm

@glebm, bunu denedim ve aynı sonucu alıyorum. Size göstermek için sorumu güncelledim.
maček

@glebm, hala aynı hatayı alıyorum. Yaptığım zaman bile render :json => current_userbeklenen varsayılan sonucu alıyorum ( UserJSON biçiminde model için tüm öznitelikler ). Ben eklediğinizde as_jsonbenim yöntemi Usermodeli ve aynı şeyi denemek, hatasını :( olsun
MACEK

@glebm, teşekkür ederim. Yanlış bir şey yaptığımı biliyorum. Güncellenen soruyu kontrol etmeye değer olabilir.
maček
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.