Rails Add Behavior to Active Record Associations 要如何在 view 中調用?

idarfan · 2012年09月17日 · 最后由 idarfan 回复于 2012年09月17日 · 2335 次阅读

我碰到一個問題,參考這本書 RailsRecipes 3 關於 Add Behavior to Active Record Associations 如何新增行為到 AR 去。

底下是實行的步驟:

用 scaffold 建立 studnet 模型包括 :name :graduating_year assoc_proxies$ rails g scaffold student name:string graduating_year:integer 用 scaffold 建立 grade 模型包括 :score :class_name assoc_proxies$ rails g scaffold grade score:integer class_name:string

assoc_proxies$ rails c
Loading development environment (Rails 3.0.10)

ruby-1.9.2-p290 :002 > me = Student.create(:name => "idarfan", :graduating_year => 2120)
 => #<Student id: 2, name: "idarfan", graduating_year: 2120, created_at: "2012-09-07 10:52:42", updated_at: "2012-09-07 10:52:42">
ruby-1.9.2-p290 :003 > me.grades.create(:score => 3, :class_name => "Algebra")
 => #<Grade id: 2, student_id: 2, score: 3, class_name: "Algebra", created_at: "2012-09-07 10:53:06", updated_at: "2012-09-07 10:53:06">
ruby-1.9.2-p290 :004 > s_all = Student.all
 => [#<Student id: 1, name: "Chad", graduating_year: 2020, created_at: "2012-09-06 12:23:13", updated_at: "2012-09-06 12:23:13">, #<Student id: 2, name: "idarfan", graduating_year: 2120, created_at: "2012-09-07 10:52:42", updated_at: "2012-09-07 10:52:42">]
ruby-1.9.2-p290 :005 > s_all.each {|s| s.grades}
 => [#<Student id: 1, name: "Chad", graduating_year: 2020, created_at: "2012-09-06 12:23:13", updated_at: "2012-09-06 12:23:13">, #<Student id: 2, name: "idarfan", graduating_year: 2120, created_at: "2012-09-07 10:52:42", updated_at: "2012-09-07 10:52:42">]

ruby-1.9.2-p290 :029 > Student.find(2).grades.below_average
 => []
#改成這樣
ruby-1.9.2-p290 :033 > s_all.each {|s| s.grades.below_average}
 => [#<Student id: 1, name: "Chad", graduating_year: 2020, created_at: "2012-09-06 12:23:13", updated_at: "2012-09-06 12:23:13">, #<Student id: 2, name: "idarfan", graduating_year: 2120, created_at: "2012-09-07 10:52:42", updated_at: "2012-09-07 
10:52:42">]
#看來似乎沒作用
 => [#<Student id: 1, name: "Chad", graduating_year: 2020, created_at: "2012-09-06 12:23:13", updated_at: "2012-09-06 12:23:13">, #<Student id: 2, name: "idarfan", graduating_year: 2120, created_at: "2012-09-07 10:52:42", updated_at: "2012-09-07 10:52:42">] 

Student 資料模型中是這樣寫的

class Student < ActiveRecord::Base  
  has_many :grades do
    def below_average
      where('score < ?', 2)
    end
  end
end

grades 資料模型中有個 score 的字段,我要怎麼在 view 中調出這個方法? 我只想列出成績小於 2 的。目前僅有兩筆資料。第一筆是 1 第 2 筆是 3.

感謝賜教。

Student.grades.below_average

但是我建议 below_average 写成 Grade 的 scope

class Grade < ActiveRecord::Base
  scope :below_average, where('score < ?', 2)
end

依然是这么调用 Student.grades.below_average

之后想要增加参数可以这样

class Grade < ActiveRecord::Base
  scope :below_average, lambda.new {|score| where('score < ?', score)}
end

调用变成Student.grades.below_average(2)

hi Rei 感謝您的回覆:

是這樣滴會改用 Behavior 是因為要彈性,有時會做出不同考題難度,要列出學生的平均來評估難度..萬一全班都考不到最及格分 60 分的話,我會再依老師的建議調整設定學生在這課裏都及格分數的字段。

所以寫成 Behavior 可能會較方便做這樣的處理。

另外跟您請教一下: scope :below_average, lambda.new {|score| where('score < ?', score)} 這個 lambda.new 的用途是?

#剛才我試了一下: 這樣在 rails c 中調不出東西哩? 奇怪
ruby-1.9.2-p290 :014 > Student.grades.below_average
NoMethodError: undefined method `grades' for #<Class:0x00000003ddd3a0>

另外我在 student controll 裏寫了

class StudentsController < ApplicationController
  # GET /students
  # GET /students.xml
  def index
    @students = Student.all
    @grades = Grade.all
    @below = Student.grades.below_average

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @students }
    end
  end

在 view 裏這寫了

<% @below.each do |below| %>
  <tr>
    <td><%= below.name %></td>
    <td><%= below.graduating_year %></td>
    <td><%= link_to 'Show', student %></td>
    <td><%= link_to 'Edit', edit_student_path(student) %></td>
    <td><%= link_to 'Destroy', student, :confirm => 'Are you sure?', :method => :delete %></td>
  </tr>
<% end %>
</table>
<br />

然後出現的底下的錯誤訊息。

 NoMethodError in StudentsController#index

undefined method `grades' for #<Class:0x007fdbc45a3208>

Rails.root: /home/kojendirect/sample_projects/assoc_proxies
Application Trace | Framework Trace | Full Trace

app/controllers/students_controller.rb:7:in `index'
需要 登录 后方可回复, 如果你还没有账号请 注册新账号