Как в Rails рендерить JSON с помощью представления?

125

Предположим, вы находитесь в своем контроллере пользователей и хотите получить ответ json для запроса на показ. Было бы неплохо, если бы вы могли создать файл в своем каталоге views / users / с именем show.json и после того, как ваши пользователи # show действие завершено, он отображает файл.

В настоящее время вам нужно сделать что-то вроде:

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

Но было бы неплохо, если бы вы могли просто создать файл show.json, который автоматически отрисовывается так:

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

Это спасло бы меня от горя и смыло бы то ужасное грязное чувство, которое я испытываю, когда рендерю свой json в контроллере.

Мэтью
источник
Глядя на этот пост сейчас, похоже, что это меня не сильно спасет, но у меня есть более сложные случаи, поверьте мне, когда я говорю, что это вызывает у меня головные боли
Мэтью
1
В Rails 3, вы можете просто позвонить format.jsonс show.json.erbфайлом. Смотрите мой ответ.
Джеймс Лим

Ответы:

64

Вы должны иметь возможность сделать что-то подобное в своем respond_toблоке:

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

который отобразит шаблон в формате app/views/users/_show.json.erb.

Алекс Рейснер
источник
5
Это хорошо, но вы быстро обнаружите, что erb - болезненный способ генерации json. Посмотрите мой ответ на некоторые альтернативы.
tybro0103 07
1
Есть ли способ сделать это без партиала?
Wylliam Judd
55

Попробуйте добавить представление users/show.json.erbЭто должно отображаться, когда вы делаете запрос для формата JSON, и вы получаете дополнительное преимущество, заключающееся в том, что он также отображается с помощью erb, поэтому ваш файл может выглядеть примерно так

{
    "first_name": "<%= @user.first_name.to_json %>",
    "last_name": "<%= @user.last_name.to_json %>"
}
Erik
источник
9
Возможно, вы захотите использовать @user.first_name.to_jsonвместо escape_javascript. Есть некоторые тонкие различия между тем, что позволяет JS, и тем, что является строго JSON. (И эти различия становятся важными, поскольку браузеры реализуют свои собственные парсеры JSON.)
Джеймс А. Розен,
1
Вероятно, вам следует заменить одинарные кавычки на двойные, поскольку JSON (в отличие от JS) принимает только строки с двойными кавычками.
Abe Voelker
1
Это хорошо, но вы быстро обнаружите, что erb - болезненный способ генерации json. Посмотрите мой ответ на некоторые альтернативы.
tybro0103 07
Я знаю, что это старый ответ, но он совершенно неверен. to_json уже вернет отформатированную строку json "", поэтому результирующий json никогда не будет действителен с дополнительными кавычками ("" значение ""). Кроме того, если имя пользователя равно нулю, результирующий json будет иметь строку "null" в качестве значения. Также <% = использует экранирование html, которое искажает символы html во входных данных.
d4n3 04
Я думаю, вам также нужно удалить кавычки, <%= xyz.to_json %>иначе у вас останутся лишние кавычки.
akostadinov
32

Как уже упоминали другие, вам нужно представление users / show.json, но есть варианты, которые следует учитывать для языка шаблонов ...

Еврорадио

Работает "из коробки". Отлично подходит для HTML, но вы быстро обнаружите, что это ужасно для JSON.

RABL

Хорошее решение. Придется добавить зависимость и изучить ее DSL.

Конструктор JSON

То же, что и RABL: Хорошее решение. Придется добавить зависимость и изучить ее DSL.

Обычный рубин

Ruby отлично умеет генерировать JSON, и здесь нет ничего нового, чему можно было бы научиться, поскольку вы можете вызывать to_jsonHash или объект AR. Просто зарегистрируйте расширение .rb для шаблонов (в инициализаторе):

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

Затем создайте представление users / show.json.rb:

@user.to_json

Для получения дополнительной информации об этом подходе см. Http://railscasts.com/episodes/379-template-handlers.

tybro0103
источник
7
Обратите внимание, что в rails 4 обработчик шаблона .ruby по умолчанию зарегистрирован на github.com/rails/rails/commit/de1060f4e02925c12004f2, поэтому вы можете пропустить регистрацию .rb и назвать свой файл users / show.json.ruby.
Тим Диггинс,
1
Кроме того, для дальнейшего обновления json_builder был заменен на github.com/rails/jbuilder .
Тим Диггинс,
27

RABL, вероятно, лучшее решение, которое я видел, если вы ищете более чистую альтернативу синтаксису ERb. json_builder и argonaut, которые являются другими решениями, кажутся несколько устаревшими и не будут работать с Rails 3.1 без исправлений.

RABL доступен через гем или в репозитории GitHub; хорошие примеры тоже

https://github.com/nesquena/rabl

zapnap
источник
21

Просто чтобы обновить этот ответ для других, которые случайно окажутся на этой странице.

В Rails 3 вам просто нужно создать файл по адресу views/users/show.json.erb. @userОбъект будет доступен к просмотру (так же , как это было бы для HTML.) Вы даже не нужно to_jsonбольше.

Подводя итог, это просто

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

и

/* views/users/show.json.erb */
{
    "name" : "<%= @user.name %>"
}
Джеймс Лим
источник
1
Я ответил на это 1,5 года назад. В настоящее время я просто использую response_with всякий раз, когда мне нужен JSON, например respond_with @user, only: [:name]. Обратитесь к этому руководству для получения дополнительной информации.
Джеймс Лим
1
Чтобы добавить к этому ответу, это на самом деле опасно по двум причинам: он позволяет инъекцию из пользовательских данных, потому что он не экранирует символы новой строки и обратной косой черты, а также <% = html экранирует данные, поэтому, например, Шон О'Коннор будет иметь его имя искалечен Шону О'Коннору.
d4n3 04
10

Просто добавьте show.json.erbфайл с содержимым

<%= @user.to_json %>

Иногда это полезно, когда вам нужны дополнительные вспомогательные методы, которые недоступны в контроллере, то есть image_path(@user.avatar)что-то для создания дополнительных свойств в JSON:

<%= @user.attributes.merge(:avatar => image_path(@user.avatar)).to_json %>
Прийт
источник
8
Это должно быть, <%= raw(@user.to_json) %>чтобы избежать экранирования HTML. Что я делаю, так это то, что я полагаюсь на to_json до тех пор, пока он дает мне то, что я хочу, но когда я хочу сделать что-то еще, я шаблонизирую его с тем, что обычно является файлом { :blah => @user.the_blah }.to_json.
clacke 08
0

Я новичок в RoR, вот что я узнал. вы можете напрямую отображать формат json

def YOUR_METHOD_HERE
  users = User.all
  render json: {allUsers: users} # ! rendering all users
END
Арт
источник