No Rails, como você renderiza o JSON usando uma view?

125

Suponha que você esteja no controlador de usuários e deseje obter uma resposta json para uma solicitação de show; seria bom se você pudesse criar um arquivo em suas views / users / dir, chamado show.json e depois dos usuários # show ação for concluída, renderiza o arquivo.

Atualmente, você precisa fazer algo como:

def show
  @user = User.find( params[:id] )
  respond_to do |format|
    format.html
    format.json{
      render :json => @user.to_json
    }
  end
end

Mas seria bom se você pudesse criar um arquivo show.json que seja automaticamente renderizado da seguinte maneira:

def show
  @user = User.find( params[:id] )
  respond_to do |format|
    format.html
    format.json
  end
end

Isso me pouparia muito pesar e eliminaria aquela sensação horrivelmente suja que sinto quando renderizo meu json no controlador

Mateus
fonte
Olhando para este post agora, parece que isso não iria salvar-me muito, mas eu tenho casos mais complicados, a confiança em mim quando digo isso está me causando dores de cabeça
Matthew
1
No Rails 3, você pode simplesmente chamar format.jsoncom um show.json.erbarquivo. Veja minha resposta.
James Lim

Respostas:

64

Você deve conseguir fazer algo assim no seu respond_tobloco:

respond_to do |format|
    format.json 
    render :partial => "users/show.json"
end

que renderizará o modelo app/views/users/_show.json.erb.

Alex Reisner
fonte
5
Isso é bom, mas você encontrará rapidamente que erb é uma maneira dolorosa de gerar json. Confira minha resposta para algumas alternativas.
precisa
1
Existe alguma maneira de fazer isso sem usar um parcial?
Wylliam Judd 23/07
55

Tente adicionar uma visualização users/show.json.erbIsso deve ser renderizado quando você faz uma solicitação para o formato JSON e obtém o benefício adicional de ser renderizado pelo erb também, para que seu arquivo possa ter algo parecido com isto

{
    "first_name": "<%= @user.first_name.to_json %>",
    "last_name": "<%= @user.last_name.to_json %>"
}
erik
fonte
9
Você pode querer usar em @user.first_name.to_jsonvez de escape_javascript. Existem algumas diferenças sutis entre o que o JS permite e o que é estritamente o JSON. (E essas diferenças estão se tornando importante como navegadores implementar seus próprios analisadores JSON.)
James A. Rosen
1
Você provavelmente deve alterar as aspas simples para aspas duplas, pois o JSON (diferente do JS) aceita apenas cadeias de caracteres entre aspas duplas.
Abe Voelker
1
Isso é bom, mas você encontrará rapidamente que erb é uma maneira dolorosa de gerar json. Confira minha resposta para algumas alternativas.
precisa
Eu sei que essa é uma resposta antiga, mas está completamente errada. to_json já retornará uma string json "" formatada, portanto o json resultante nunca será válido com aspas extras ("" valor ""). Além disso, se o nome do usuário for nulo, o json resultante terá a cadeia "null" como valor. Além disso, <% = usa escape html, que altera caracteres html nos dados de entrada.
d4n3 4/15
Eu acho que você também precisa remover aspas, <%= xyz.to_json %>caso contrário você ficará com aspas extras.
akostadinov 23/08/16
32

Como outros já mencionaram, você precisa de uma visão users / show.json, mas há opções a serem consideradas no idioma do modelo ...

ERB

Trabalha fora da caixa. Ótimo para HTML, mas você rapidamente descobrirá que é horrível para JSON.

RABL

Boa solução. Tem que adicionar uma dependência e aprender sua DSL.

Construtor JSON

O mesmo negócio que o RABL: boa solução. Tem que adicionar uma dependência e aprender sua DSL.

Plain Ruby

Ruby é incrível na geração de JSON e não há nada novo para aprender, pois você pode chamar to_jsonum Hash ou um objeto AR. Basta registrar a extensão .rb para modelos (em um inicializador):

ActionView::Template.register_template_handler(:rb, :source.to_proc)

Em seguida, crie a visão users / show.json.rb:

@user.to_json

Para mais informações sobre essa abordagem, consulte http://railscasts.com/episodes/379-template-handlers

tybro0103
fonte
7
Observe que no rails 4, o manipulador de modelo .ruby é registrado por padrão github.com/rails/rails/commit/de1060f4e02925c12004f2, para que você possa pular o registro .rb e nomear seu arquivo como user / show.json.ruby.
Tim Timggins
1
Além disso, para atualizar ainda mais, o json_builder foi substituído por github.com/rails/jbuilder .
Tim Timggins
27

O RABL é provavelmente a melhor solução para isso que eu já vi se estiver procurando uma alternativa mais limpa à sintaxe do ERb. json_builder e argonaut, que são outras soluções, parecem um pouco desatualizados e não funcionarão com o Rails 3.1 sem correções.

O RABL está disponível via gem ou consulte o repositório GitHub; bons exemplos também

https://github.com/nesquena/rabl

zapnap
fonte
21

Apenas para atualizar esta resposta em prol de outras pessoas que acabam nesta página.

No Rails 3, você só precisa criar um arquivo em views/users/show.json.erb. O @userobjeto estará disponível para a visualização (como seria para html.) Você nem precisa to_jsonmais.

Para resumir, é apenas

# users contoller
def show
  @user = User.find( params[:id] )
  respond_to do |format|
    format.html
    format.json
  end
end

e

/* views/users/show.json.erb */
{
    "name" : "<%= @user.name %>"
}
James Lim
fonte
1
Eu respondi isso 1,5 anos atrás. Atualmente, eu apenas uso o respond_with sempre que eu precisar do JSON, por exemplo respond_with @user, only: [:name]. Consulte este tutorial para obter mais informações.
James Lim
1
Apenas para adicionar a esta resposta, isso é realmente perigoso por dois motivos: permite a injeção de dados do usuário porque não escapa linhas novas e barras invertidas e também <% = html escapa dos dados, por exemplo, Sean O'Connor terá seu nome mutilado para Sean O'Connor.
d4n3 4/15
10

Basta adicionar show.json.erbarquivo com o conteúdo

<%= @user.to_json %>

Às vezes, é útil quando você precisa de alguns métodos auxiliares adicionais que não estão disponíveis no controlador, image_path(@user.avatar)ou seja, ou algo para gerar propriedades adicionais no JSON:

<%= @user.attributes.merge(:avatar => image_path(@user.avatar)).to_json %>
Priit
fonte
8
Seria necessário <%= raw(@user.to_json) %>evitar o escape de HTML. O que faço é confiar no to_json, desde que ele me dê o que quero, mas quando quero fazer outra coisa, modelo-o com o que geralmente é um { :blah => @user.the_blah }.to_json.
Clacke
0

Sou novo no RoR, foi o que descobri. você pode renderizar diretamente um formato json

def YOUR_METHOD_HERE
  users = User.all
  render json: {allUsers: users} # ! rendering all users
END
aRtoo
fonte