Rusrails створення відгуків (частина перша)

З точки зору контролера є три способи створити відгук HTTP:

Ми розкриємо кожен з цих методів по черзі. Але спочатку трохи про саму просту річ, яку може робити контролер для створення відгуку: не робити нічого.







Візуалізація за замовчуванням: угода над конфігурацією в дії

Ви вже чули, що Rails сприяє принципом "convention over configuration". Візуалізація за замовчуванням - прекрасний приклад цього. За замовчуванням контролери в Rails автоматично Рендер вьюха з іменами, відповідними екшн. Наприклад, якщо є такий код у Вашому класі BooksController:

І наступне в файлі маршрутів:

І у вас є файл вьюха app / views / books / index.html.erb:

Однак це повідомлення мінімально корисно, тому незабаром ви створите модель Book і додасте стрілялки index в BooksController:

Знову відзначте, що у нас угоди понад конфігурації в тому, що відсутня надмірна рендер в кінці цього екшна index. Правило в тому, що не потрібно щось надмірно рендерить в кінці екшна контролера, rails буде шукати шаблон action_name.html.erb по шляху вьюха контролера і отрендеріть його, тому в нашому випадку Rails отрендеріть файл app / views / books / index.html .erb.

Отже, в нашій вьюха ми хочемо відобразити властивості всіх книг, це робиться за допомогою шаблону ERB. подібного наступного:

Фактично рендеринг здійснюється підкласами ActionView :: TemplateHandlers. Ми не будемо заглиблюватися в цей процес, але важливо знати, що розширення файлу вьюха контролює вибір обробника шаблону. Починаючи з Rails 2, стандартні розширення це .erb для ERB (HTML з вбудованим Ruby) і .builder для Builder (генератор XML).

Використання render

У багатьох випадках метод ActionController :: Base # render виконує велику роботу по рендерингу вмісту Вашого застосування для використання в браузері. Є різні способи встановлення можливостей render. Ви можете рендерить вьюха за замовчуванням для шаблону Rails, або певний шаблон, або файл, або вбудований код, або зовсім нічого. Можна рендерить текст, JSON або XML. Також можна визначити тип вмісту або статус HTTP відрендерене відгуку.

Якщо хочете побачити точні результати виклику render без необхідності дивитися його в браузері, можете викликати render_to_string. Цей метод приймає ті ж самі опції, що і render. але повертає рядок замість відгуку для браузера.

Чи не Рендер нічого

Найпростіше, що ми можемо зробити з render це не рендерить нічого:

Якщо поглянути на відгук, використовуючи cURL, побачимо наступне:

Ми бачимо порожній відгук (немає даних після рядка Cache-Control), але Rails встановив відгук 200 OK, тому запит був успішним. Можете встановити опцію: status. щоб змінити цей відгук. Порожній рендеринг корисний для запитів AJAX. коли все, що ви хочете повернути браузеру, - це підтвердження того, що запит був виконаний.

Можливо слід використовувати метод head. який розглянемо в другій частині цієї глави, замість render: nothing. Це додасть додаткову гнучкість і зробить явним те, що генеруються тільки заголовки HTTP.

Візуалізація вьюха екшна

Якщо хочете отрендеріть вьюха, відповідну іншому екшн, в той же шаблон, можна використовувати render з ім'ям вьюха:

Якщо виклик update_attributes провалюється, виклик екшна update в цьому контролері отрендеріть шаблон edit.html.erb. що належить тому ж контролера.

Якщо хочете, можете використовувати символ замість рядка для визначення екшна для рендеринга:

Щоб бути точним, можете використовувати render з опцією: action (хоча це не є необхідним в Rails 3.0):

Використання render з: action - частий джерело плутанини для новачків в Rails. Певний стрілялки використовується для визначення, яку рендерить вьюха, але Rails працює програмне забезпечення будь-якої код для цього екшна в контролері. Будь-які змінні екземпляра, які потрібні у вьюха, повинні бути визначені в поточному екшені до виклику render.

Візуалізація шаблону екшна з іншого контролера

Що, якщо ви хочете отрендеріть шаблон з абсолютно іншого контролера? Це можна також зробити з render. який приймає повний шлях шаблону для рендера (щодо app / views). Наприклад, якщо запускаємо код в AdminProductsController який знаходиться в app / controllers / admin. можете отрендеріть результат екшна в шаблон в app / views / products наступним чином:

Rails знає, що ця вьюха належить іншому контролеру, оскільки містить символ слеша в рядку. Якщо хочете бути точними, можете використовувати опцію: template (яка була потрібна в Rails 2.2 і раніших):







Візуалізація довільного файлу

Метод render також може використовувати вьюха, яка розташована поза вашого застосування (можливо, ви спільно використовуєте вьюха двома додатками на Rails):

Rails визначає, що це рендер файлу з початкового символу слеша. Якщо хочете бути точним, можете використовувати опцію: file (яка була потрібна в Rails 2.2 і раніших):

За замовчуванням файл рендери без використання поточного макета. Якщо Ви хочете, щоб Rails вклав файл в поточний макет, необхідно додати опцію: layout => true.

Якщо ви працюєте під Microsoft Windows, то повинні використовувати опцію: file для рендера файлу, тому що імена файлів Windows не мають той же формат, як імена файлів Unix.

навороченность

Вищеописані три методу рендеру (рендеринг іншого шаблону в контролері, рендеринг шаблону в іншому контролері і рендеринг довільного файлу в файлової системі) насправді є варіантами одного і того ж екшна.

Фактично в методі BooksController, в екшені edit, в якому ми хочемо отрендеріть шаблон edit, якщо книжка не була успішно оновлена, все нижченаведені виклики отрендеріть шаблон edit.html.erb в директорії views / books:

Який з них ви будете використовувати - це питання стилю і угод, але практичне правило полягає в використанні найпростішого, яке має сенс для коду та написання.

Використання render з: inline

Метод render цілком може обійтися без вьюха, якщо ви використовуєте опцію: inline для підтримки ERB. як частини виклику методу. Це цілком валідності:

Повинно бути серйозна підстава для використання цієї опції. Вкраплення ERB в контролер порушує MVC орієнтованість Rails і створює труднощі для інших розробників в проходженні логіці вашого проекту. Замість цього використовуйте окрему erb-вьюха.

За замовчуванням вбудований рендеринг використовує ERb. Можете примусити використовувати замість цього Builder за допомогою опції: type:

Візуалізація тексту

Ви можете надіслати простий текст - зовсім без розмітки - назад браузеру з використанням опції: text в render:

Візуалізація чистого тексту найбільш корисний, коли ви робите AJAX відгук, або відповідаєте на запити веб-сервісу, який чекає щось інше, ніж HTML.

За замовчуванням при використанні опції: text текст рендерится без використання поточного макета. Якщо хочете, щоб Rails вклав текст в поточний макет, необхідно додати опцію: layout => true

Візуалізація JSON

Не потрібно викликати to_json в об'єкті, який хочете рендерить. Якщо використовується опція: json. render автоматично викличе to_json за вас.

Візуалізація XML

Rails також має вбудовану підтримку для конвертації об'єктів в XML і рендеринга цього XML для викликає:

Не потрібно викликати to_xml в об'єкті, який хочете рендерить. Якщо використовується опція: xml. render автоматично викличе to_xml за вас.

Опції для render

Виклик методу render як правило приймає чотири опції:

Опція: content_type

За замовчуванням Rails вкаже результатами операції рендеринга тип вмісту MIME text / html (або application / json якщо використовується опція: json. Або application / xml для опції: xml). Іноді буває так, що ви хочете змінити це, і тоді можете налаштувати опцію: content_type:

Опція: layout

З більшістю опцій для render. відрендерене вміст відображається як частина поточного макета. Ви дізнаєтеся більш детально про макетах, і як їх використовувати, пізніше в цьому керівництві.

Опція: layout потрібна, щоб повідомити Rails використовувати певний файл як макет для поточного екшна:

Також можна повідомити Rails рендерить взагалі без макета:

Опція: status

Rails автоматично згенерує відгук з коректним кодом статусу HTML (в більшості випадків дорівнює 200 OK). Опцію: status можна використовувати, щоб змінити це:

Опція: location

Опцію: location можна використовувати, щоб встановити заголовок HTTP Location:

Пошук макетів

Щоб знайти поточний макет, Rails спочатку дивиться файл в app / views / layouts з ім'ям, таким же, як ім'я контролера. Наприклад, рендеринг екшнів з класу PhotosController буде використовувати /app/views/layouts/photos.html.erb (або app / views / layouts / photos.builder). Якщо такого макета немає, Rails буде використовувати /app/views/layouts/application.html.erb або /app/views/layouts/application.builder. Якщо немає макета .erb. Rails буде використовувати макет .builder. якщо такий є. Rails також надає кілька способів більш точно призначити певні макети окремих контролерам і екшн.

Визначення макетів для контролерів
Вибір макетів під час виконання

Можете використовувати символ для відстрочки вибору макета до тих пір, поки не буде зроблений запит:

Можете навіть використовувати вкладений метод, такий як Proc, для визначення макета. Наприклад, якщо передати об'єкт Proc, то блок, переданий в Proc, буде переданий в екземпляр контролера. таким чином макет може бути визначений, грунтуючись на поточному запиті:

умовні макети

Макети, певні на рівні контролера, підтримують опції: only і: except. Ці опції приймають або ім'я методу, або масив імен методів, відповідних іменам методів в контролері:

спадкування макета

У цьому додатку:

Уникнення помилок подвійного рендеру

Рано чи пізно, більшість розробників на Rails побачать повідомлення про помилку "Can only render or redirect once per action". Хоч таке і дратує, це відносно просто правиться. Зазвичай таке відбувається в зв'язку з фундаментальним нерозумінням методу роботи render.

Наприклад, ось деякий код, який викличе цю помилку:

Якщо @ book.special? визначається як true. Rails починає процес рендеринга, вивантажуючи змінну @book у вьюха special_show. Але це не зупинить від виконання решті код в екшені show. і коли Rails досягне кінця екшна, він почне рендерить вьюха show - і видасть помилку. Рішення просте: переконайтеся, що у вас є тільки один виклик render або redirect за один прохід. Ще може допомогти така річ, як and return. Ось виправлена ​​версія методу:

Переконайтеся, що використовуєте and return замість return. оскільки return не працюватиме у зв'язку з пріоритетом операторів в мові Ruby.

Відзначте, що неявний рендер, що виконується ActionController, визначає, чи був викликаний render тому наступний код буде працювати без проблем:

Це отрендеріть книгу з заданим special? за допомогою шаблону special_show. в той час як інші книги будуть рендери з дефолтних шаблоном show.

У продовженні будуть розкриті питання використання redirect_to і head