Atualizar:
Este problema não foi devidamente explorado. O verdadeiro problema está dentro render :json
.
A primeira colagem de código na questão original produzirá o resultado esperado. No entanto, ainda há uma ressalva. Veja este exemplo:
render :json => current_user
NÃO é o mesmo que
render :json => current_user.to_json
Ou seja, render :json
não chamará automaticamente o to_json
método associado ao objeto Usuário. Na verdade , se to_json
estiver sendo sobrescrito no User
modelo, render :json => @user
irá gerar o ArgumentError
descrito abaixo.
resumo
# 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
Tudo isso me parece bobo. Isso parece me dizer que render
não está realmente chamando Model#to_json
quando o tipo :json
é especificado. Alguém pode explicar o que realmente está acontecendo aqui?
Qualquer gênio que possa me ajudar com isso provavelmente pode responder à minha outra pergunta: Como construir uma resposta JSON combinando @ foo.to_json (opções) e @ bars.to_json (opções) no Rails
Questão original:
Eu vi alguns outros exemplos no SO, mas nenhum faço o que estou procurando.
Estou tentando:
class User < ActiveRecord::Base
# this actually works! (see update summary above)
def to_json
super(:only => :username, :methods => [:foo, :bar])
end
end
Estou ficando ArgumentError: wrong number of arguments (1 for 0)
em
/usr/lib/ruby/gems/1.9.1/gems/activesupport-2.3.5/lib/active_support/json/encoders/object.rb:4:in `to_json
Alguma ideia?
fonte
username
,foo
oubar
métodos esperar argumentos?username
não é um método e umfoo
ebar
não requerem métodos. Eu atualizei minha pergunta para mostrar onde o erro está acontecendo.Respostas:
Você está recebendo
ArgumentError: wrong number of arguments (1 for 0)
porqueto_json
precisa ser substituído por um parâmetro, ooptions
hash.Mais explicação sobre
to_json
,as_json
e renderização:No ActiveSupport 2.3.3,
as_json
foi adicionado para resolver problemas como o que você encontrou. A criação do json deve ser separada da renderização do json.Agora, a qualquer momento
to_json
é chamado em um objeto,as_json
é chamado para criar a estrutura de dados e, em seguida, esse hash é codificado como uma string JSON usandoActiveSupport::json.encode
. Isso acontece para todos os tipos: objeto, numérico, data, string, etc (ver o código ActiveSupport).Os objetos ActiveRecord se comportam da mesma maneira. Existe um padrão
as_json
implementação que cria um hash que inclui todos os atributos do modelo. Você deve substituiras_json
em seu modelo para criar a estrutura JSON desejada .as_json
, assim como o antigoto_json
, tem um hash de opção onde você pode especificar atributos e métodos para incluir declarativamente.Em seu controlador,
render :json => o
pode aceitar uma string ou um objeto. Se for uma string, ela será passada como o corpo da resposta, se for um objeto,to_json
é chamado, o que disparaas_json
conforme explicado acima.Portanto, contanto que seus modelos sejam representados corretamente com
as_json
substituições (ou não), o código do controlador para exibir um modelo deve ser assim:A moral da história é: evite ligar
to_json
diretamente, permitarender
fazer isso por você. Se você precisar ajustar a saída JSON, chameas_json
.fonte
as_json
. Como você pode ver nos documentos ActiveRecord :: Serialization ( api.rubyonrails.org/classes/ActiveRecord/… ), há muito pouca (nenhuma) documentação para isso. Vou tentar :)as_json
documentos! Obrigado novamente :)Se você está tendo problemas com isso no Rails 3, substitua ao
serializable_hash
invés deas_json
. Isso também obterá sua formatação XML gratuitamente :)Isso me levou uma eternidade para descobrir. Espero que ajude alguém.
fonte
serializable_hash
? Quando eu o uso, ele altera minha saída xml subsequente de envolver o objeto com seu nome (por exemplo, "quote" para um objeto de cotação ") para sempre envolvê-lo com" <hash> ".to_xml
Para pessoas que não desejam ignorar as opções dos usuários, mas também adicionar as deles:
Espero que isso ajude alguém :)
fonte
options
hash com,= {}
portanto, não é necessário ao chamarSubstitua não to_json, mas as_json. E de as_json chame o que quiser:
Experimente isto:
fonte
as_json
apenas para ActiveResource?render :json => current_user
isso, obtenho o resultado padrão esperado (todos os atributos doUser
modelo no formato JSON). Quando adiciono oas_json
método ao meuUser
modelo e tento a mesma coisa, recebo o erro :(