2013-04-20 1 views
1

Я немного новичок в сцене RoR ... и я только сейчас начинаю соединять точки. Можете ли вы, прекрасные люди SO, дать мне более четкое руководство и направление в моей жизни?Rails: Routes, Controllers, Views, Oh My (восклицательный знак)

Я не понимаю взаимосвязи между маршрутами, контроллерами и представлениями (и как они соединяются друг с другом).

Итак, я получил мой контроллер с index, show, new, create, destroy методы. И соответствующее

GET /entries(.:format)      entries#index 
POST /entries(.:format)      entries#create 
GET /entries/new(.:format)     entries#new 
GET /entries/:id/edit(.:format)   entries#edit 
GET /entries/:id(.:format)     entries#show 
PUT /entries/:id(.:format)     entries#update 
DELETE /entries/:id(.:format)     entries#destroy 

Каким образом, если добавить новый метод vote_up или vote_down, например, и мнение с соответствующими именами действий, он не работает.

1) Каков правильный способ добавления новых действий и подключения их к представлениям? 2) Бонус Каков правильный способ сделать эти методы ajax-совместимыми (сделать частичным с ajax)? Что произойдет, если у пользователя нет js?

Я могу расширить/развить этот вопрос на основе ответов, которые я получаю.

Я устал от таких вещей, как: пользовательский маршрут маршрута действия и т. Д., Чтобы уклониться от моих приложений. Это дренаж и плохая форма, и я, наконец, дошел до уровня, чтобы понять лингво - я был самоучкой 100% ... поэтому, пожалуйста, постарайтесь понять, можете ли вы для молодого падавана.

+0

почтовый индекс из файла 'routes.rb'. – ole

ответ

6

Вот как думать об этом, с самого начала:

1) Одно и единственное, что ваше приложение делает реагировать на HTTP-запросы.

Наиболее типичные виды запросов являются:

  • GET - пользователь вводит что-то в адресной строке своего браузера и хиты Enter.

  • POST - пользователь подает заявку на форме.

Существуют также другие виды HTTP-запросов, самое главное PUT, PATCH и DELETE. Rails следует за шаблоном REST, что означает, что он присваивает определенные значения этим HTTP-глаголам.

2) Когда какой-либо запрос поступает в ваше приложение, он должен быть перенаправлен на действие контроллера.

Ваш routes.rb файл представляет собой набор инструкций для Rails Router (ActionDispatch), который сообщает маршрутизатору, куда отправлять запросы.«Стандарт» рельсы ресурса дается как ярлык, например:

resources :things 

Это означает следующее:

GET /things => things#index 

GET /things/:id => things#show 

GET /things/new => things#new 

GET /things/edit/:id => things#edit 

POST /things => things#create 

PUT /things/:id => things#update 

DELETE /things/:id => things#destroy 

Они считаются стандартными RESTful действия - ничто иное не установлено вашим resources :things декларации , Итак, если вы хотите, чтобы контроллер выполнял другие нестандартные действия, вы должны добавить их вручную.

Если вы хотите, чтобы выполнить действие на конкретную запись, лучший способ заключается в использовании:

resources :things do 
    member do 
    get 'vote_up' 
    end 
end 

Это говорит маршрутизатору, что если кто-то делает запрос GET к /things/123/vote_up, что он должен вызвать в ThingsControllervote_up действие.

Все это подробно изложено в Rails Guide, вы должны прочитать все это.

3) Задача вашего диспетчера - отправить ответ на запрос.

Обычно это означает что-то вроде загрузки записи из базы данных и визуализации представления для этой записи.

Каждое действие контроллера завершается отправкой ответа обратно на входящий запрос. Этот ответ может быть либо вызовом render, что означает отправку некоторых данных в некотором формате - или вызов redirect - который в основном делает новый запрос для вас, и поэтому вы получаете ответ от этого другого запроса.

В Rails перенаправление эффективно отправляет запрос на другое действие контроллера.

Render call отправляет данные в ответ на запрос.

При вызове render :new, это ярлык render :template => :new, который загружает шаблон app/views/things/new.html.erb (или любой другой), передает его данные из контроллера (обычно ваши переменные экземпляра) и оценивает это с помощью языка шаблонов (ERB, HAML и т. д.). Это приводит к большой строке HTML, которую контроллер затем передает в браузер.

Хотите видеть это в себе? Попробуйте окончание контроллер с render :text => 'Hello World', или даже:

render :inline => '<!DOCTYPE html><head><title>Inline Wow!</title></head><body>Mind blown.</body></html>' 

Посмотрите, что происходит.

При ответе (отрисовке) вы можете отправлять «обычные» HTML-шаблоны, имея в своем распоряжении всю ценность страницы (head, body и т. Д.) Или частичную, которая используется Ajax. Вы также можете отправлять необработанные данные, такие как JSON или XML. На самом деле это всего лишь текст, и в зависимости от содержимого этого текста (и заголовков HTTP, которые приходят с ним) браузер, сценарий или клиентское приложение обрабатывают его соответствующим образом.

Опять же, см. Rails Guide.

4) Когда запрос сделан браузером, вы, вероятно, захотите отправить обратно HTML. Если запрос сделан Ajax, вы, вероятно, захотите отправить обратно JSON.

В случае пользовательского действия, такого как vote_up, вы можете не захотеть показать шаблон вообще, а просто перенаправить. Итак, у вас может быть что-то вроде этого:

ThingsController < ApplicationController 

    def vote_up 
    @thing = Thing.find(params[:id]) 
    @thing.vote_up 
    redirect_to @thing 
    end 

end 

Теперь одно из преимуществ маршрутизатора - это предоставить вам URL-адреса. Если вы создали маршрут и действия, как показано выше, на странице «показать вещь» вы могли бы иметь URL вроде этого:

link_to 'Vote up this thing!', vote_up_thing_path(@thing) 

Это создало бы ссылку на things/123/vote_up, и если кто-то нажал на него будет запускать код в действии vote_up на ThingsController, а затем перенаправлять обратно в представление show thing.

5) Ваши шаблоны отправляют сообщения контроллерам, используя ссылки и формы. Ссылки делают запросы GET, формы обрабатывают запросы POST.

Если вы хотите начать с запросов AJAX, все в порядке. В этом случае вам просто нужно сделать запрос в Javascript и обработать ответ. Так, например, вы могли бы поставить что-то вроде этого в шаблоне:

= link_to 'Vote up this thing', vote_up_thing_path(@thing), :id => 'vote-up-button' 

Тогда в Javascript (с JQuery) вы могли бы иметь такую ​​функцию:

$(function(){ 
    $('a#vote-up-button').click(function(event){ 
    event.preventDefault(); 
    $.ajax({ 
     url: this.attr('href'), 
     type: 'GET', 
     success: function(){...}, 
     error: function(){...} 
    }); 
    }); 
}); 

В этом случае JQuery Ajax метод просто делает запрос на получение, а затем выполняет функцию обратного вызова на основе полученного ответа.

6) Структура вашего контроллера/маршрута не влияет на какие запросы вы можете сделать, только какое действие будет реагировать на то, какой метод HTTP на каком URL-адресе.

Что вы делаете внутри вашего действия контроллера определяет, являетесь ли вы готовы ответить на яваскрипт или HTML запросы и т.д.

Хотя рельсы, конечно, иметь возможность обрабатывать несколько форматов запросов в одном действии контроллера, используя блок respond_to , в практическом отношении я нахожу, что все работает намного плавно, когда вы выбираете, чтобы маршруты отвечали только на один или другой формат.

IE: Я бы сделал ваши обычные запросы на загрузку страницы (индекс, показать, новый, отредактировал) только HTML-запросы, а затем я сделаю любые дополнительные действия AJAX, которые вы хотите добавить, только Javascript - т.е. они отвечают с JSON вместо HTML. Конечно, вам не обязательно это делать, но ваша жизнь будет легче, если вы это сделаете.

Надеюсь, это даст вам более четкое представление о том, что происходит в вашем приложении. Добро пожаловать в Rails, вы присоединяетесь к большому сообществу!

+0

Если вы читали, когда я редактировал, извините. Трудно получить форматирование и т. Д. Прямо на длинном столбце из небольшого окна редактирования. Если у вас есть вопросы, сообщите мне, и я постараюсь ответить на них. – Andrew

+0

Эндрю, очень полезно сообщение. Спасибо. –

0

Если у вас есть RESTful контроллер:

resources :entries do 
    collection do 
    get :vote_down 
    get :vote_up 
    end 
end 

это будет генерировать 2 дополнительных маршрутов:

GET /entries/:id/vote_up(.:format)     entries#vote_up 
GET /entries/:id/vote_down(.:format)    entries#vote_down 

Вы можете легко изменить метод HTTP GET для, POST, PUT и DELETE.

Кроме того, отметьте «Adding More RESTful Actions» в документации по маршрутам.

+1

Возможно, это должны быть POST-запросы. –

+0

@ole, прочитайте, пожалуйста, весь вопрос выше. Я ищу полный подробный ответ. Я ценю отзывы, но я ищу, как связать это с контроллерами/представлениями и тем, как они взаимодействуют. –

2

Добро пожаловать в мир ROR. :)

Маршруты, контроллеры и представления работают вместе, чтобы перевести HTTP-запрос в какой-либо ответ (будь то HTML, JSON или XML). Каждый атакует другую часть проблемы.

Начиная с конца, views являются шаблонами в мире рельсов, и они обычно ERB. ERB - это всего лишь одна система шаблонов, другие могут быть использованы, например, haml. Их задача состоит в том, чтобы взять некоторые данные, данные им контроллером, и создать отформатированный вывод, снова, как правило, HTML, JSON или XML.

Но откуда вы знаете, какой вид рендеринга для конкретного запроса? Как вы получаете данные в своем представлении, чтобы он мог делать все необходимые вам динамические материалы? Это то, где входят контроллеры. Controllers - это классы ruby ​​с заданием изучения обработанного HTTP-запроса и любых связанных параметров, получения данных из базы данных (или где угодно), а затем передачи этих данных в представление. Обычно контроллер имеет несколько разных методов, каждый из которых соответствует другой задаче (например, создавать, показывать, обновлять и т. Д.).

Наконец, Routes являются DSL для анализа HTTP-запросов и отправки разобранного HTTP-запроса определенному методу контроллера. Это клей, который Rails использует для маршрутизации URL-адресов для методов, отсюда и имя, routes.

Что касается ваших конкретных вопросов:

1) Для того, чтобы создать новое действие, нужно добавить маршрут, метод контроллера и вид. Так, например, если вы хотите, чтобы получить количество ваших записей, вы можете добавить маршрут как:

get '/entries/count' => "entries#count" 

Это говорит ROR для вызова метода count в контроллере entries, когда этот URL будет получен. Ваш метод управления в этом случае будет что-то простое, как:

def count 
    @cnt = Entries.count 
end 

Тогда наконец, вы бы сделать вид в app/views/entries/count.html.erb, что было что-то вроде:

<p>Count: <%= @cnt %></p> 

2) Ajax совместимого кода действительно просто способ спросить «что, если запрошенный формат для этого запроса - JSON?». Для этого вам нужно использовать метод respond_to. В некотором смысле response_to является формальным способом указать другой вид для обработки форматирования запроса. Для продолжения приведенного выше примера вы можете:

def count 
    @cnt = Entries.count 
    respond_to do |fmt| 
    fmt.html # This just renders the default template 
    fmt.json { render json: { count: @cnt } } 
    end 
end 

N.b. - Весь код выше свободной руки. :)

+0

Благодарим вас за качественный ответ! Как происходит эта магия? Это то, что было трудно понять извне ... это немного волшебный, не так ли? :) –

+0

Это немного волшебный, да. Но любая достаточно продвинутая технология тоже! :) Если вы действительно хотите ответить на этот * вопрос, вы, вероятно, захотите прочитать исходный код ROR или, по крайней мере, сориентироваться в [API docs] (http://api.rubyonrails.org/).С точки зрения разработчика Rails предоставляет эти услуги, и пока вы будете следовать API, вам не нужно беспокоиться о том, как это сделать. Но если вы хотите узнать, исходным кодом Rails является авторитет. –

Смежные вопросы