Вызов AJAX не работает в рельсах 3 - PullRequest
0 голосов
/ 13 мая 2011

Я пытаюсь заставить мой вызов AJAX работать с рельсами 3, но я в замешательстве запутался.У меня есть индексная страница, на которой перечислены все объекты в небольшой таблице с подробной ссылкой за ней.Страница HAML выглядит следующим образом:

%h1
  Step 1: Create/upload your CV
#europasslogo
%table.index
  %tr
    %th.bottom_border= 'CV ID'
    %th.bottom_border= 'CV Title'
    %th.bottom_border= 'Links'
  - @cvs.each do |cv|
    %tr
      %td.cell= cv.id
      %td.cell= cv.name
      %td.cell
        = link_to 'Matching', match_resume_url(cv.id)
         
        = link_to "Details", cv_path(cv.id), {:remote => true, :method => :get}
.clear
#details

Идея состоит в том, что, когда пользователь нажимает ссылку "детали", ответ должен отображаться в блоке #details внизу.Это действительно просто, так как я просто хочу выводить резюме в виде открытого текста в этом div.

В моем контроллере я создал следующее:

class CvsController < ApplicationController
  def new
    @cvs = Cv.all
  end

  def show
    cv = Cv.find params[:id]
    @data = IO.readlines("public/cvs/#{cv.id}.xml", "").to_s
    render :layout => false
  end

  def match
    @cv = Cv.find params[:id]
    @language = Language.find_or_create_by_code :en
    @vacancies = Vacancy.joins(:vacancy_occupations).where('vacancy_occupations.concept_id' => @cv.occupations.collect{|o| o.id}).uniq
  end
end

Получает CV и читает соответствующий файл,Пока ничего особенного.Когда я открываю страницу и нажимаю на ссылку, я вижу, что запрос AJAX попадает на сервер следующим образом:

Started GET "/cvs/2" for 192.168.33.82 at Fri May 13 00:55:49 -0700 2011
  Processing by CvsController#show as JS
  Parameters: {"id"=>"2"}
  Cv Load (0.1ms)  SELECT `cvs`.* FROM `cvs` WHERE `cvs`.`id` = 2 LIMIT 1
Rendered cvs/show.js.haml (2.1ms)
Completed 200 OK in 69ms (Views: 4.3ms | ActiveRecord: 0.1ms)

Итак, я знаю, что сервер получает вызов AJAX и генерируется ответ.Используя Firebug, я также вижу ответ от сервера в консоли:

$('details').html(&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;?xml-stylesheet href=&quot;http://europass.cedefop.europa.eu/xml/cv_en_GB.xsl&quot; type=&quot;text/xsl&quot;?&gt;
&lt;europass:learnerinfo xsi:schemaLocation=&quot;http://europass.cedefop.europa.eu/Europass/V2.0 http://europass.cedefop.europa.eu/xml/EuropassSchema_V2.0.xsd&quot; xmlns:europass=&quot;http://europass.cedefop.europa.eu/Europass/V2.0&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; locale=&quot;en_GB&quot;&gt;
    &lt;docinfo&gt;
        &lt;issuedate&gt;2011-05-05T11:31:55+02:00&lt;/issuedate&gt;
        &lt;xsdversion&gt;V2.0&lt;/xsdversion&gt;
        &lt;comment&gt;Automatically generated Europass CV&lt;/comment&gt;&lt;/docinfo&gt;
    &lt;prefs&gt;
        &lt;field name=&quot;step1.firstName&quot; before=&quot;step1.lastName&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step1.addressInfo&quot; keep=&quot;true&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step1.telephone&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step1.mobile&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step1.fax&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step1.email&quot; keep=&quot;true&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step1.nationality&quot; keep=&quot;true&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step1.birthDate&quot; keep=&quot;true&quot; format=&quot;/numeric/long&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step1.gender&quot; keep=&quot;true&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step1.photo&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step1.application.label&quot; keep=&quot;true&quot;&gt;&lt;/field&gt;
        &lt;field format=&quot;/numeric/long&quot; name=&quot;step3List[0].period&quot;&gt;&lt;/field&gt;

        &lt;field name=&quot;step3List&quot; keep=&quot;true&quot; before=&quot;step4List&quot;&gt;&lt;/field&gt;
        &lt;field keep=&quot;false&quot; name=&quot;step3List[0].company.sector.label&quot;&gt;&lt;/field&gt;
        &lt;field keep=&quot;false&quot; name=&quot;step3List[0].company.addressInfo&quot;&gt;&lt;/field&gt;
        &lt;field keep=&quot;false&quot; name=&quot;step3List[0].company.name&quot;&gt;&lt;/field&gt;
        &lt;field keep=&quot;true&quot; name=&quot;step3List[0].activities&quot;&gt;&lt;/field&gt;
        &lt;field keep=&quot;true&quot; name=&quot;step3List[0].position.label&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step4List&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step5.motherLanguages&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step5.foreignLanguageList&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step6.socialSkills&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step6.organisationalSkills&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step6.technicalSkills&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step6.computerSkills&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step6.artisticSkills&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step6.otherSkills&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step6.drivingLicences&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step7.additionalInfo&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;step7.annexes&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;
        &lt;field name=&quot;grid&quot; keep=&quot;false&quot;&gt;&lt;/field&gt;&lt;/prefs&gt;
    &lt;identification&gt;
        &lt;firstname&gt;Wouter&lt;/firstname&gt;
        &lt;lastname&gt;ESCOmatch&lt;/lastname&gt;
        &lt;contactinfo&gt;
            &lt;address&gt;
                &lt;addressLine&gt;Haachtstesteenweg&lt;/addressLine&gt;
                &lt;municipality&gt;Kampenhout&lt;/municipality&gt;
                &lt;postalCode&gt;1910&lt;/postalCode&gt;
                &lt;country&gt;
                    &lt;label&gt;BElgium&lt;/label&gt;&lt;/country&gt;&lt;/address&gt;
            &lt;telephone&gt;&lt;/telephone&gt;
            &lt;fax&gt;&lt;/fax&gt;
            &lt;mobile&gt;&lt;/mobile&gt;
            &lt;email&gt;wouter.dewanckel@tenforce.com&lt;/email&gt;&lt;/contactinfo&gt;
        &lt;demographics&gt;
            &lt;birthdate&gt;1975-01-26&lt;/birthdate&gt;
            &lt;gender&gt;M&lt;/gender&gt;
            &lt;nationality&gt;
                &lt;label&gt;belgium&lt;/label&gt;&lt;/nationality&gt;&lt;/demographics&gt;&lt;/identification&gt;
    &lt;application&gt;
        &lt;code&gt;71110&lt;/code&gt;
        &lt;label&gt;Miner&lt;/label&gt;&lt;/application&gt;
    &lt;workexperiencelist&gt;
        &lt;workexperience&gt;
            &lt;period&gt;
                &lt;from&gt;
                    &lt;year&gt;2000&lt;/year&gt;
                    &lt;month&gt;--02&lt;/month&gt;
                    &lt;day&gt;---02&lt;/day&gt;
                &lt;/from&gt;
                &lt;to&gt;
                    &lt;year&gt;2004&lt;/year&gt;
                    &lt;month&gt;--02&lt;/month&gt;
                    &lt;day&gt;---02&lt;/day&gt;
                &lt;/to&gt;
            &lt;/period&gt;
            &lt;position&gt;
                &lt;code&gt;82121&lt;/code&gt;
                &lt;label&gt;Quartermaster staff, military&lt;/label&gt;
            &lt;/position&gt;
            &lt;activities&gt;
                process control
                diving
                military
            &lt;/activities&gt;
            &lt;employer&gt;
                &lt;name&gt;&lt;/name&gt;
                &lt;address&gt;
                    &lt;addressLine&gt;&lt;/addressLine&gt;
                    &lt;municipality&gt;&lt;/municipality&gt;
                    &lt;postalCode&gt;&lt;/postalCode&gt;
                    &lt;country&gt;
                        &lt;label&gt;&lt;/label&gt;
                    &lt;/country&gt;
                &lt;/address&gt;
                &lt;sector&gt;
                    &lt;label&gt;&lt;/label&gt;
                &lt;/sector&gt;
            &lt;/employer&gt;
        &lt;/workexperience&gt;
    &lt;/workexperiencelist&gt;
    &lt;languagelist&gt;
        &lt;language xsi:type=&quot;europass:mother&quot;&gt;
            &lt;label&gt;           &lt;/label&gt;&lt;/language&gt;&lt;/languagelist&gt;
    &lt;skilllist&gt;
        &lt;skill type=&quot;social&quot;&gt;&lt;/skill&gt;
        &lt;skill type=&quot;organisational&quot;&gt;&lt;/skill&gt;
        &lt;skill type=&quot;technical&quot;&gt;&lt;/skill&gt;
        &lt;skill type=&quot;computer&quot;&gt;&lt;/skill&gt;
        &lt;skill type=&quot;artistic&quot;&gt;&lt;/skill&gt;
        &lt;skill type=&quot;other&quot;&gt;&lt;/skill&gt;
        &lt;structured-skill xsi:type=&quot;europass:driving&quot;&gt;&lt;/structured-skill&gt;&lt;/skilllist&gt;
    &lt;misclist&gt;
        &lt;misc type=&quot;additional&quot;&gt;&lt;/misc&gt;
        &lt;misc type=&quot;annexes&quot;&gt;&lt;/misc&gt;&lt;/misclist&gt;&lt;/europass:learnerinfo&gt;);

Извините, но файлы довольно большие.Итак, я вижу, как много генерируется Javascript.Файл show.js.haml выглядит следующим образом:

= "$('details').html(#{@data});"

Я что-то не так делаю?Я не очень хорош в этом JavaScript, но то, что я спрашиваю, не может быть таким сложным, верно?Все, что я хочу, это когда я нажимаю на ссылку, все, что находится внутри переменной @data, помещается в мои данные div ...

Ответы [ 3 ]

1 голос
/ 13 мая 2011

Я думаю, вы обнаружите, что гораздо меньше головной боли, когда вы отделяете JS от кода на стороне сервера, и никогда не встретите их. Ваш контроллер в основном просто читает файл и загружает его на страницу. Мы можем сделать это полностью в JS:

CV ссылка

= link_to "Details", cv_path(cv.id), :'data-cv-id' => cv.id

JS wireup

$('table.index').delegate('a[data-cv-id]', 'click', function (e) {
  var id = $(e.target).data('cv-id');
  $.ajax({
    type: 'GET',
    url: '/cv/' + id + '.xml',
    dataType: 'xml',
    success: function (xml) {
      $('#detail').html(xml);
    }
  });
  e.preventDefault();
});

(бесстыдный плагин) Мой плагин jquery может сделать это еще проще:

$('table.index').delegate('a[data-cv-id]', 'click', function (e) {
  $.read('/cv/{id}.xml', { id: $(e.target).data('cv-id') })
   .then(function (xml) {
     $('#details').html(xml);
   });
  e.preventDefault();
});

JS wireup - прототип

Вот пример использования Prototype.js

var table = $$('table.index')[0];
$(table).on('a[data-cv-id]', 'click', function (event, element) {
  new Ajax.Request('/cv/' + event.getAttribute('data-cv-id') + '.xml', {
    method: 'get',
    onSuccess: function (transport) {
      //do something with transport.responseXML
      //not sure how to write Prototype code for this bit
    }
  });
  Event.stop(event);
});

Вы можете сделать этот шаг дальше и отделить запрос / представление проблем с помощью ampify.request . Также обратите внимание на системы шаблонов JS, такие как Handlebars .

Я знаю, что заманчиво комбинировать шаблоны Rails с Javascript ... но по моему опыту это никогда не сработало. Проще написать ваши контроллеры как API службы JSON / XML и выполнять запрос / шаблон данных в Javascript.

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

1 голос
/ 13 мая 2011

При = "$('details').html(#{@data});" код экранируется в HAML.

Используйте != "$('details').html(#{@data});", тогда код должен быть выполнен и заменить содержимое.

Однако я не уверен, что «детали» - правильный выбор. Насколько я знаю, вы должны использовать '#details', если это ID.

0 голосов
/ 13 мая 2011

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

В контроллере у меня есть следующий код:

@cv = Cv.find params[:id]
doc = REXML::Document.new File.open "public/cvs/#{@cv.id}.xml"
@data = REXML::XPath.first(doc.root, "identification").text
@data << REXML::XPath.first(doc.root, "application").text
@data << REXML::XPath.first(doc.root, "workexperiencelist").text

# Render the partial
render(:update) { |page| page.replace_html 'details', :partial => 'cvs/show', :layout => false}

Это загружает все нужные мне данные и частично отображает. Остальная часть команды выполняет магию, которая мне нужна, и запускает JavaScript для обновления. Я лично считаю, что этот подход намного легче понять.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...