Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 使用FactoryGirl创建的模型是';在控制器中不可用 原始问题_Ruby On Rails_Rspec_Capybara - Fatal编程技术网

Ruby on rails 使用FactoryGirl创建的模型是';在控制器中不可用 原始问题

Ruby on rails 使用FactoryGirl创建的模型是';在控制器中不可用 原始问题,ruby-on-rails,rspec,capybara,Ruby On Rails,Rspec,Capybara,我试图用RSpec和Capybara编写一些功能测试,并想知道为什么我的gon对象总是空的,尽管它是在我的控制器中设置的: app/controllers/timetrackings\u controller.rb: class TimetrackingsController < ApplicationController include ApplicationHelper before_action :authenticate_user! before_action :se

我试图用RSpec和Capybara编写一些功能测试,并想知道为什么我的gon对象总是空的,尽管它是在我的控制器中设置的:

app/controllers/timetrackings\u controller.rb

class TimetrackingsController < ApplicationController
  include ApplicationHelper

  before_action :authenticate_user!
  before_action :set_timetracking, only: [:update, :destroy]

  # GET /timetrackings
  def index
    projects = Project.all_cached.select('id, name, category, number, customer_id').includes(:customer).where(:archived => false).order(:number)
    gon.projects = group_by_customer(projects).to_h
    gon.services = Service.all_cached.select('id, name').where(:archived => false).order('LOWER(name)')
  end

  ...
require 'devise'

# Setup Capybara
require 'capybara/rspec'
require 'capybara/poltergeist'
Capybara.always_include_port = true
Capybara.javascript_driver = :poltergeist

# Use SimpleCov for code coverage
require 'simplecov'
require 'simplecov-shield'
SimpleCov.start 'rails'
SimpleCov.formatters = [
  SimpleCov::Formatter::HTMLFormatter,
  SimpleCov::Formatter::ShieldFormatter
]

# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rspec/rails'
require 'shoulda-matchers'

# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

# Checks for pending migrations before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)

module ControllerMacros
  def attributes_with_foreign_keys(*args)
    FactoryGirl.build(*args).attributes.delete_if do |k, v|
      ['id', 'type', 'foreign_id', 'foreign_type', 'created_at', 'updated_at'].member?(k)
    end
  end
end

RSpec.configure do |config|

  config.use_transactional_fixtures = false
  config.use_instantiated_fixtures  = false
  config.mock_with :rspec

  # Use FactoryGirl for fixtures
  config.include FactoryGirl::Syntax::Methods

  # Auto-detect spec types
  config.infer_spec_type_from_file_location!

  # Insert devise helpers in controller specs
  config.include Devise::TestHelpers, type: :controller
  config.include Warden::Test::Helpers
  config.extend ControllerMacros, type: :controller
  config.include ControllerMacros


  # Run specs in random order to surface order dependencies. If you find an
  # order dependency and want to debug it, you can fix the order by providing
  # the seed, which is printed after each run.
  #     --seed 1234
  config.order = 'random'

  config.before(:suite) do

    Warden.test_mode!

    # Clean all tables to start
    DatabaseCleaner.clean_with :truncation

    # Use transactions for tests
    DatabaseCleaner.strategy = :transaction

    # Truncating doesn't drop schemas, ensure we're clean here, app *may not* exist
    Apartment::Tenant.drop('test') rescue nil

    # Create the default tenant for our tests
    Account.create!(name: 'Test', domain: 'test', email: 'info@example.com')

  end

  config.before(:each) do

    # Start transaction for this test
    DatabaseCleaner.start

    # Switch into the default tenant
    Apartment::Tenant.switch! 'test'

    # Use Timecop to freeze times on time-critical tests
    Timecop.return

  end

  config.after(:each) do

    # Reset tentant back to `public`
    Apartment::Tenant.reset

    # Rollback transaction
    DatabaseCleaner.clean

  end

end
但结果只是:

########
{}
[{"id":2,"number":"2","name":"project2","description":"Some notes","archived":false,"customer_id":2,"created_at":"2015-11-30T16:05:40.160+01:00","updated_at":"2015-11-30T16:05:40.160+01:00","rate_type":null,"hourly_rate":null,"service_rates":null,"budget_type":null,"budget_rate":null,"category":"A","deadline":null}]
[{"id":2,"name":"service2","description":"Some notes","archived":false,"created_at":"2015-11-30T16:05:40.173+01:00","updated_at":"2015-11-30T16:05:40.173+01:00","billable":null,"hourly_rate":null}]
########
这是我的
spec\u helper.rb

class TimetrackingsController < ApplicationController
  include ApplicationHelper

  before_action :authenticate_user!
  before_action :set_timetracking, only: [:update, :destroy]

  # GET /timetrackings
  def index
    projects = Project.all_cached.select('id, name, category, number, customer_id').includes(:customer).where(:archived => false).order(:number)
    gon.projects = group_by_customer(projects).to_h
    gon.services = Service.all_cached.select('id, name').where(:archived => false).order('LOWER(name)')
  end

  ...
require 'devise'

# Setup Capybara
require 'capybara/rspec'
require 'capybara/poltergeist'
Capybara.always_include_port = true
Capybara.javascript_driver = :poltergeist

# Use SimpleCov for code coverage
require 'simplecov'
require 'simplecov-shield'
SimpleCov.start 'rails'
SimpleCov.formatters = [
  SimpleCov::Formatter::HTMLFormatter,
  SimpleCov::Formatter::ShieldFormatter
]

# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rspec/rails'
require 'shoulda-matchers'

# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end
# in _spec.rb will both be required and run as specs, causing the specs to be
# run twice. It is recommended that you do not name files matching this glob to
# end with _spec.rb. You can configure this pattern with with the --pattern
# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

# Checks for pending migrations before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)

module ControllerMacros
  def attributes_with_foreign_keys(*args)
    FactoryGirl.build(*args).attributes.delete_if do |k, v|
      ['id', 'type', 'foreign_id', 'foreign_type', 'created_at', 'updated_at'].member?(k)
    end
  end
end

RSpec.configure do |config|

  config.use_transactional_fixtures = false
  config.use_instantiated_fixtures  = false
  config.mock_with :rspec

  # Use FactoryGirl for fixtures
  config.include FactoryGirl::Syntax::Methods

  # Auto-detect spec types
  config.infer_spec_type_from_file_location!

  # Insert devise helpers in controller specs
  config.include Devise::TestHelpers, type: :controller
  config.include Warden::Test::Helpers
  config.extend ControllerMacros, type: :controller
  config.include ControllerMacros


  # Run specs in random order to surface order dependencies. If you find an
  # order dependency and want to debug it, you can fix the order by providing
  # the seed, which is printed after each run.
  #     --seed 1234
  config.order = 'random'

  config.before(:suite) do

    Warden.test_mode!

    # Clean all tables to start
    DatabaseCleaner.clean_with :truncation

    # Use transactions for tests
    DatabaseCleaner.strategy = :transaction

    # Truncating doesn't drop schemas, ensure we're clean here, app *may not* exist
    Apartment::Tenant.drop('test') rescue nil

    # Create the default tenant for our tests
    Account.create!(name: 'Test', domain: 'test', email: 'info@example.com')

  end

  config.before(:each) do

    # Start transaction for this test
    DatabaseCleaner.start

    # Switch into the default tenant
    Apartment::Tenant.switch! 'test'

    # Use Timecop to freeze times on time-critical tests
    Timecop.return

  end

  config.after(:each) do

    # Reset tentant back to `public`
    Apartment::Tenant.reset

    # Rollback transaction
    DatabaseCleaner.clean

  end

end
更新 好吧,我认为问题出在别处:

使用FactoryGirl(如
FactoryGirl.create(:project)
)创建模型后,控制器中的记录不可用。如果我写了这样的东西

@foo = Project.all.to_json
在我的控制器中,要在我的视图中显示此数据,我只需获得
[]
(在调用
保存和打开页面后)

我想,
FactoryGirl.create
直接将数据写入数据库?为什么我的控制器方法中没有可用的数据

更新2 添加

config.before(:each, :js => true) do
  DatabaseCleaner.strategy = :truncation
end
解决了这个问题,但现在我得到:

 Failure/Error: user = FactoryGirl.create(:user)
     ActiveRecord::RecordNotUnique:
       PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_users_on_lastname"
       DETAIL:  Key (lastname)=(Kautzer) already exists.
       : INSERT INTO "users" ("email", "initial", "firstname", "lastname", "encrypted_password", "archived", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id"
我以为每次测试后数据库都会被清理

更新3 不管怎样,最后一个问题是数据库设置中的错误。

添加

config.before(:each, :js => true) do
  DatabaseCleaner.strategy = :truncation
end
config.before(:each, :js => true) do
  DatabaseCleaner.strategy = :truncation
end
对于我的
spec\u helper.rb
解决了问题:)

不完全是我的问题和解决方案,但它导致了我的解决方案。这个故事的寓意是:在使用FactoryGirl时使用
DatabaseCleaner
,并正确设置它们+1谢谢