В работе над текущим проектом мне часто приходится иметь дело с форматом json, причем не только выдавать json ответом с сервера, но еще и читать json-параметры запросов, и даже наборы параметров, сериализованные в json и уложенные в поле в таблице БД.
В ruby, как известно, для этого существует стандартная библиотека json
. Упаковка данных в json и распаковка их обратно происходит с помощью 2 методов:
1 2 3 4 |
|
И все бы хорошо, да вот только в один прекрасный день моя коллега на своей ubuntu-машине запустила спеки, и JSON.load
почему-то повел себя как IO.load
- решил, что параметром ему подсовывают имя файла - но файла под названием {"result":true}
рядом не нашлось, и случился Errno::ENOENT: No such file or directory
Поначалу проблема казалась абсолютно мистической и необъяснимой, и JSON.load
было решено поменять во всем проекте на ActiveSupport::JSON.decode
- он работал без проблем как на убунтах коллег, так и на моем маке.
Но однажды я забыл об этой особенности, и продеплоил код на staging-сервер. Результат не заставил себя ждать - JSON.load
снова захотел получить параметром путь к некоему файлу. Можно было бы, конечно, снова заменить его на вариант из ActiveSupport, но я решил, что раз уж код работает у меня на маке, то должен работать везде (уж такие вещи, как JSON, точно не должны быть платформозависимыми).
После долгих мытарств выяснилось, что ruby необходимо скомпилировать с поддержкой iconv
. Причем речь идет именно о ruby - сам iconv был уже установлен на сервере, но интерпретатор об этом понятия не имел.
В случае использования RVM
все это сводится к 3 командам (к сожалению, включающим в себя переустановку текущей версии ruby):
1 2 3 |
|
Первая команда устанавливает iconv, причем не куда-нибудь, а в ~/.rvm/usr
; вторая сносит ruby 1.9.2 - ну а третья ставит его обратно, компилируя с поддержкой iconv. Чуть более подробно этот процесс описан здесь.
После этого JSON.load
/ JSON.dump
замечательным образом заработали.