javascript - JavaScript 的 Fetch 可以用来更新 Rails Controller 中的参数值吗?

标签 javascript ruby-on-rails datatables

使用 JavaScript、Rails 以及 DataTables API 设置用于跟踪任务事件的报告界面。现在,我正在尝试弄清楚如何通过使用 JavaScript 连接界面的现有日期选择按钮(例如,今天、过去 7 天、过去 30 天等)来用新数据更新面向客户端的数据表在 Rails Controller 中的不同 time_range 参数值之间切换。

在 Controller 代码中,这些参数值之间的切换意味着会更新服务器端查询的 date_range 参数。此参数随后通过控制 db 命令的 WHERE 子句中指定的内容来过滤服务器端查询返回的数据。

我的问题是我在 JavaScript 中设置的获取请求显然无法对切换哪些参数值传递到控件产生任何影响流在 Controller 的 index 方法的顶部。

<小时/>

编辑

以下是单击“昨天”和“过去 7 天”日期选择按钮后开发工具中的网络 Pane 显示的内容。这些点击似乎正在运行成功的获取请求:

Tracking Fetch requests in the Network activity tracker in DevTools

我应该在这里指出的另一件事是,从网络工具的预览中返回和查看的数据与我的“昨天”提取和“过去 7 天”提取的相同 。发出 fetch 请求的全部要点是,它通过与 Rails Controller 中编写的查询交互,检索根据界面中选择的日期范围定制的 json 数据结构。

在那里,使用 puts 在控制流 block 之后输出我的 @date_range 变量的值(用破折号 block 分隔此调试方面),Rails 控制台准确地报告了问题 - 我的客户端代码没有按预期更新@date_range的值,但是,它确实显示顶部的 Parameters 哈希记录了传递给 time_range 的值更新的可见性:

Started GET "/task_reporting?time_range=yesterday" for ::1 at 2019-09-17 10:01:21 -0400
Processing by TaskReportingController#index as JSON
  Parameters: {"time_range"=>"yesterday", "task_reporting"=>{}}
  User Load (2.6ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
      ---------------------------------------------------------
      The value of @date_range is >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
      ---------------------------------------------------------
   (13.1ms)          SELECT tasks.id, tasks.name, users.name, DATE_FORMAT(MAX(kits.updated_at), '%a. %b %d, %Y'),
        COUNT(DISTINCT(DATE(kits.updated_at))), COUNT(DISTINCT(kits.id))
        FROM kits
        JOIN tasks ON tasks.id = kits.task_id JOIN users ON users.id = kits.user_id JOIN annotations ON annotations.kit_id = kits.id
        WHERE kits.updated_at >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
        GROUP BY tasks.id, users.name

Completed 200 OK in 39ms (Views: 1.3ms | ActiveRecord: 15.7ms)


Started GET "/task_reporting?time_range=last_seven_days" for ::1 at 2019-09-17 10:02:29 -0400
Processing by TaskReportingController#index as JSON
  Parameters: {"time_range"=>"last_seven_days", "task_reporting"=>{}}
  User Load (4.3ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
      ---------------------------------------------------------
      The value of @date_range is >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
      ---------------------------------------------------------
   (1.7ms)          SELECT tasks.id, tasks.name, users.name, DATE_FORMAT(MAX(kits.updated_at), '%a. %b %d, %Y'),
        COUNT(DISTINCT(DATE(kits.updated_at))), COUNT(DISTINCT(kits.id))
        FROM kits
        JOIN tasks ON tasks.id = kits.task_id JOIN users ON users.id = kits.user_id JOIN annotations ON annotations.kit_id = kits.id
        WHERE kits.updated_at >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
        GROUP BY tasks.id, users.name

Completed 200 OK in 18ms (Views: 1.1ms | ActiveRecord: 6.0ms)

结束编辑

<小时/>

代码注释中描述了更多信息...

我的 JavaScript (task_reporting.js.coffee) 是从该工具的 View 代码末尾调用的:

Rails View (简化)

index.html.haml:

-content_for :action_specific_js do
  != "task_reporting.init()"

JavaScript(jQuery + CoffeeScript)

window.task_reporting = ( ->
    // Important: initializes DataTable, loading default, thirty-day date-range data
    init: () ->
          this.init_datepicker_button()
          this.init_daterange_buttons()
          $("#tasks_report").DataTable
              paging: false
              scrollY: "400px"
              scrollCollapse: true
              sAjaxSource: "/task_reporting"
              order: [[1, "asc"]]
    // Important: Believe the problem is here.
    // Method should send fetch request to server-side, altering query parameters in the controller
    render_table: (passed_time_range) ->
          query_params = "?time_range=#{passed_time_range}"
          console.log(query_params)

          fetch("/task_reporting#{query_params}",
              method: 'GET'
              headers:
                  "content-type": "application/json"
                  "Accept": "application/json"
              credentials: "same-origin"
          )
          .then (response) -> response.json()
          .then (data) ->
            console.log(data)
            $("#tasks_report").DataTable().clear().rows.add(data).draw
          .catch((e) -> console.error("Error:", e))

    // Not important: sets listener on date-range button (undeveloped)
    init_datepicker_button: ->
          dateRangeButton = $(".datepickerContainer > button#daterange")
          dateRangeButton.on "click", this.init_dropdown

    // Sets listeners on individual date range buttons, calling pass_time_range to set param value in fetch
    init_daterange_buttons: ->
          rangeItemButton = $(".range-item")
          rangeItemButton.on "click", this.pass_time_range

    init_dropdown: ->
          console.log "dropdown here"

    // Handles event on daterange buttons
    // Passes param value to render_table according to button's class name
    pass_time_range: (e) ->
          e.preventDefault()
          // console.log e
          clickedTimeRange = e.target.className
          if clickedTimeRange.includes "today"
              task_reporting.render_table("today")
          else if clickedTimeRange.includes "yesterday"
              task_reporting.render_table("yesterday")
          else if clickedTimeRange.includes "last_seven_days"
              task_reporting.render_table("last_seven_days")
          else if clickedTimeRange.includes "last_thirty_days"
              task_reporting.render_table("last_thirty_days")
          else if clickedTimeRange.includes "custom_range"
              task_reporting.render_table("custom_range")
)()

Rails Controller

class TaskReportingController < ApplicationController
  
  before_filter :authenticate
  
  def index
    
      # Checks param value and updates @date_range accordingly
      if params[:time_range] == "range_today"
        @date_range = '>= CURDATE()'
      elsif params[:time_range] == "range_yesterday"
        @date_range = '>= DATE_SUB(CURDATE(), INTERVAL 1 DAY)'
      elsif params[:time_range] == "range_last_seven_days"
        @date_range = '>= DATE_SUB(CURDATE(), INTERVAL 7 DAY)'
      else params[:time_range] == "range_last_thirty_days"
        @date_range = '>= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)'
      end
    
    # My fetch obviously fails to influence the :time_range param value
    # as the default thirty day range is always output here
    print <<-EOM
      ############
      The value of @date_range is #{@date_range}
      ############
    EOM

    # heredoc query
    query = <<-SQL
        SELECT tasks.name, users.name, DATE_FORMAT(MAX(kits.updated_at), '%a. %b %d, %Y'), 
        COUNT(DISTINCT(DATE(kits.updated_at))), COUNT(DISTINCT(kits.id)) 
        FROM kits
        JOIN tasks ON tasks.id = kits.task_id JOIN users ON users.id = kits.user_id JOIN annotations ON annotations.kit_id = kits.id
        WHERE kits.updated_at #{@date_range}
        GROUP BY tasks.id, users.name
      SQL
        
    query_result = Kit.connection.execute(query).to_a

    respond_to do |format|
      format.html
      format.json { render json: {"aaData": query_result} }
    end
  end
end

在我出错的地方寻找一些方向。欢迎就使用这样的 fetch 是否是使用 DataTables API 从客户端更新表数据的正确方法提出任何建议。

最佳答案

日志中您的参数值为“yesterday”或“last_seven_days”,但您的代码会检查“range_yesterday”或“range_last_seven_days”。这就是它失败并回落到默认范围的原因。

做类似的事情:

query_params = "?time_range=range_#{passed_time_range}"

或更改您的检查以与“昨天”而不是“range_yesterday”进行比较

关于javascript - JavaScript 的 Fetch 可以用来更新 Rails Controller 中的参数值吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57962704/

相关文章:

javascript - Internet Explorer 何时在文档对象上引入 readyState 属性?

对象中的 JavaScript 变量

ruby-on-rails - 防止Rails中重复记录的正确方法

javascript - Jquery 数据表排序和 rowReorder 不起作用

javascript - datatable.fnDraw() 不是函数

javascript - 后续调用 reloadData() 时, Angular 数据表有效负载格式不会更改

javascript - 在移动设备上将页面列表动态显示为一行

ruby-on-rails - 如何为多态关联执行稍微复杂的 ActiveRecord 范围查询?

ruby-on-rails - 设计字段上的错误消息

javascript - 下载多个文件和 zip - Chrome 扩展