【问题标题】:Rails Ajax Call to Controller Needs RecordRails Ajax 对控制器的调用需要记录
【发布时间】:2022-01-10 04:25:39
【问题描述】:

我正在使用Rails ruby 6.1.4ruby 2.6.7

我有一个用于newedit 视图的部分表单。有两个select 下拉表单元素。 application.js 代码对controller 进行Ajax 调用,以根据第一个选择的内容来填充第二个下拉列表。

对于new 视图,我的代码运行良好。但是,在edit 视图中查看记录时,它不起作用。在 edit 视图上时,路径中似乎需要一个 id

在我的浏览器中使用developer tools 时,console 窗口在edit 视图上显示此错误:

[XHR] GET http://localhost:3000/fitness/weights/24/exercises?muscle_group=SHOULDERS

如您所见,它需要路径中的id。但我不需要id 来获得下拉练习。当然,第二个下拉菜单不会填充。

如何调整路线以使newedit 视图都能正常工作?或者,我需要更改我的 ajax 调用吗?注意:当我将:exercises 移出路线中的collection 时,会发生相反的情况; new 表单不起作用,但 edit 表单可以。

这是我的代码:

application.js:

// if edit view is showing
// get the current value of the Muscle Group field
//
var current_muscle_group;
if( $('#fitness_weight_muscle_group') ){
  current_muscle_group = $('#fitness_weight_muscle_group').val();
}
if( current_muscle_group != '' && current_muscle_group != 'Select One' && current_muscle_group != null ){
  get_exercises(current_muscle_group);
}


// user selects muscle_group from drop-down
// new or edit form
//
$('#fitness_weight_muscle_group').change(function(){
  get_exercises($(this).val());
})

// get_exercises
// ajax call to controller#exercises
// to get exercies for the muscle_group
//
function get_exercises(current_muscle_group){
  $.ajax({
    url: "exercises",
    dataType: "json",
    data: {muscle_group: current_muscle_group},
    success: function(data){
      populate_exercise_select(data);
    }
  });
}
...

控制器

...fitness/weights/controller:

  protect_from_forgery except: [:exercises, :past_exercise, :max_weight]
  ...

  def exercises
    # run sql to get exercises for muscle group passed in 
    if params[:muscle_group]
    @exercises=Fitness::Weight.select("DISTINCT exercise")
                              .where(admin_user_id: session[:user_id])
                              .where(muscle_group: params[:muscle_group].upcase)
    return render json: @exercises
  end
...

我的路线

config/routes:
...
resources :weights do
  collection do
    get  :exercises
    ...
  end
    ## added this route to satisfy issue with ajax call
    ## ... to controller action that requires a record id
  get :get_edit_exercises
end
...

解决方案

在查看edit 表单进行记录时,我添加了一条新路线(见上文)以解决路径中的ID 问题。我添加了一个controller#get_edit_exercises 操作来匹配路线。它返回 @exercises 就像 def exercises 一样。

当它是一个编辑视图时,我将application.js 更改为调用新的controller#get_edit_exercises 操作。如果ID 在路径/url 中,则它是一个编辑视图。

application.js

// get the exercises
function get_exercises(current_muscle_group){
  var url = "exercises";
  var current_record_id = get_current_record_id();  // function below

  if( current_record_id > 0 ){
    // get_exercises is for edit form. it expects an ID
    url = "/fitness/weights/" + current_record_id + "/get_edit_exercises";
  }
  $.ajax({
    url: url,
    dataType: "json",
    data: {muscle_group: current_muscle_group},
    success: function(data){
      populate_exercise_select(data);
    }
  })
}

function get_current_record_id() {
  var pathname = $(location).attr('pathname');
  return pathname.replace(/[^0-9]/g,'');
}

注意: id 在路径中显示了两次,但在 url: url 中使用完整路径解决了这个问题。还需要转发/

url = "/fitness/weights/" + current_record_id + "/get_edit_exercises";```

I also added the new ```controller#get_edit_exercises``` to the controller's ```protect_from_forgery except: [...]```

Everything works. I just need to DRY up some code now.

【问题讨论】:

    标签: javascript jquery ruby-on-rails ajax


    【解决方案1】:

    换句话说,我们有一个 has_many 练习的肌肉组,(也许还有一个练习 has_many 肌肉组),如果它是一个双向的 has_many,那么它可以通过muscle_group has_and_belongs_to_many exercises 实现,反之亦然。

    因此,要填充练习下拉列表,对于给定的肌肉组,我建议使用带有 index 方法的 ExerciseController,该方法可以接受肌肉组 id 参数并使用练习列表响应 ajax 请求。

    所以路线是:

    resources :muscle_groups do
      resources :exercises
    end
    

    和控制器:

    class ExercisesController < ApplicationController
      def index
        @exercises = Exercise.joins(exercise_muscles: :muscles)
                             .where(muscles: { id: params[:muscle_group_id] })
        render @exercises # assumes a partial file '_exercise.html.erb' produces the option tag for an exercise dropdown
      end
    end
    

    【讨论】:

    • @max 编辑后我注意到一个错误(很好的编辑,感谢@max)。路线应该制作像/muscle_groups/:muscle_group_id/exercises这样的网址。
    • 感谢您的回答。它让我想到了一个新的路由和控制器来解决 ID 问题。我应该早点看到的。我已经编辑了我的问题以在底部添加解决方案。
    • @JohnCowan 很好,你可以让它工作,但在权重控制器中使用get_exercisesget_edit_exercises 并不是一种好的风格。是的,它可以工作,但最好将控制器方法限制为基本的 CRUD,所以如果你要返回 Exercise 对象的集合,它应该在练习控制器中。当您只是试图让它工作时,样式问题可能看起来并不重要,但当您必须维护代码时它们会非常有用。在你让它工作并拥有一个测试套件(你确实有测试,对吗?)之后,最后一步是重构并使它变得漂亮。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-26
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多