【问题标题】:How to pass hash method rspec to controller如何将哈希方法 rspec 传递给控制器
【发布时间】:2018-07-03 01:10:50
【问题描述】:

使用 Rails 5.1.4、Ruby 2.4.1、rspec

场景:

在文章中销毁只允许角色为“a,m”的用户 current_ma_user

然后:

检查 current_ma_user.role = "a,m" 或 current_ma_user 自己的文章 (@article.user)

所以我创建 current_ma_user 作为哈希以及用户。 然后调用role来检查什么是user[role]

问题:

  1. 如何向哈希添加新方法。

  2. 如何将该 hash.method 从 rspec controller_spec 传递给控制器​​。

失败:

  1) ArticlesController DELETE #destroy destroys the requested article
     Failure/Error: delete :destroy, params: {id: article.to_param}, session: valid_session, :current_ma_user.role => "a,m"

     NoMethodError:
       undefined method `role' for :current_ma_user:Symbol
     # ./spec/controllers/articles_controller_spec.rb:172:in `block (4 levels) in <top (required)>'
     # ./spec/controllers/articles_controller_spec.rb:171:in `block (3 levels) in <top (required)>'

这是gist

articles_controller_spec.rb:

require 'rails_helper'
RSpec.describe ArticlesController, type: :controller do

    class Hash #patch to temp pass problem 1
      def role
        "a,m"  #Hard Code, need to call user["role"] need code
      end
    end

    user = {}
    user["uid"] = "admin"
    user["provider"] = "Facebook"
    user["email"] = "1.0@kul.asia"
    user["role"] = "a,m"

    current_ma_user = user

  describe "DELETE #destroy" do

    it "destroys the requested article" do
      article = Article.create! valid_attributes
      expect {
        delete :destroy, params: {id: article.to_param}, session: valid_session
      }.to change(Article, :count).by(-1)
    end

    it "redirects to the articles list" do
      article = Article.create! valid_attributes
      delete :destroy, params: {id: article.to_param}, session: valid_session
      expect(response).to redirect_to(articles_url)
    end
  end
end

控制器:

class ArticlesController < ApplicationController   before_action :load_article, only: [:show, :destroy]

  def destroy
    if current_ma_user.role.upcase.split(',').include?("A") || current_ma_user == @article.user
    #if current_ma_user == @article.user
      @article.destroy
    end
      redirect_to :action=>'index'   end

  private

  def load_article
    @article = Article.find(params[:id])   end

end

更新了行号:

更新了调试以在 .spec 和控制器中显示 current_ma_user 的值

【问题讨论】:

  • 您是否使用工厂来创建文章?如果有请发帖
  • 不,我尝试创建用户和 current_ma_user 用于销毁,其他测试如创建,更新都可以
  • 你能在 '` 中显示# ./spec/controllers/articles_controller_spec.rb:172:in block(4 个级别)吗 - 这个字符串(以及这个字符串周围的另一个)
  • @kunashir 请查看更新的行是否足够或任何信息可能会有所帮助。谢谢
  • 您的current_ma_user 在某些地方似乎被定义为Symbol,但您尝试像对象一样使用它并调用role。尝试分析此错误的回溯。愿你用完整的跟踪和完整的控制器代码做一个要点

标签: ruby-on-rails ruby methods hash rspec


【解决方案1】:

这是您的错误的来源(在您的控制器中):

if current_ma_user.role.upcase.split(',').include?("A") || current_ma_user == @article.user

建议的解决方案

  • current_ma_user 在控制器中定义在哪里?(如果没有赋值,则需要在调用 current_ma_user 变量的角色方法之前赋值。

试试看效果如何。

  • 做这样的事情:

current_ma_user = User.find( params[:user_id])

  • 现在您似乎想将某些内容传递到 params 哈希中。请记住将您决定传递给参数的任何内容列入白名单。无论是用户 ID 或角色 ID 等,还是角色字符串。

  • 在编写测试时,将适当的值传递给 params 哈希。如果您在测试中传入user_id,则必须确保在测试中创建了用户。

delete :destroy, {:id =&gt; article.id.to_s, :user_id =&gt; @current_ma_user.id }, session: valid_session

  • 也可能在您的规范文件中,在您的测试中,将 current_ma_user 放在一个前置过滤器中,并使其成为一个实例变量,以便您的所有测试都可以访问它:

    before(:each) do @current_ma_user = user.create( <--- create the user with the appropriate attributes here --->) end

警告:未经测试

我只是在堆栈溢出编辑器中输入了它。

【讨论】:

  • 我已经添加了调试器镜像。我只是不知道如何将 current_ma_user.role 传递给控制器​​来使用它。
  • 在测试中,通过 params hash 传递角色,但您必须对其进行白化(不要忘记),但即使这样做,您仍然必须分配 current_ma_user 并且您仍然必须定义角色方法就可以了。首先尝试上述作为健全性检查,然后尝试通过参数传递角色
  • 如何将角色加入白名单或通过参数传递。我现在在规范文件中使用像这样的全局变量 $xvars["current_ma_user"] = current_ma_user 并稍后在控制器中检索它:使用 current_ma_user = $xvars["current_ma_user"] 然后调用 current_ma_user.role 并按预期工作。但想知道更好地使用参数而不是另一个全局变量。
  • 是的,但是您在哪里设置 current_ma_user 在您的控制器中?你需要这样一行:current_ma_user = User.find( params[:user_id]).
  • 并且在您的测试中,您需要将用户 ID 传递给 params 哈希。
猜你喜欢
  • 1970-01-01
  • 2019-04-10
  • 1970-01-01
  • 2016-08-13
  • 2013-11-27
  • 2012-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多