首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rails 4访问模型属性

Rails 4访问模型属性
EN

Stack Overflow用户
提问于 2013-10-14 22:07:14
回答 2查看 894关注 0票数 0

我正在学习rails (我主要是一个java开发人员),从我的问题中可以明显看出,并且在从rspec测试中访问我的模型上的方法时遇到了困难。我基本上是在跟踪本教程,但将它应用到我自己的项目中。我试图将graduation_year定义为一种基于学生成绩和每年当前时间的方法。当我实例化该对象并在rails控制台中调用该方法时,它如我所期望的那样工作,但是当我试图在测试中执行它时,我得到了如下结果:

代码语言:javascript
复制
undefined method `graduation_year'

student.rb

代码语言:javascript
复制
class Student < ActiveRecord::Base
  validates :school_id, presence: true, uniqueness: true
  validates :first_name, presence: true, length: { maximum: 30 }
  validates :last_name, presence: true, length: { maximum: 40 }
  validates :gender, presence: true, inclusion: { :in => %w(m f M F) }
  validates :grade, presence: true, numericality: { greater_than_or_equal_to: 1 , less_than_or_equal_to: 12 }

  def graduation_year
    year = Date.today.year + ( 12 - grade )
  end
end

student_spec.rb

代码语言:javascript
复制
require 'spec_helper'

describe Student do
  before { @student = Student.new(
                        school_id: 3, 
                        first_name: "Michael", 
                        last_name: "Green", 
                        gender: "M", 
                        grade: 6)}

  subject { @student }

  it { should respond_to(:school_id) }
  it { should respond_to(:first_name) }
  it { should respond_to(:last_name) }
  it { should respond_to(:gender) }
  it { should respond_to(:grade) }
  it { should respond_to(:graduation_year) }

  it { should be_valid }

  describe "when school_id is not present" do
    before { @student.school_id = " " }
    it { should_not be_valid }
  end
  .
  .
  .  
  describe "when grade is 7 graduation_year should be calculated correctly" do
    before { @student.grade = 7 }
    expect(@student.graduation_year).to eq(Date.today.year+5)
  end
end

错误消息

代码语言:javascript
复制
~/dev/rails_apps/spec/models/student_spec.rb:96:in `block (2 levels) in <top (required)>': undefined method `graduation_year' for nil:NilClass (NoMethodError)
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/example_group.rb:242:in `module_eval'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/example_group.rb:242:in `subclass'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/example_group.rb:228:in `describe'
from ~/dev/rails_apps/spec/models/student_spec.rb:94:in `block in <top (required)>'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/example_group.rb:242:in `module_eval'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/example_group.rb:242:in `subclass'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/example_group.rb:228:in `describe'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/dsl.rb:18:in `describe'
from ~/dev/rails_apps/spec/models/student_spec.rb:3:in `<top (required)>'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/configuration.rb:819:in `load'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/configuration.rb:819:in `block in load_spec_files'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/configuration.rb:819:in `each'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/configuration.rb:819:in `load_spec_files'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/command_line.rb:22:in `run'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/runner.rb:80:in `run'
from ~/dev/.rvm/gems/ruby-2.0.0-p247/gems/rspec-core-2.13.1/lib/rspec/core/runner.rb:17:in `block in autorun'

而且,我不认为这是问题,但我最初将graduation_year作为一个属性放在了Student表中,但是删除了它,并且这个测试应该验证它的计算是否正确。

我还在测试中尝试过puts first_name,并且在first_name上得到了相同的未定义方法错误。我想我只是错过了一些关于ruby/rails工作方式的东西。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-10-15 01:42:57

expect语句没有包装在'it‘子句中。试着写作

代码语言:javascript
复制
describe "when grade is 7" do
  before { @student.grade = 7 }
  it 'calculates the graduation year correctly' do
    expect(@student.graduation_year).to eq(Date.today.year+5)
  end
end

顺便说一句,用这种方式使用“学生”并不是惯用的。你最好用一个叫let的语句来定义学生。因此,您可以使用Student.new代替最初的like块,编写如下所示的内容:

代码语言:javascript
复制
let(:student) { Student.new(
                    school_id: 3, 
                    first_name: "Michael", 
                    last_name: "Green", 
                    gender: "M", 
                    grade: 6)}

你随后提到的“学生”将被替换为“学生”。这确保了描述块内(或外)没有泄漏。

let语句将回溯对象,并且只有在规范中引用了学生时才会实例化该对象。

票数 2
EN

Stack Overflow用户

发布于 2013-10-14 23:24:03

不能在describe块中直接设置期望,就像行中的情况一样:

代码语言:javascript
复制
expect(@student.graduation_year).to eq(Date.today.year+5)

您没有说明所得到的具体错误(即,有未定义方法的对象),但此时@student将是nil,因为所有未定义的实例变量都是nil,因此它不会有graduation_year方法。但是,如果@student.graduation_year是一个有效的表达式,那么您就会在expect调用上得到一个未定义的方法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19370071

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档