Ruby on rails, Validation failed: Countries can't be blank - ruby-on-rails

it "renders index page" do
projects_user = FactoryGirl.create(:projects_user)
get :index, id: projects_user.id
expect(response).to render_template :index
end
this is my controller test, when i run it it says: Validation failed: Countries can't be blank
I am new to stackoverflow and ruby soo any help i get is great
FilesController:
class FilesController < ApplicationController
before_filter :authenticate_user!
def index
#pu = ProjectsUser.find(params[:id])
debugger
#files = UserFile.includes(:user).where(project_id: #pu.id)
end
def new
#file = UserFile.new
end
def create
#file = UserFile.new(file_params)
if #file.save
flash[:success] = "File successfully uploaded!"
redirect_to files_path
else
#files = UserFile.includes(:user).where(user_id: current_user.id)
render :index
end
end
def destroy
#file = UserFile.find(params[:file_id])
if #file.destroy
flash[:success] = "File successfully deleted!"
redirect_to files_path
else
flash[:error] = "File could not be deleted."
redirect_to files_path
end
end
protected
def file_params
params.require(:user_file).permit(:file, :user_id, :created_at, :updated_at, :project_id)
end
end
Country controller:
class CountriesController < ApplicationController
def states
#states = State.where(country_id: params[:id]).all
return render :json => {success: true, status: 200, data: #states}
end
end
Country model:
class Country < ActiveRecord::Base
validates :name, presence: true
has_many :states
has_many :users
has_and_belongs_to_many :projects
validates :name, presence: true
end
Factory for country:
require 'ffaker'
FactoryGirl.define do
factory :country do
name {FFaker::AddressUS.country}
end
end
output of error:
ActiveRecord::RecordInvalid:
Validation failed: Countries can't be blank
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib /factory_girl/configuration.rb:18:in `block in initialize'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/evaluation.rb:15:in `[]'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/evaluation.rb:15:in `create'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/strategy/create.rb:12:in `block in result'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/strategy/create.rb:9:in `tap'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/strategy/create.rb:9:in `result'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/factory.rb:42:in `run'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/factory_runner.rb:29:in `block in run'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/factory_runner.rb:28:in `run'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/strategy/create.rb:5:in `association'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/evaluator.rb:33:in `association'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/attribute/association.rb:19:in `block in to_proc'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/evaluator.rb:77:in `instance_exec'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/evaluator.rb:77:in `block in define_attribute'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:56:in `get'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:16:in `block (2 levels) in object'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:15:in `each'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:15:in `block in object'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:14:in `tap'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/attribute_assigner.rb:14:in `object'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/evaluation.rb:12:in `object'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/strategy/create.rb:9:in `result'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/factory.rb:42:in `run'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/factory_runner.rb:29:in `block in run'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/factory_runner.rb:28:in `run'
# /home/nemanja/.rvm/gems/ruby-2.1.2/gems/factory_girl-4.8.0/lib/factory_girl/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
# ./spec/controllers/files_controllers_spec.rb:31:in `block (3 levels) in <top (required)>'
UPDATE:
Factory for project, project has_and_belongs_to_many countries
require 'ffaker'
FactoryGirl.define do
factory :project do
sponsor_name "John Pare"
title "Anea"
start_date Date.new(2016, 5, 7)
end_date Date.new(2017, 3, 6)
description {FFaker::Lorem.paragraph}
number_of_sites_planned "5"
estimated_enrollment "24"
feasibility_questionnaire File.open("#{Rails.root}/spec/internal_spec_files/app.pdf")
association :disease_type
association :disease_condition
association :user
association :project_category
association :project_subcategory
after(:create) do |m|
m.countries << build(:country)
end
end
end

The problem is within the
projects_user = FactoryGirl.create(:projects_user)
the creation code (where you defined this factory) does not set a country and this is why you get an error.

Related

Rails Integration testing with rspec and fixture_file_upload

I recently ran into an issue with an integration test using rspec.
RSpec.describe "Images", type: :request do
before(:each) do
#user = User.create(username: "sam", password: "password")
#tag = #user.tags.create(name: "outdoors")
post login_path, params: { username: "sam", password: "password" }
expect(session[:user_id]).to eql #user.id
#file = fixture_file_upload("/dingo.jpeg", "image/jpeg")
end
it "can show images" do
#image = #user.images.create(caption: "hello", image_file: #image)
get user_image_path(#user, #image)
expect(response).to be_success
end
end
The before each creates a valid user, tag and logs the user in. Then it loads an image file.
The test it's self creates a new image for the #user and assigns it a value for caption and the loaded file for its :image_file.
The Image model uses has_one_attached :image_file to associate an uploaded image with an image record
class Image < ApplicationRecord
belongs_to :user
has_and_belongs_to_many :tags
has_one_attached :image_file
end
the controller and action as follows:
class ImageController < ApplicationController
before_action :unauthorized_redirect
def show
#user = current_user
#image = Image.find(params[:id])
#tags = #user.tags.all
authorize #image, :show?
end
private
def image_params
params.require(:image).permit(:caption, :image_file, tag_ids: [])
end
end
When I run the test I get an error:
Failures:
1) Images can show images
Failure/Error: <%= image_tag #image.image_file, class: "img-fluid show-image" %>
ActionView::Template::Error:
Can't resolve image into URL: undefined method `persisted?' for nil:NilClass
# ./app/views/image/show.html.erb:7:in `_app_views_image_show_html_erb__3727703739275822003_20580'
# <internal:kernel>:90:in `tap'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/actiontext-6.1.4.1/lib/action_text/rendering.rb:20:in `with_renderer'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/actiontext-6.1.4.1/lib/action_text/engine.rb:59:in `block (4 levels) in <class:Engine>'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/rack-2.2.3/lib/rack/tempfile_reaper.rb:15:in `call'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/rack-2.2.3/lib/rack/etag.rb:27:in `call'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/rack-2.2.3/lib/rack/conditional_get.rb:27:in `call'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/rack-2.2.3/lib/rack/head.rb:12:in `call'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/rack-2.2.3/lib/rack/session/abstract/id.rb:266:in `context'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/rack-2.2.3/lib/rack/session/abstract/id.rb:260:in `call'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/railties-6.1.4.1/lib/rails/rack/logger.rb:37:in `call_app'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/railties-6.1.4.1/lib/rails/rack/logger.rb:26:in `block in call'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/railties-6.1.4.1/lib/rails/rack/logger.rb:26:in `call'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/rack-2.2.3/lib/rack/method_override.rb:24:in `call'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/rack-2.2.3/lib/rack/runtime.rb:22:in `call'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/rack-2.2.3/lib/rack/sendfile.rb:110:in `call'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/railties-6.1.4.1/lib/rails/engine.rb:539:in `call'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/rack-test-1.1.0/lib/rack/mock_session.rb:29:in `request'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/rack-test-1.1.0/lib/rack/test.rb:266:in `process_request'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/rack-test-1.1.0/lib/rack/test.rb:119:in `request'
# /home/sam/.rvm/gems/ruby-3.0.0/gems/rails-controller-testing-1.0.5/lib/rails/controller/testing/integration.rb:16:in `block (2 levels) in <module:Integration>'
# ./spec/requests/images_spec.rb:38:in `block (2 levels) in <main>'
# ------------------
# --- Caused by: ---
# NoMethodError:
# undefined method `persisted?' for nil:NilClass
# ./app/views/image/show.html.erb:7:in `_app_views_image_show_html_erb__3727703739275822003_20580'
Finished in 0.79372 seconds (files took 0.46552 seconds to load)
30 examples, 1 failure
Failed examples:
rspec ./spec/requests/images_spec.rb:36 # Images can show images
I have debugged this issue with breakpoints everywhere and I just don't understand why it's not working in test when it works in production. I hope I've provided enough information this bug has been driving me crazy for the past two days.
Thank you!
Versions:
rails: 6.1.4.1
rspec: 5.0.2
Changed one line and fixed it
it "can show images" do
#image = #user.images.create(caption: "hello", image_file: #image)
get user_image_path(#user, #image)
*expect(response).to be_success ----REMOVE*
expect(response.successful?).to eql true
end

WARN: ArgumentError: missing keyword: user_id in job perform method

I am trying to pass devise current_user into rails job with Sidekiq Shopify worker, but the job initiates, I get WARN: ArgumentError: missing keyword: user_id. Here is what I have done below which could be that I am doing it wrongly.
OrderWebhookController
# frozen_string_literal: true
class OrderWebhooksController < ApplicationController
include ShopifyApp::WebhookVerification
def orders_paid
params.permit!
OrdersPaidJob.perform(shop_domain: shop_domain, webhook: webhook_params.to_h, user_id: current_user.id)
head :no_content
end
private
def webhook_params
params.except(:controller, :action, :type)
end
end
OrdersPaidJob
# frozen_string_literal: true
class OrdersPaidJob < ApplicationJob
def perform(shop_domain:, webhook:, user_id:)
shop = Shop.find_by(shopify_domain: shop_domain)
webhook.to_json
shop.with_shopify_session do
customer = webhook['customer']
payload = {
user_id: user_id,
email: customer['email'],
amount_spent: customer['total_spent'],
first_name: customer['first_name'],
last_name: customer['last_name'],
point_balance: (customer['total_spent']),
recorded_on: Time.now
}
customer_records = [].tap do |array|
array << payload
end
customer_exists(customer) ? CustomerDetail.upsert(customer_records) : CustomerDetail.insert_all(customer_records)
end
end
private
def earning_rules
EarningRule.order_rule || 0
end
def customer_exists(customer)
CustomerDetail.find_by_email(customer['email'])
end
end
Log Error
error_message\":\"missing keyword: user_id\",\"error_class\":\"ArgumentError\",\"failed_at\":1574158701.8283021,\"retry_count\":4,\"retried_at\":1574159903.266159}"}
2019-11-19T10:39:09.892Z pid=6341 tid=oxrqw3mjx WARN: ArgumentError: missing keyword: user_id
2019-11-19T10:39:09.893Z pid=6341 tid=oxrqw3mjx WARN: /Users/tiwa/RubymineProjects/ShopifyLoyaltyApp/app/jobs/orders_paid_job.rb:5:in `perform'
/Users/tiwa/.gem/ruby/2.6.2/gems/activejob-6.0.1/lib/active_job/execution.rb:39:in `block in perform_now'
/Users/tiwa/.gem/ruby/2.6.2/gems/activesupport-6.0.1/lib/active_support/callbacks.rb:112:in `block in run_callbacks'
/Users/tiwa/.gem/ruby/2.6.2/gems/i18n-1.7.0/lib/i18n.rb:297:in `with_locale'
/Users/tiwa/.gem/ruby/2.6.2/gems/activejob-6.0.1/lib/active_job/translation.rb:9:in `block (2 levels) in <module:Translation>'
/Users/tiwa/.gem/ruby/2.6.2/gems/activesupport-6.0.1/lib/active_support/callbacks.rb:121:in `instance_exec'
/Users/tiwa/.gem/ruby/2.6.2/gems/activesupport-6.0.1/lib/active_support/callbacks.rb:121:in `block in run_callbacks'
/Users/tiwa/.gem/ruby/2.6.2/gems/activesupport-6.0.1/lib/active_support/core_ext/time/zones.rb:66:in `use_zone'
/Users/tiwa/.gem/ruby/2.6.2/gems/activejob-6.0.1/lib/active_job/timezones.rb:9:in `block (2 levels) in <module:Timezones>'
/Users/tiwa/.gem/ruby/2.6.2/gems/activesupport-6.0.1/lib/active_support/callbacks.rb:121:in `instance_exec'
/Users/tiwa/.gem/ruby/2.6.2/gems/activesupport-6.0.1/lib/active_support/callbacks.rb:121:in `block in run_callbacks'
Any help will be appreciated.
In your case you can access this passed arguments as follow:
def perform(shop_domain:, webhook:, user_id:)
change to:
def perform(params)
and then params["user_id"] etc.
Sidekiq does not support named parameters https://github.com/mperham/sidekiq/wiki/Best-Practices#1-make-your-job-parameters-small-and-simple
However, there are some good workarounds on this like this one: https://github.com/mperham/sidekiq/issues/2372#issuecomment-469660538
This is copypasta from above source:
# jobs/job.rb
class Job
include Sidekiq::Worker
# ... more default options here
def perform(params={})
params = params.to_h.transform_keys(&:to_sym)
execute params
end
end
# jobs/greet_job.rb
class Greet < Job
def execute(name: "there")
puts "Hi #{name}!"
end
end
So now all jobs simply define execute instead of defining perform.
And it even works nicely in specs:
# spec/greet_job_spec.rb
expect(Greet).to have_enqueued_sidekiq_job(name: "Lloyd Christmas")

Solidus: Code that is executed in after_save callback returns error in rspec

I'm using latest version of Solidus e-commerce (fork of Spree) and I'm having this issue. To describe it quickly:
In Admin I create Spree::Membership record
after_save callback in Spree::Membership creates Product and 2 variants
This code works when I run the server, but when I'm trying to use Rspec it gives me this error:
Failure/Error: reload.product.setup_membership_variants
NoMethodError:
undefined method `setup_membership_variants' for nil:NilClass
# ./app/models/spree/membership.rb:26:in `block in setup_product'
# ./app/models/spree/membership.rb:18:in `setup_product'
# /box/gems/factory_girl-4.8.0/lib/factory_girl/configuration.rb:18:in `block in initialize'
# /box/gems/factory_girl-4.8.0/lib/factory_girl/evaluation.rb:15:in `create'
# /box/gems/factory_girl-4.8.0/lib/factory_girl/strategy/create.rb:12:in `block in result'
# /box/gems/factory_girl-4.8.0/lib/factory_girl/strategy/create.rb:9:in `tap'
# /box/gems/factory_girl-4.8.0/lib/factory_girl/strategy/create.rb:9:in `result'
# /box/gems/factory_girl-4.8.0/lib/factory_girl/factory.rb:42:in `run'
# /box/gems/factory_girl-4.8.0/lib/factory_girl/factory_runner.rb:29:in `block in run'
# /box/gems/factory_girl-4.8.0/lib/factory_girl/factory_runner.rb:28:in `run'
# /box/gems/factory_girl-4.8.0/lib/factory_girl/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
# ./spec/controllers/spree/premium_controller_spec.rb:4:in `block (2 levels) in <top (required)>'
# ./spec/controllers/spree/premium_controller_spec.rb:33:in `block (6 levels) in <top (required)>'
# ./spec/controllers/spree/premium_controller_spec.rb:53:in `block (8 levels) in <top (required)>'
# ./spec/controllers/spree/premium_controller_spec.rb:53:in `block (7 levels) in <top (required)>'
Here is code I'm using:
membership.rb
class Spree::Membership < Spree::Base
has_many :active_memberships, class_name: 'Spree::ActiveMembership', dependent: :destroy
has_one :membership_product, class_name: "Spree::MembershipProduct", dependent: :destroy
has_one :product, through: :membership_product, source: :product
validates :name, presence: true
validates :monthly_quota, presence: true
validates :price, presence: true
after_save :setup_product
private
def setup_product
if product.nil?
ActiveRecord::Base.transaction do
create_membership_product(
product: Spree::Product.create(
name: name,
price: price,
shipping_category: Spree::ShippingCategory.find_by(name: "Default")
)
)
reload.product.setup_membership_variants
end
else
product.update(name: name, price: price)
end
end
end
product_decorator.rb
Spree::Product.class_eval do
def setup_membership_variants
ot = Spree::OptionType.find_or_create_by(name: "Membership")
option_types << ot
if ot.option_values.empty?
["Monthly", "Yearly"].each do |freq|
ot.option_values.create(name: freq, presentation: freq)
end
end
month = variants.create(is_master: false, price: price, track_inventory: false)
month.option_values << Spree::OptionValue.find_by(name: "Monthly")
year = variants.create(is_master: false, price: price * 12, track_inventory: false)
year.option_values << Spree::OptionValue.find_by(name: "Yearly")
end
end
membership.rb factory
FactoryGirl.define do
factory :membership, class: Spree::Membership do
name {FFaker::Lorem.word}
monthly_quota { rand(10..200) }
price { rand(10..200) }
trait :unnamed do
name nil
end
trait :without_quota do
monthly_quota nil
end
trait :priceless do
price nil
end
end
end
example of controller test
require 'rails_helper'
RSpec.describe Spree::PremiumController, type: :controller do
let(:valid_membership) { create(:membership) }
let(:variant) { create(:master_variant) }
context "#show" do
it "returns http success" do
get :show
expect(response).to have_http_status(:success)
end
it "returns all memberships" do
get :show
expect(assigns[:memberships]).to include(valid_membership)
end
end
context "#create" do
let!(:store) { create(:store) }
context "user not logged" do
context "valid attributes" do
context "user doesn't exist in database" do
subject do
post(:create, params: {
premium: {
first_name: "Ondrej",
last_name: "Kubala",
email: "ondrej#bala.com",
password: "test123",
password_confirmation: "test123",
membership_id: valid_membership.id,
payment_frequency: "1", #monthly yearly is 2
cc_number: "4111111111111111",
cc_exp_date: "10/22",
cvv: "123"
}
})
end
it "creates user with valid attributes" do
expect { subject }.to change { Spree::User.count }.from(0).to(1)
end
it "logs in user" do
expect(controller.warden).to receive(:set_user)
subject
end
context "create order with variant" do
it "should handle population" do
expect { subject }.to change { Spree::Order.count }.by(1)
user = Spree::User.find_by email: "ondrej#bala.com"
order = user.orders.last
expect(response).to redirect_to go_premium_path
expect(order.line_items.size).to eq(1)
# line_item = order.line_items.first
# expect(line_item.variant_id).to eq(valid_membership.reload.product.variants.)
end
it "charges credit card"
it "should redirect to account page"
end
end
context "user already exists"
end
context "wrong user attributes" do
end
context "wrong payment attributes" do
end
end
context "user is logged in" do
let(:user) { create(:user) }
before do
allow(controller).to receive_messages try_spree_current_user: user
allow(controller).to receive_messages spree_current_user: user
end
it "doesn't create user"
end
end
end
I don't have too much experience in Rspec, but it's weird that it works when server is running in development but in test it gives me that error.
Any idea what is wrong?
My guess would be that product creation call fails for some reason.
Try bang version(product: Spree::Product.create!) to have the error thrown when it occurs.
If product indeed gets created, use pry or byebug to figure out why after reload membership, product is not associated with membership.

RSpec fails upon a namespaced model assigned to blog

I was doing the RSpec testing with Rails and it's failing due to the namespaced model that I assigned to its associations of the model.
CLI:
Failures:
1) Blog::BlobsController GET index assigns all blog/blobs as #blobs
Failure/Error: expect(assigns(:blog::blobs)).to eq([blog::blobs])
NoMethodError:
undefined method `blobs' for :blog:Symbol
# ./spec/controllers/blog/blobs_controller_spec.rb:8:in `block (3 levels) in <top (required)>'
spec/controllers/blog/blobs_controller_spec.rb
RSpec.describe Blog::BlobsController, type: :controller do
describe "GET index" do
it "assigns all blog/blobs as #blobs" do
blobs = Blog::Blob.create!
get :index, {}
expect(assigns(:blog::blobs)).to eq([blog::blobs])
end
end
end
routes.rb
# SNIPPED FOR BREVITY...
namespace :blog do
resources :blobs
end
app/controllers/blog/blobs_controller.rb
class Blog::BlobsController < ApplicationController
before_filter :authenticate_user!, except: [:index, :show]
def index
#blobs = Blog::Blob.all
end
def new
#blob = Blog::Blob.new
end
def edit
#blob = Blog::Blob.find(params[:id])
end
def create
#blob = Blog::Blob.new(blob_params)
if #blob.save
redirect_to #blob
else
render 'new'
end
end
def update
#blob = Blog::Blob.find(params[:id])
if #blob.update(blob_params)
redirect_to #blob
else
render 'edit'
end
end
def show
#blob = Blog::Blob.find(params[:id])
end
def destroy
#blob = Blog::Blob.find(params[:id])
#blob.destroy!
redirect_to blog_blobs_path
end
private
def blob_params
params.require(:blob).permit(:title, :body)
end
end
Is there a better way to test this controller with RSpec?
UPDATE:
Failures:
1) Blog::BlobsController GET #index assigns all widgets as #widgets
Failure/Error: expect(assigns(:blobs)).to eq([blob])
TypeError:
no implicit conversion of Symbol into Integer
# /usr/local/rvm/gems/ruby-2.1.5#rails4/gems/mongo-2.0.4/lib/mongo/server_selector.rb:56:in `[]'
# /usr/local/rvm/gems/ruby-2.1.5#rails4/gems/mongo-2.0.4/lib/mongo/server_selector.rb:56:in `get'
# /usr/local/rvm/gems/ruby-2.1.5#rails4/gems/mongo-2.0.4/lib/mongo/client.rb:170:in `read_preference'
# /usr/local/rvm/gems/ruby-2.1.5#rails4/gems/mongo-2.0.4/lib/mongo/collection/view/readable.rb:318:in `default_read'
# /usr/local/rvm/gems/ruby-2.1.5#rails4/gems/mongo-2.0.4/lib/mongo/collection/view/readable.rb:251:in `read'
# /usr/local/rvm/gems/ruby-2.1.5#rails4/gems/mongo-2.0.4/lib/mongo/collection/view/iterable.rb:38:in `each'
# /usr/local/rvm/gems/ruby-2.1.5#rails4/bundler/gems/mongoid-26f67146a7b7/lib/mongoid/query_cache.rb:207:in `each'
# /usr/local/rvm/gems/ruby-2.1.5#rails4/bundler/gems/mongoid-26f67146a7b7/lib/mongoid/contextual/mongo.rb:116:in `each'
# /usr/local/rvm/gems/ruby-2.1.5#rails4/bundler/gems/mongoid-26f67146a7b7/lib/mongoid/contextual.rb:20:in `each'
# /usr/local/rvm/gems/ruby-2.1.5#rails4/bundler/gems/mongoid-26f67146a7b7/lib/mongoid/criteria.rb:48:in `entries'
# /usr/local/rvm/gems/ruby-2.1.5#rails4/bundler/gems/mongoid-26f67146a7b7/lib/mongoid/criteria.rb:48:in `=='
# ./spec/controllers/blog/blobs_controller_spec.rb:8:in `block (3 levels) in <top (required)>'
Updated spec code:
require 'rails_helper'
RSpec.describe Blog::BlobsController, type: :controller do
describe "GET #index" do
it "assigns all blobs as #blobs" do
blob = Blog::Blob.create!
get :index, {}
expect(assigns(:blobs)).to eq([blob])
end
end
end
Your test says:
blobs = Blog::Blob.create!
This is confusing, because blobs is plural, but you're only creating one blob. So start by renaming that to blob. Then expect(assigns(:blog::blobs)).to eq([blog::blobs]) should be expect(assigns(:blobs)).to eq([blob]).
In the index action, you set #blobs = Blog::Blob.all. The assigns correspond to the controller's instance variables. There's no namespacing.

Mongoid self referencing with accepts_nested_attributes_for

Model:
class Plan
include Mongoid::Document
# Fields
field :name, type: String
# Relationships
references_many :sub_plans,
:autosave => true,
:class_name => 'Plan',
:inverse_class_name => 'Plan',
:inverse_of => :super_plans
references_many :super_plans,
:class_name => 'Plan',
:inverse_class_name => 'Plan',
:inverse_of => :sub_plans
accepts_nested_attributes_for :sub_plans
# Validations
validates_presence_of :name
end
Test:
describe Plan do
it "should always have a name" do
plan = Plan.new
plan.save.should == false
plan[:name] = "World Domination"
plan.save.should == true
end
it "should allow nested plan creation" do
plan = Plan.new(:name => "World Domination", :sub_plans_attributes => {
:name => "Get $50b",
:sub_plans_attributes => {
:name => "Invent"
}
});
plan.sub_plans.count.should == 1
plan.sub_plans.first.name.should == "Get $50b"
plan.sub_plans.first.sub_plans.count.should == 1
plan.sub_plans.first.sub_plans.first.name.should == "Invent"
end
end
Output with -b:
Running spec/models/plan_spec.rb
.F
Failures:
1) Plan should allow nested plan creation
Failure/Error: plan = Plan.new(:name => "World Domination", :sub_plans_attributes => {
TypeError:
can't convert Symbol into String
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/relations/builders/nested_attributes/many.rb:67:in `delete'
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/relations/builders/nested_attributes/many.rb:67:in `destroyable?'
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/relations/builders/nested_attributes/many.rb:103:in `process'
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/relations/builders/nested_attributes/many.rb:30:in `block in build'
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/relations/builders/nested_attributes/many.rb:26:in `each'
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/relations/builders/nested_attributes/many.rb:26:in `build'
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/nested_attributes.rb:47:in `block (3 levels) in accepts_nested_attributes_for'
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/attributes.rb:193:in `_assigning'
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/nested_attributes.rb:45:in `block (2 levels) in accepts_nested_attributes_for'
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/attributes/processing.rb:111:in `block in process_nested'
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/attributes/processing.rb:110:in `each_pair'
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/attributes/processing.rb:110:in `process_nested'
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/attributes/processing.rb:122:in `process_pending'
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/attributes/processing.rb:29:in `process'
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/document.rb:131:in `block in initialize'
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/relations/builders.rb:47:in `_building'
# /usr/lib/ruby/gems/1.9.1/gems/mongoid-2.3.1/lib/mongoid/document.rb:127:in `initialize'
# ./spec/models/plan_spec.rb:11:in `new'
# ./spec/models/plan_spec.rb:11:in `block (2 levels) in <top (required)>'
# /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.6.4/lib/rspec/core/example.rb:48:in `instance_eval'
# /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.6.4/lib/rspec/core/example.rb:48:in `block in run'
# /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.6.4/lib/rspec/core/example.rb:107:in `with_around_hooks'
# /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.6.4/lib/rspec/core/example.rb:45:in `run'
# /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.6.4/lib/rspec/core/example_group.rb:294:in `block in run_examples'
# /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.6.4/lib/rspec/core/example_group.rb:290:in `map'
# /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.6.4/lib/rspec/core/example_group.rb:290:in `run_examples'
# /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.6.4/lib/rspec/core/example_group.rb:262:in `run'
# /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.6.4/lib/rspec/core/command_line.rb:24:in `block (2 levels) in run'
# /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.6.4/lib/rspec/core/command_line.rb:24:in `map'
# /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.6.4/lib/rspec/core/command_line.rb:24:in `block in run'
# /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.6.4/lib/rspec/core/reporter.rb:12:in `report'
# /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.6.4/lib/rspec/core/command_line.rb:21:in `run'
# /usr/lib/ruby/gems/1.9.1/gems/rspec-core-2.6.4/lib/rspec/monkey/spork/test_framework/rspec.rb:5:in `run_tests'
# /usr/lib/ruby/gems/1.9.1/gems/spork-0.9.0.rc9/lib/spork/run_strategy/forking.rb:13:in `block in run'
# /usr/lib/ruby/gems/1.9.1/gems/spork-0.9.0.rc9/lib/spork/forker.rb:21:in `block in initialize'
# /usr/lib/ruby/gems/1.9.1/gems/spork-0.9.0.rc9/lib/spork/forker.rb:18:in `fork'
# /usr/lib/ruby/gems/1.9.1/gems/spork-0.9.0.rc9/lib/spork/forker.rb:18:in `initialize'
# /usr/lib/ruby/gems/1.9.1/gems/spork-0.9.0.rc9/lib/spork/run_strategy/forking.rb:9:in `new'
# /usr/lib/ruby/gems/1.9.1/gems/spork-0.9.0.rc9/lib/spork/run_strategy/forking.rb:9:in `run'
# /usr/lib/ruby/gems/1.9.1/gems/spork-0.9.0.rc9/lib/spork/server.rb:48:in `run'
# /usr/lib/ruby/1.9.1/drb/drb.rb:1558:in `perform_without_block'
# /usr/lib/ruby/1.9.1/drb/drb.rb:1518:in `perform'
# /usr/lib/ruby/1.9.1/drb/drb.rb:1592:in `block (2 levels) in main_loop'
# /usr/lib/ruby/1.9.1/drb/drb.rb:1588:in `loop'
# /usr/lib/ruby/1.9.1/drb/drb.rb:1588:in `block in main_loop'
Finished in 0.00917 seconds
2 examples, 1 failure
Failed examples:
rspec ./spec/models/plan_spec.rb:10 # Plan should allow nested plan creation
Why am I getting this error, and how can I get my many-many self reference working? I'm using Mongoid version 2.3.1 and Rails version 3.1.1. Thanks
After several hours spent trying several different combinations and finally giving up and sleeping on it, I have finally got it to work! Model:
class Plan
include Mongoid::Document
# Fields
field :name, type: String
# Relationships
has_and_belongs_to_many :subplans, :inverse_of => :parents, :class_name => 'Plan', :autosave => true
has_and_belongs_to_many :parents, :inverse_of => :subplans, :class_name => 'Plan', :autosave => true
accepts_nested_attributes_for :subplans
# Validations
validates_presence_of :name
end
Tests:
describe Plan do
it "should always have a name" do
plan = Plan.new
plan.save.should == false
plan[:name] = "World Domination"
plan.save.should == true
end
it "should have a nested relationship" do
root = Plan.create name: "Parent Plan"
child1 = root.subplans.create name: 'Child Plan #1'
child2 = Plan.create name: "Child Plan #2"
root.subplans << child2
root.subplans.size.should == 2
child1.parents.size.should == 1
child1.parents.first.should == root
child2.parents.size.should == 1
child2.parents.first.should == root
end
it "should accept nested attributes for subplans" do
plan = Plan.new :name => "root",
:subplans_attributes => [{:name => "child"}]
plan.save; plan.reload
plan.subplans.size.should == 1
plan.subplans.first.name.should == "child"
end
end

Resources