【问题标题】:How can I force js.erb to refresh Ruby code如何强制 js.erb 刷新 Ruby 代码
【发布时间】:2020-05-03 03:09:23
【问题描述】:

我正在尝试将我的 XslSheet 模型的 data_file_names 列表放入我的 js.erb 文件中的 select 下拉列表中。

我在 input.js.erb 中尝试了以下内容:

inputEx.registerType("button", inputEx.ButtonField, [
{
    type: "select",
    label: I18n.t('form.field.xsl'),
    name: "xsl",
    choices: <% if User.current_user %>
               <% if User.current_user.current_scope['ab'] %>
                 <%= XslSheet.where(:assetable_id=>User.current_user.current_scope['ab']).pluck(:data_file_name) %>
               <% end %>
             <% end %>,
    required: false
}], true);

我也试过把它放在一个部分并渲染它:

input.js.erb:

inputEx.registerType("button", inputEx.ButtonField, [
{
    type: "select",
    label: I18n.t('form.field.xsl'),
    name: "xsl",
    choices: <%= Erubis::Eruby.new(File.read(File.join(Rails.root, 'app/views/admin/forms', '_xsl_sheet_names.html.erb'))).result(period: @period) %>,
    required: false
}], true);

_xsl_sheet_names.html.erb:

<% if User.current_user %>
  <% if User.current_user.current_scope['ab'] %>
  <%= XslSheet.where(:assetable_id=>User.current_user.current_scope['ab']).pluck(:data_file_name) %>
  <% end %>
<% end %>

由于我的 input.js.erb 位于 assets 文件夹中,因此需要使用 Erubis 来渲染部分内容。

这些方法都不起作用。我需要清除 tmp/cache 文件夹才能在选择中查看更新的值。 清除缓存并重新加载页面后,我可以看到更新的值。

还有其他方法可以尝试吗?

编辑:

现在尝试在 XslSheet 模型中创建一个方法并在 input.js.erb 中调用它。

xsl_sheet.rb

def xsl_names
    if User.current_user 
      if User.current_user.current_scope['Application'] 
        x = XslSheet.where(:assetable_id=>User.current_user.current_scope['Application']).pluck(:data_file_name) 
        x
      end 
    end 
  end

input.js.erb

choices: <% x = XslSheet.new %>
              <%= x.xsl_names %>,

这也需要在显示更新值之前清除缓存

【问题讨论】:

  • input.js.erb 位于何处?如果它在app/assets 中,则意味着它将成为资产管道的一部分,它应该只包含静态资产。不是针对每个请求而更改的资产。
  • @3limin4t0r 是的,它在应用程序/资产中。我不确定如果没有这个文件,我还能如何操作选择的内容!

标签: javascript ruby-on-rails ruby asset-pipeline erb


【解决方案1】:

app/assets 中的所有内容都应该是静态的,并且只会在生产服务器上预编译一次(这意味着 ERB 也将执行一次)。您完全可以使用 ERB 的原因是正确链接到图像和其他静态文件。他们将获得指纹,您需要使用资产帮助程序来正确设置 URL。

现在开始解决您的问题,因为您想要一些动态 JavaScript,请考虑创建一个提供动态 JavaScript 的 /js/:file_name 路由。

# app/routes.rb
get '/js/:file_name', as: 'dynamic_js', to: 'javascript#show', defaults: { format: 'js' }

现在为路由添加一个新控制器。

# app/controllers/javascript_controller.rb
class JavascriptController < ApplicationController
  FILE_PATH = "#{Rails.root}/app/views/javascript/*"
  EXT_REGEX = /[.]js(?:[.]erb)?\z/
  FILES = Dir[FILE_PATH].grep(EXT_REGEX).map { |file| file.sub(EXT_REGEX, '') }

  def show
    unless FILES.include?(params[:file_name])
      raise ActiveRecord::RecordNotFound, # handled with 404 by default
            "Couldn't find JavaScript with file name '#{params[:file_name]}'"
    end

    render params[:file_name]
  end
end

将您的 JavaScript 文件移出

app/assets/javascripts/input.js.erb

app/view/javascript/input.js.erb

最后要做的是更新用法。由于您很可能希望使用已加载的静态 JavaScript 文件/库,因此该文件应在静态 JavaScript 资产之后加载。

<%# app/views/layouts/application.html.erb %>
<!doctype html>
<head>
  <%# ... %>
</head>

<body>
  <%= yield # your main yield for all views %>
  <%= javascript_include_tag 'application' %>
  <%= yield :javascript %>
</body>
</html>

有了以上内容,您现在可以使用content_for 方法。您现在应该能够创建以下视图。

<% content_for :javascript do %>
  <%= javascript_tag '', src: dynamic_js_path('input', format: :js) %>
<% end %>

<p>Your normal view content</p>

或者,如果您需要在每个页面上加载此特定脚本,您可以直接将其插入app/views/layouts/application.html.erb

您可能还想阅读writing unobtrusive JavaScript,这是一种从元素中提取动态数据的静态 JavaScript。通过这种方式,您可以保持 JavaScript 静态,同时本质上通过视图提供参数。

如果您想了解更多关于资产管道的内部信息,可以找到他们here

【讨论】:

    猜你喜欢
    • 2016-11-18
    • 1970-01-01
    • 2012-12-15
    • 1970-01-01
    • 1970-01-01
    • 2010-11-16
    • 2015-11-25
    • 2011-01-13
    • 1970-01-01
    相关资源
    最近更新 更多