AJAX调用无法在rails 3中工作

时间:2011-05-13 07:58:49

标签: javascript ajax ruby-on-rails-3

我正在尝试让我的AJAX调用使用rails 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中。这是非常基本的,因为我只想将CV的输出作为该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 个答案:

答案 0 :(得分:1)

使用= "$('details').html(#{@data});"代码会在HAML中转义。

使用!= "$('details').html(#{@data});"然后执行代码并替换内容。

但是我不确定'细节'是否是正确的选择器。据我所知,如果是ID,你应该使用'#details'。

答案 1 :(得分:1)

我认为当你将JS与服务器端代码分开时,你会发现更少的麻烦,而且twain不会满足。您的控制器基本上只是读取文件并将其加载到页面上。我们完全可以在JS中做到这一点:

简历链接

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

JS连线

$('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 plugin可以让这更容易:

$('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连线 - 原型

以下是使用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);
});

您可以更进一步,将请求/提出问题与amplify.request分开。另请参阅JS模板系统,如Handlebars

我知道将Rails模板与Javascript结合起来很诱人......但根据我的经验,这从未真正解决过。将控制器编写为JSON / XML服务API并在Javascript中进行数据请求/模板化更容易。

从Rails中删除RJS是有原因的:当您在服务器端代码和前端代码之间创建这些不必要的连接时,您的应用程序会变得更脆弱并且难以维护。您的控制器不应该依赖于模板中的标记。

答案 2 :(得分:0)

感谢所有反馈人员,但我设法在我的帮助下得到了一些帮助。

在控制器中,我有以下代码:

@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以更新内容。我个人认为这种方法很容易理解。