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.