Rails中的Ajax调用产生重复信息而不能正确显示页面

时间:2016-08-25 17:04:54

标签: jquery ruby-on-rails ajax

我正在创建一个应用,学生可以点击复选框说他们已经上过课。我尝试使用ajax调用来执行此操作,并实时更新同一页面。到目前为止,我能够在数据库中正确获取信息,但我有两个错误。一个错误是学生的名字在视图上显示两次(在硬刷新之后),第二个是代码没有在页面上实时显示结果。我该如何解决这些错误?我非常感谢任何帮助,我已经坚持了一段时间。这是我到目前为止的代码......

lecture.html.erb(查看页面,讲座显示页面)

<h1>Lecture Profile</h1>
<h3><%= @lecture.name %></h3>
<p>Start Time: <%= @lecture.start_time %></p>
<p>End Time: <%= @lecture.end_time %></p>
<p>Notes: <%= @lecture.notes %></p>
<div>
  <p><%= link_to "Edit Lecture", "/lectures/#{@lecture.id}/edit" %></p>
  <p><%= link_to "Delete Lecture", "/lectures/#{@lecture.id}", method: :delete, data:{confirm: "Are you sure you want to delete this lecture"} %></p>
</div><br>

<%= form_for @attendance, remote: true do |f| %>
  <%= render partial: "/attendances/form", locals: {f: f} %>

  <%= f.hidden_field :arrived, value: Time.now %>
  <%= f.hidden_field :student_id, value: current_student.id %>
  <%= f.hidden_field :lecture_id, value: @lecture.id %>
  <%= submit_tag "Submit" %>
<% end %>

<h2>Students Attended</h2>
  <%= render partial: "/attendances/index", locals:{attendances: @attendances}%> 

_form.html.erb(新出席的表格)

<div id="attended-checkbox">
  <%= f.label current_student.friendly_name %>
  <%= f.label :attended %>
  <%= f.check_box :attended %>
</div>

_index.html.erb(查看用于展示参加过该课程的学生的模板)

<div class="lectures-attended-students" id="attendance_<%= @attendance.id %>"> 
  <% @attendances.each do |attendance| %>
    <% attendance.lecture.cohort.students.each do |student| %>
      <% student.attendances.each do |a|%>
        <% if a.attended == true %>
           <p><%= student.friendly_name %></p>
        <% end %>
      <% end %>
    <% end %>
  <% end %>
</div>

考勤控制员

class AttendancesController < ApplicationController

  def new

  end

  def create
    @attendance = Attendance.new(attendance_params)
    @lecture = Lecture.find_by(id: params[:id])

    respond_to do |format|
      if @attendance.save
        format.html { redirect_to '/lectures/@lecture.id', notice: 'Attendance was successfully created.' }
        format.json { render :show, status: :created, location: @attendance }
        format.js
      else
        format.html { render :new }
        format.json { render json: @attendance.errors, status: :unprocessable_entity }
        format.js
      end
    end
  end

  private

    def attendance_params
      params.require(:attendance).permit(
        :arrived,
        :attended,
        :lecture_id,
        :student_id
      )
    end

end

讲座控制员

class LecturesController < ApplicationController
  def new
    @lecture = Lecture.new
    @cohort = Cohort.find_by(id: params[:id])
  end

  def create
    @lecture = Lecture.new(lecture_params)

    if @lecture.save
      flash[:success] = "Successfully created new lecture"
      redirect_to "/cohorts/#{@lecture.cohort_id}"
    else
      flash[:warning] = "Lecture Not Created"
      render :new
    end
  end

  def show
    @lecture = Lecture.find_by(id: params[:id])
    @attendance = Attendance.new
    @attendances = Attendance.all
  end

  def edit
    @lecture = Lecture.find_by(id: params[:id])
  end

  def update
    @lecture = Lecture.find_by(id: params[:id])

    if @lecture.update(lecture_params)
      flash[:success] = "Successfully updated lecture"
      redirect_to "/cohorts/#{@lecture.cohort_id}"
    else
      flash[:warning] = "Lecture Not Updated"
      render :edit
    end
  end

  def destroy
    @lecture = Lecture.find_by(id: params[:id])
    cohort_id = @lecture.cohort_id
    @lecture.destroy
    flash[:success] = "Your lecture has been deleted"
    redirect_to "/cohorts/#{cohort_id}"
  end

  private

    def lecture_params
      params.require(:lecture).permit(
        :name,
        :start_time,
        :end_time,
        :notes,
        :cohort_id
      )
    end
end

create.js.erb

$("#attended-checkbox").val('');

$(".lectures-attended-students").prepend('<%= j render @attendance');

选中此框并单击提交按钮后,终端将返回此错误

attendances/create.js.erb:7: syntax error, unexpected tSTRING_BEG, expecting keyword_do or '{' or '('
...$(".lectures-attended-students").prepend(\''.freeze;@output_...

单击视图页面上的刷新按钮后,终端显示此

Started GET "/lectures/1" for ::1 at 2016-08-25 11:50:33 -0500
Processing by LecturesController#show as HTML
  Parameters: {"id"=>"1"}
  Lecture Load (1.0ms)  SELECT  "lectures".* FROM "lectures" WHERE "lectures"."id" = $1 LIMIT 1  [["id", 1]]
  Student Load (0.4ms)  SELECT  "students".* FROM "students" WHERE "students"."id" = $1 LIMIT 1  [["id", 5]]
  Rendered attendances/_form.html.erb (8.0ms)
  Attendance Load (0.7ms)  SELECT "attendances".* FROM "attendances"
  Lecture Load (0.3ms)  SELECT  "lectures".* FROM "lectures" WHERE "lectures"."id" = $1 LIMIT 1  [["id", 1]]
  Cohort Load (0.3ms)  SELECT  "cohorts".* FROM "cohorts" WHERE "cohorts"."id" = $1 LIMIT 1  [["id", 5]]
  Student Load (0.3ms)  SELECT "students".* FROM "students" WHERE "students"."cohort_id" = $1  [["cohort_id", 5]]
  Attendance Load (0.3ms)  SELECT "attendances".* FROM "attendances" WHERE "attendances"."student_id" = $1  [["student_id", 5]]
  Attendance Load (0.3ms)  SELECT "attendances".* FROM "attendances" WHERE "attendances"."student_id" = $1  [["student_id", 7]]
  CACHE (0.0ms)  SELECT  "lectures".* FROM "lectures" WHERE "lectures"."id" = $1 LIMIT 1  [["id", 1]]
  CACHE (0.1ms)  SELECT  "cohorts".* FROM "cohorts" WHERE "cohorts"."id" = $1 LIMIT 1  [["id", 5]]
  CACHE (0.0ms)  SELECT "students".* FROM "students" WHERE "students"."cohort_id" = $1  [["cohort_id", 5]]
  CACHE (0.0ms)  SELECT "attendances".* FROM "attendances" WHERE "attendances"."student_id" = $1  [["student_id", 5]]
  CACHE (0.0ms)  SELECT "attendances".* FROM "attendances" WHERE "attendances"."student_id" = $1  [["student_id", 7]]
  Rendered attendances/_index.html.erb (25.2ms)
  Rendered lectures/show.html.erb within layouts/application (52.1ms)
Completed 200 OK in 311ms (Views: 290.8ms | ActiveRecord: 3.8ms)

提交前的视图(测试测试是学生的名字)

Lecture Profile
Routing
Start Time: 2016-08-31 18:00:00 UTC

End Time: 2016-08-31 21:30:00 UTC

Notes: Intro to Rails routing.

Edit Lecture

Delete Lecture


Test test Attended  
Submit
Students Attended

Test45 Test45

本地主机帖子提交和硬刷新的实际显示。 (显示三个名称,而不是一个新名称。这包括先前提交的名称,以及新名称两次)

Lecture Profile
Routing
Start Time: 2016-08-31 18:00:00 UTC

End Time: 2016-08-31 21:30:00 UTC

Notes: Intro to Rails routing.

Edit Lecture

Delete Lecture


Test test Attended  
Submit
Students Attended
Test Test

Test45 Test45

Test Test

Test45 Test45

编辑:--------------------------------------------- ------------------------

这些更改修复了硬刷新中的重复数据错误,但现在我正在处理ajax请求的nil类错误。我不明白我是怎么不通过讲座的。

讲座.rb(将演讲模式改为此)

class Lecture < ActiveRecord::Base
  belongs_to :cohort
  has_many :attendances
  has_many :attended_students, through: :attendances, source: :student
end

_attendance.html.erb(更改为此内容)

<div class="lectures-attended-students" id="attendance_<%= @attendance.id %>"> 
  <% @lecture.attended_students.each do |student| %>
    <p><%= student.friendly_name %></p>
  <% end %>
</div>

show.html.erb(Lectures Show Page现在看起来像这样)

<h1>Lecture Profile</h1>
<h3><%= @lecture.name %></h3>
<p>Start Time: <%= @lecture.start_time %></p>
<p>End Time: <%= @lecture.end_time %></p>
<p>Notes: <%= @lecture.notes %></p>
<div>
  <p><%= link_to "Edit Lecture", "/lectures/#{@lecture.id}/edit" %></p>
  <p><%= link_to "Delete Lecture", "/lectures/#{@lecture.id}", method: :delete, data:{confirm: "Are you sure you want to delete this lecture"} %></p>
</div><br>

<%= form_for @attendance, remote: true do |f| %>
  <%= render partial: "/attendances/form", locals: {f: f} %>

  <%= f.hidden_field :arrived, value: Time.now %>
  <%= f.hidden_field :student_id, value: current_student.id %>
  <%= f.hidden_field :lecture_id, value: @lecture.id %>
  <%= submit_tag "Submit" %>
<% end %>

<h2>Students Attended</h2>
  <%= render partial: @attendance, locals:{lecture: @lecture}%> 

create.js.erb(现在看起来像这样)

$("#attended-checkbox").val('');

$(".lectures-attended-students").prepend('<%= j render @attendance, locals:{lecture: @lecture} %>');

这是终端给我的东西

Completed 500 Internal Server Error in 42ms (ActiveRecord: 9.4ms)

ActionView::Template::Error (undefined method `attended_students' for nil:NilClass):
    1: <div class="lectures-attended-students" id="attendance_<%= @attendance.id %>"> 
    2:   <% @lecture.attended_students.each do |student| %>
    3:     <p><%= student.friendly_name %></p>
    4:   <% end %>
    5: </div>
  app/views/attendances/_attendance.html.erb:2:in `_app_views_attendances__attendance_html_erb__505249290825397873_70333903626520'
  app/views/attendances/create.js.erb:3:in `_app_views_attendances_create_js_erb__3555789531505990218_70333854235700'
  app/controllers/attendances_controller.rb:11:in `create'

1 个答案:

答案 0 :(得分:0)

我相信你的问题可能就在这里:

<% @attendances.each do |attendance| %>
    <% attendance.lecture.cohort.students.each do |student| %>
      <% student.attendances.each do |a|%>
        <% if a.attended == true %>
           <p><%= student.friendly_name %></p>
        <% end %>
      <% end %>
    <% end %>
 <% end %>

您正在查询所有出席情况,并在每个出席情况中进行迭代,然后再回到学生的出席情况。每次出席时,您都会打印所有参加考试的学生。在这种情况下,您有2个参加者,因此每个学生有2个参赛作品。具有这种活动记录查询的嵌套循环可能很麻烦,并且是不好的做法,因为它们会对数据库进行多次调用。他们应该避免。查看n + 1查询问题。

出勤实际上只是讲座和学生之间的联系,那么为什么不使用这种关系来构建您的查询呢?有很多方法可以做到这一点。您可以尝试使用joins编写更清晰的单行内容,它只会为您提供所需的数据。在模型上通过关系添加has_many将基本上为您构建这个。由于看起来您已经有一个讲座对象可以从您的控制器和您的讲座展示页面获得,您可以在您的讲座模型中创建一个关系,该关系将返回参加该讲座的学生。它可能是这样的:

app / models / lecture.rb

class Lecture < ActiveRecord::Base
  has_many :attendances
  has_many :attended_students, through: :attendances, class_name: "Student"
end
app / models / attendance.rb

class Attendance < ActiveRecord::Base
  belongs_to :student
  belongs_to :lecture
end

在app / views / lectures / show.html.erb

<ul>
<% @lecture.attended_students.each do |student| %>
  <li><%=student.friendly_name%></li>
<% end %>
</ul>

如果您更正了我在评论中提到的缺少erb标记的问题,那么ajax也适用于您。