Rspec Rails 在 JSON 对象中设置一个值

Rspec Rails setting a value in a JSON object

我正在为 application_controller.rb 中的方法编写测试,但在编写正确的测试时遇到了问题。该应用程序基于 Rails 3.2.17.

object.rb

def previously_purchased?
  return JSON.parse(self.features)['key']['previously_purchased'] if self.features
end

application_controller.rb

def include_bar?
  url_param = params[:keyword] || cookies[:keyword]
  @keyword_object = Object.find_by_url(url_param)
    if @keyword_object.previously_purchased? && !cookies[:prior_purchase] 
      @keyword_object = nil
      return
    end
end

factories.rb

factory: object do
  url_param 'TEST'
end

application_controller_spec.rb

#this was the most recent test I tried

context 'URL parameter keyword is present or keyword cookie is present' do
  context 'object is displayed only to previously purchased' do
    before(:each) do
      @saved_object = create :object
      @other_object = JSON.parse(@saved_object.features)
      @other_object['key']['previously_purchased'] = true
      @new_object = @other_object.to_json
      request.cookies[:prior_purchase] = 'sub'
      get :index
   end

    it 'finds object' do
      expect(assigns(:keyword_object)).to be_nil
    end
  end
end

这个returns下面的错误

Failure/Error: @other_object = JSON.parse(@saved_nanobar.features)
TypeError: no implicit conversion of nil into String

这是有道理的,因为我无法将值 previously_purchased 设置为 true。

我也试过了

context 'object is displayed only to previously purchased' do
  before(:each) do
     @saved_object = create :object
     @saved_object.features['key']['previously_purchased'] = true
     request.cookies[:prior_purchase] = 'sub'
     get :index
  end

  it 'finds object' do
    expect(assigns(:keyword_object)).to be_nil
  end
end

Failure/Error: @saved_object.features['key']['previously_purchased'].to_json = true
NoMethodError: undefined method[ ]' 对于 nil:NilClass`

我有点理解,但还不足以修复我的测试。在形成和编写我的问题时,我可能遗漏了结尾或一些其他语法,所以请耐心等待。

这一直困扰着我,我很感激任何帮助。我无法找到资源来进一步指导我。如果您需要我修改/澄清我的问题或需要更多信息,请告诉我,我会马上处理。

您的 object.features 需要包含一个 JSON。像这样设置你的对象:

@saved_object = create(
  :object, features: "{ \"key\": { \"previously_purchased\": true} }"
)

如果列保存为 JSON,您应该使用 serialize,这将解决所有问题:

class MyModel < ActiveRecord::Base
  serialize :features, JSON
end

然后您可以像处理任何其他结构一样操作它,而无需手动反序列化或重新序列化:

model = MyModel.new
model.features = { key: { previously_purchased: true } }
model.save

那么你可以这样做:

def previously_purchased?
  if (self.features)
    !!self.features.dig('key', 'previously_purchased')
  else
    false
  end
end

使用双重否定 (!!) 将该值强制为布尔值以及 Ruby 2.3.1 dig 方法来导航散列。