0

我正在开发一个 Rails 应用程序,并试图将event_calendar gem 的“下个月”链接转换为 ajax 响应。

我将链接设置为远程:

  def month_link(month_date)
    link_to I18n.localize(month_date, :format => "%B"),
      {:month => month_date.month, :year => month_date.year},
      remote: true
  end

告诉它响应js...

respond_to do |format|
  format.html
  format.js { render text: "help me!" }
end

它有效!

Started GET "/calendar/2012/6" for 127.0.0.1 at 2012-07-03 15:27:42 -0500
Processing by CalendarController#index as JS
  Parameters: {"year"=>"2012", "month"=>"6"}
  Event Load (0.3ms)  SELECT "events".* FROM "events" WHERE (('2012-05-27 05:00:00.000000' <= end_at) AND (start_at< '2012-07-01 05:00:00.000000')) ORDER BY start_at ASC
  Rendered text template (0.0ms)
Completed 200 OK in 14ms (Views: 0.7ms | ActiveRecord: 0.3ms)

好吧......除了它实际上没有渲染任何东西的部分我通过它。如果我只是告诉它format.js没有渲染,它实际上不会响应 js 文件。

什么可能导致渲染不显示?

更新

  • 我刚刚注意到,如果您像这样访问 urllocalhost:3000/calendar/2012/6.js它会按预期工作,所以我认为这是如何设置链接的问题?

  • 好的,我得到了 js 文件,但我不知道为什么。我认为我在使用错误render(尽管我可以发誓我曾经将它用于调试目的)。我猜 render 只有在响应 html 请求时才真正呈现 html 页面。会有意义,因为它将 json 传递给 javascript 以进行 ajax 请求。

  • 问题的另一部分是我试图将 CoffeeScript 与index.js.coffee.erbor一起使用index.js.erb.coffee。我以为它工作了最长时间,但真正发生的是,它使用的是index.js.erb我先写的原件,即使我已经删除了它。一旦我重新启动服务器,一切都坏了。

4

2 回答 2

1

试试这个:

def month_link(month_date)
  link_to I18n.localize(month_date, :format => "%B"),
  {:remote=>true, :month => month_date.month, :year => month_date.year}
end

您要使用的 link_to 格式为:

link_to(body, url_options = {}, html_options = {})

:remote=>true 想要在 url_options 中。我不确定 :month 和 :year 键的用途,但如果它们是 html 选项,你会想要这个:

def month_link(month_date)
  link_to I18n.localize(month_date, :format => "%B"),
  {:remote=>true}, 
  {:month => month_date.month, :year => month_date.year}
end
于 2012-07-03T21:26:58.693 回答
1

似乎默认情况下该remote选项会忽略任何呈现或重定向的尝试。考虑到 Ajax 的目的是防止这两种情况……我明白为什么。

为了自我参考,这里是(据我所知)创建远程时发生的情况link_to

jquery_ujs.js 的第 51 行

  $.rails = rails = {
    // Link elements bound by jquery-ujs
    linkClickSelector: 'a[data-confirm], a[data-method], a[data-remote], a[data-disable-with]',

下面linkClickSelector我们在第 300 行找到这个函数

  $(document).delegate(rails.linkClickSelector, 'click.rails', function(e) {
    var link = $(this), method = link.data('method'), data = link.data('params');
    if (!rails.allowAction(link)) return rails.stopEverything(e);

    if (link.is(rails.linkDisableSelector)) rails.disableElement(link);

    if (link.data('remote') !== undefined) {
      if ( (e.metaKey || e.ctrlKey) && (!method || method === 'GET') && !data ) { return true; }

      if (rails.handleRemote(link) === false) { rails.enableElement(link); }
      return false;

    } else if (link.data('method')) {
      rails.handleMethod(link);
      return false;
    }
  });

假设handleRemote处理 AJAX,我们在第 107 行找到这个怪物

// Submits "remote" forms and links with ajax
handleRemote: function(element) {
  var method, url, data, crossDomain, dataType, options;

  if (rails.fire(element, 'ajax:before')) {
    crossDomain = element.data('cross-domain') || null;
    dataType = element.data('type') || ($.ajaxSettings && $.ajaxSettings.dataType);

    if (element.is('form')) {
      method = element.attr('method');
      url = element.attr('action');
      data = element.serializeArray();
      // memoized value from clicked submit button
      var button = element.data('ujs:submit-button');
      if (button) {
        data.push(button);
        element.data('ujs:submit-button', null);
      }
    } else if (element.is(rails.inputChangeSelector)) {
      method = element.data('method');
      url = element.data('url');
      data = element.serialize();
      if (element.data('params')) data = data + "&" + element.data('params');
    } else {
      method = element.data('method');
      url = rails.href(element);
      data = element.data('params') || null;
    }

    options = {
      type: method || 'GET', data: data, dataType: dataType, crossDomain: crossDomain,
      // stopping the "ajax:beforeSend" event will cancel the ajax request
      beforeSend: function(xhr, settings) {
        if (settings.dataType === undefined) {
          xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
        }
        return rails.fire(element, 'ajax:beforeSend', [xhr, settings]);
      },
      success: function(data, status, xhr) {
        element.trigger('ajax:success', [data, status, xhr]);
      },
      complete: function(xhr, status) {
        element.trigger('ajax:complete', [xhr, status]);
      },
      error: function(xhr, status, error) {
        element.trigger('ajax:error', [xhr, status, error]);
      }
    };
    // Only pass url to `ajax` options if not blank
    if (url) { options.url = url; }

    return rails.ajax(options);
  } else {
    return false;
  }
},
于 2012-07-04T17:06:18.110 回答