【问题标题】:When do I use the at-sign (@), the colon (:) and just the variable name in rspec / rails?何时使用 at 符号 (@)、冒号 (:) 以及 rspec / rails 中的变量名?
【发布时间】:2013-02-14 05:40:50
【问题描述】:

我已经完成了 Hartl 的 Rails 教程,但仍然存在一个困惑:我什么时候使用 @variable,什么时候应该使用 :variable,以及什么时候只是 variable 正确?

这是我从tutorial 获取的一些示例代码:

describe "micropost associations" do
    before { @user.save }
    let!(:older_micropost) do 
      FactoryGirl.create(:micropost, user: @user, created_at: 1.day.ago)
    end
    let!(:newer_micropost) do
      FactoryGirl.create(:micropost, user: @user, created_at: 1.hour.ago)
    end
    .
    .
    .
    it "should destroy associated microposts" do
      microposts = @user.microposts.dup
      @user.destroy
      microposts.should_not be_empty
      microposts.each do |micropost|
        Micropost.find_by_id(micropost.id).should be_nil
      end
    end
  end
  .
  .
  .
end

相比:

describe Micropost do
  let(:user) { FactoryGirl.create(:user) }
  before { @micropost = user.microposts.build(content: "Lorem ipsum") }

以下是这个(和其他代码)为我提出的一些更具体的问题:

  1. @user 是否需要在第一个 sn-p 中使用 @,因为它是主题还是..?
  2. 我是否总是使用: 声明新变量? (实际上我很确定情况并非如此,但我不明白其中的原因和原因。)
  3. 当我稍后引用我使用: 创建的变量时,我是否再次使用:?例如,如果我要执行print(:older_micropost)print(older_micropost),有区别吗? (参见第二个 sn-p 中的 let 语句)。
  4. 它们在before 块内的工作方式与在块外的工作方式相同吗?我发现有些代码只能在 before 块内/外工作(例如 older_micropost.destroy)。

我已经在别处寻找过这个问题的答案,但我找不到关于@: 的所有三个的讨论,什么都没有。

编辑:这是第三个 sn-p 代码,这次是我自己的。我已经评论了哪些有效,哪些无效:

describe "deleting a user following" do
  let(:userid) { @user.id }
  before { print(@user.id.inspect) # this works
           @user.destroy }         # this works
  @user.destroy                    # this doesn't
  print(@user.id.inspect)          # this doesn't
  subject { other_user }
  its(:followed_users) { should_not include(userid) }
end

(显然我没有将所有 4 行注释代码一起运行,我在 before 块内运行两行或在外部运行两行)

为什么这些语句只能在 before 块中工作?

【问题讨论】:

    标签: ruby-on-rails rspec capybara railstutorial.org


    【解决方案1】:

    他混合了新旧 RSpec 语法,这让它有些混乱。

    RSpec 的原始化身自始至终都使用实例变量。所以:

    before { @user = User.new }
    
    it "should be valid" do
      @user.should be_valid
    end
    

    RSpec 后来获得了使用let 为变量赋值的能力:

    let(:user) { User.new }
    
    it "should be valid" do
      user.should be_valid
    end
    

    let 将符号作为参数并定义一个方法,该方法在引用该方法时产生指定的结果。 let 的主要优点是它是惰性求值的。这使您可以延迟变量设置,这在嵌套示例时效果特别好。

    您可以像 Hartl 那样混合和匹配这两种范式,但这可能会让人感到困惑。最好使用一种风格或另一种风格。

    @user 在第一个 sn-p 中是否需要 @,因为它是主题 还是..?

    它需要用@或不用(使用let)定义,然后总是以相同的方式引用。 @useruser 不是一回事。

    我总是使用 : 声明新变量吗? (其实我很确定 事实并非如此,但我不明白其中的原因和原因。)

    : 是符号的前缀。您只能在 let 内使用它。

    当我稍后引用我使用 : 创建的变量时,我是否会再次使用 :? 例如,如果我要执行 print(:older_micropost) 或 print(older_micropost),有区别吗? (参见 let 语句 在第二个 sn-p)。

    在引用变量时,您使用的是方法名称,而不是符号。所以micropost,而不是:micropost

    它们在 before 块中的工作方式是否与在外面的相同?我是 发现某些代码只能在 before 块内部/外部工作 (例如 old_micropost.destroy)。

    在示例正文中工作的任何代码也应该在 before 块中工作。 的工作是将代码放在示例之外,例如:

    let(:user) { User.new(:name => "Phil") }
    
    before { puts user.name } # "Phil"
    
    it "sets the name" do
      puts user.name # "Phil"
    end
    
    puts user.name # undefined local variable or method `user' 
    

    【讨论】:

    • 这很棒,真的很有帮助,谢谢!关于before 块,您知道为什么我的第三个代码sn-p 的代码在before 块之外失败吗?一个更简单的例子是 describe "this works" do before { @user.destroy } enddescribe "this doesn't work" do @user.destroy end
    • 您的代码需要进入示例块(使用itspecify 定义)或before(或after)块。这些块之外的代码将在“主”上下文中运行;示例中的代码在单独的上下文中运行,并且可以访问设置块中定义的变量和方法。
    【解决方案2】:

    这是一个实例变量,意味着每当您需要将信息从控制器传递到视图或反之亦然时,我们通常使用这个@variable

    现在: 用于符号,意味着它们大部分时间与字符串相似,但在内存方面它们比简单字符串便宜,因为它一次比较整个字符串。

    有关这方面的更多信息,请阅读文章http://www.robertsosinski.com/2009/01/11/the-difference-between-ruby-symbols-and-strings/

    【讨论】:

    • 好的,谢谢,我阅读了整篇文章,但我仍然不清楚 @ 和我的问题 1-4。我将用更多代码更新我的问题,看看是否更清楚
    • @Lindsayts 我将同时更新我的​​答案..为该主题提供更多研发成果:)
    猜你喜欢
    • 2011-04-02
    • 2021-11-11
    • 1970-01-01
    • 2010-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-28
    • 2016-10-24
    相关资源
    最近更新 更多