用于测试的Rspec测试在父资源内创建嵌套资源的控制器

时间:2015-11-04 10:19:54

标签: ruby-on-rails ruby rspec

My Rails API应用程序有两个资源:文章(父级)和注释(子级)。我想测试一下,当创建父项时,还会创建任何指定的子项。所以我想在父母的创建控制器测试中测试这个创建,除了孩子的创建控制器测试本身。

我已经让JSON请求正常工作但我不确定如何构建我的RSpec测试

{
  "article": {
    "original_language": "ja",
    "title": "日本のコンビニが中東で初めて店を開く",
    "body": "コンビニの会社「セブン-イレブン・ジャパン」は13日、中東のUAE=アラブ首長国連邦のドバイに新しい店を開きました。日本のコンビニが中東に店を開くのは初めてです。\nUAEには24時間開いている店がほとんどありませんでした。このため、UAEの中のアブダビ首長国の王族(=王と王の親類)が新しいやり方の店を開いてほしいと頼んでいました。\n新しい店では、特に弁当やおにぎりなどを売りたいと考えています。UAEの人が好きなインドのスパイスを入れたり、大きなソーセージをのせたりしたおにぎりも作りました。新しい店の社長は「UAEにはいろいろな国の人たちが来ています。お客様がみんな喜ぶような店にしたいです」と話していました。\nセブン-イレブン・ジャパンは、これから3年でUAEに100の店を開く予定です。",
    "source_name": "NHK Easy News",
    "source_url": "http://www3.nhk.or.jp/news/easy/k10010269131000/k10010269131000.html",
    "privacy_status": 1,
    "scheduled_date": null,
    "level": 3,
    "annotations": [
      {
        "destination_language": "en",
        "authority_level": 1,
        "source_text": "コンビニ",
        "location_start": 1,
        "location_end": 5,
        "category": 0,
        "definition": "Convenience Store",
        "reading": null,
        "translation": null,
        "usage_note": "Convenience stores are everywhere in Japan. Most open 24/7. The big chains are 7/11, Lawson, Family Mart, Sunkus, and Circle K.",
        "specific_note": null,
        "paragraph_id": 1
      },
      {
        "destination_language": "en",
        "authority_level": 1,
        "source_text": "コンビニ",
        "location_start": 1,
        "location_end": 5,
        "category": 0,
        "definition": "Convenience Store",
        "reading": null,
        "translation": null,
        "usage_note": "Convenience stores are everywhere in Japan. Most open 24/7. The big chains are 7/11, Lawson, Family Mart, Sunkus, and Circle K.",
        "specific_note": null      }
    ]
  }
}

到目前为止,这是我的尝试。我意识到我所做的并不是在JSON之类的文章下嵌套注释。我怎么能这样做?

@article_attributes = create_prospective(scope: :article)
@annotation_attributes_valid = create_prospective(scope: :annotation)
@annotation_attributes_invalid = create_prospective(scope: :annotation, trait: :invalid)
post :create, {user: @user.id, article: @article_attributes, annotations: @annotation_attributes_valid }, format: :json

注意:create_prospective是FactoryGirl的辅助方法

控制器

def create
    @article = current_resource_owner.articles.build(article_params)

    if @article.save
      annotation_result = create_annotation(@article, params[:article][:annotations])

      render json: {article: @article, total_number_annotations: annotation_result[:total_count], number_annotations_succeeded: annotation_result[:success_count], number_annotations_failed: annotation_result[:failure_count], successful_annotations: annotation_result[:success_list], failed_annotations: annotation_result[:failure_list]}, status: annotation_result[:api_status]
      # end
    else
      render json: { errors: @article.errors }, status: 422
    end

注意:create_annotation是保存注释的关注点,可以在文章控制器和注释控制器中重复使用

1 个答案:

答案 0 :(得分:0)

您的规范正在创建实际的ArticleAnnotation个对象,而不是属性哈希,正如您所说,您还没有嵌套Annotation内的Article。您应该做的第一件事是创建一个参数哈希,您可以验证该参数哈希与您正在工作的JSON请求具有相同的结构。我希望看起来像这样:

article_data = attributes_for(:article, annotations: [attributes_for(:annotation)])

然后,您应该能够将属性数据正确地发布到控制器:

post :create, article: article_data, format: :json

一旦规范工作,您可以使用Article模型上的accepts_nested_attributes_for来简化控制器。 Rails为这种情况提供了它,它可以帮助您一次验证所有对象,以防您不希望使用无效的Article创建Annotation,并且它可以很好地与方式Rails做nested forms