Ruby on rails 使Rails类属性不可访问-Rails教程第9章,练习1

Ruby on rails 使Rails类属性不可访问-Rails教程第9章,练习1,ruby-on-rails,railstutorial.org,Ruby On Rails,Railstutorial.org,我正在学习Michael Hartl的Rails教程。我来了。它要求您添加一个测试来验证User类的admin属性是否不可访问。以下是注释掉不相关部分的用户类: class User < ActiveRecord::Base attr_accessible :name, :email, :password, :password_confirmation attr_protected :admin # before_save methods # validations

我正在学习Michael Hartl的Rails教程。我来了。它要求您添加一个测试来验证
User
类的
admin
属性是否不可访问。以下是注释掉不相关部分的用户类:

class User < ActiveRecord::Base
  attr_accessible :name, :email, :password, :password_confirmation
  attr_protected :admin

  # before_save methods
  # validations
  # private methods
end

测试失败了。它说,尽管
admin
属性受到保护,但没有引发任何错误。如何才能通过考试?

这只适用于批量作业,如从表单提交设置字段。试着这样做:

@user.update_attrtibutes(:admin => true)
@user.admin.should be_false

正如Rails文档所声称的,attr_受保护

此宏中命名的属性不受批量分配的影响,例如new(属性)、update_属性(属性)或Attributes=(属性)


所以您可以手动更改字段。”attr_protected“仅与质量分配有关

来自Ruby文档:

批量分配安全性提供了一个接口,用于保护属性不受最终用户分配的影响

请尝试此代码

describe "accesible attributes" do
  it "should not allow access to admin" do
    expect do
      User.new(admin: true) 
    end.should raise_error(ActiveModel::MassAssignmentSecurity::Error)
  end
end

根据提示,我首先在app/models/user.rb中将
:admin
添加到
attr\u accessible
,以红色开头。 然后我添加了测试:

describe "admin attribute" do
    it  "should not be accessible" do
        expect do
            @user.update_attributes(:admin => true)
        end.to raise_error(ActiveModel::MassAssignmentSecurity::Error)
    end
end
符合规格,并得到一个红色。 从user.rb中删除
:admin
,我得到一个绿色。到目前为止还不错。

让我困惑的是我为什么要使用sintax:

@user.update_attributes(:admin => true)

而不是
@user.admin=true
(我检查了,在本例中它不起作用)。

@agaved。这个答案可能来得晚,你可能已经有了答案,但我想回答你的问题,它可能会帮助其他人

了解
update\u attributes
与直接分配有何不同的最佳方法
@user.admin=true
就是尝试在控制台中执行此操作。如果您正在学习Hartl的教程,请尝试以下操作:

@user = User.first
@user.admin?
=> true
@user.admin = false
=> false
直接分配管理将用户的属性admin的值从
true
更改为
false
,而不会引起批量分配错误。这是因为在调用
update\u attributes
或使用不可访问的属性创建新用户
user.new
时会引发批量分配错误。换句话说,当用户试图更新
(attribute\u update)
或创建
user.new(admin:true)
一个属性不可访问的新用户时,Rails会引发大量分配错误。在上述情况下,直接分配不使用用户控制器的创建或更新方法

它们是非常相似的代码片段,因为在上述情况下,您可以使用
@user.save!(validate:false)
直接在IRB中,但正如我上面所说的,这不会使用用户控制器的创建或更新方法,因此不会抛出错误


我希望这对我有帮助。

[剧透警报:如果你想自己解决Hartl书中的练习,我很确定我会给出答案。尽管被接受的答案是有趣的信息,但我不相信这是Hartl的想法,因为这需要书中没有涵盖的知识,也没有具体说明通过网络操作或使用他提供的测试更新。]

如果我没弄错的话,我想你可能会认为这个练习比实际困难得多。首先,你误解了这个暗示:

提示:您的第一步应该是将admin添加到user_params中允许的参数列表中

它没有说要在类中更改其attr声明。它说要修改帮助函数user_params。因此我将其添加到users_controller.rb中的列表中:

def user_params
  params.require(:user).permit(:name, :email, :password,
                             :password_confirmation, :admin)
end
接下来,我将清单9.48中的代码复制到spec/requests/user\u pages\u spec.rb中指定的位置:

require 'spec_helper'

describe "User pages" do
  .
  .
  .
  describe "edit" do
    .
    .
    .
    describe "forbidden attributes" do
      let(:params) do
        { user: { admin: true, password: user.password,
                  password_confirmation: user.password } }
      end
      before do
        sign_in user, no_capybara: true
        patch user_path(user), params
      end
      specify { expect(user.reload).not_to be_admin }
    end
  end
end
然后测试失败,表明可以传入admin参数,从而将普通用户更改为admin,这不是您希望允许的:

$ rspec spec
.....................[edited out dots].................................F

Failures:

  1) User pages edit forbidden attributes 
     Failure/Error: specify { expect(user.reload).not_to be_admin }
       expected admin? to return false, got true
     # ./spec/requests/user_pages_spec.rb:180:in `block (4 levels) in <top (required)>'

Finished in 4.15 seconds
91 examples, 1 failure

Failed examples:

rspec ./spec/requests/user_pages_spec.rb:180 # User pages edit forbidden attributes 
现在,尝试使用新的admin值修补用户失败……测试成功,验证“admin属性不能通过web编辑”

$ rspec spec
.....................[edited out dots].................................F

Failures:

  1) User pages edit forbidden attributes 
     Failure/Error: specify { expect(user.reload).not_to be_admin }
       expected admin? to return false, got true
     # ./spec/requests/user_pages_spec.rb:180:in `block (4 levels) in <top (required)>'

Finished in 4.15 seconds
91 examples, 1 failure

Failed examples:

rspec ./spec/requests/user_pages_spec.rb:180 # User pages edit forbidden attributes 
def user_params
  params.require(:user).permit(:name, :email, :password,
                             :password_confirmation)
end
    $ rspec spec
...........................................................................................

Finished in 4.2 seconds
91 examples, 0 failures