Skip to content

Instantly share code, notes, and snippets.

@exocode
Created November 16, 2022 14:33
Show Gist options
  • Save exocode/6d635f226f008e4c0e35c45e5b332de9 to your computer and use it in GitHub Desktop.
Save exocode/6d635f226f008e4c0e35c45e5b332de9 to your computer and use it in GitHub Desktop.
AR tests (example for counter_culutre)
#!/usr/bin/env ruby
# frozen_string_literal: true
#######################################
## just run in your terminal:
##
## > ruby test.rb
##
## If you need logging callbacks
## just uncomment the affected lines
#######################################
require 'bundler/inline'
gemfile(true) do
source 'https://rubygems.org'
gem 'dry-types', '0.13.3'
gem 'sqlite3'
gem 'rom-repository', '2.0.2', require: false
gem 'rom-sql', '2.5.0', require: false
gem 'activerecord'
gem 'pry-byebug'
gem 'rspec'
gem 'counter_culture'
end
require 'rspec/autorun'
RSpec.configure do |config|
config.color = true
config.formatter = :documentation
end
require 'pry'
require 'rspec'
require 'sqlite3'
require 'active_record'
require 'active_support/all'
RSpec.describe 'Count relations' do
before(:each) do
ActiveRecord::Base.establish_connection(
adapter: :sqlite3,
database: 'database.db'
)
ActiveRecord::Schema.define do
create_table :categories do |t|
t.column 'gid', :int
t.column 'name', :string
t.integer 'products_count', default: 0
end
create_table :products do |t|
t.column 'gid', :int
t.column 'name', :string
t.column 'visible', :boolean
end
create_table :categories_products do |t|
t.column 'gid', :int
t.bigint 'category_id', null: false
t.bigint 'product_id', null: false
end
end
class Category < ActiveRecord::Base
has_many :categories_products
has_many :products, through: :categories_products, class_name: 'Product'
end
class Product < ActiveRecord::Base
has_many :categories_products, dependent: :destroy
has_many :categories, through: :categories_products, class_name: 'Category'
scope :visible, -> { where(visible: true) }
end
class CategoriesProduct < ActiveRecord::Base
belongs_to :category # , class_name: 'Category' # , counter_cache: :products_count
belongs_to :product # , class_name: 'Product'
end
class CategoriesProduct < ActiveRecord::Base
belongs_to :category # , class_name: 'Category' # , counter_cache: :products_count
belongs_to :product # , class_name: 'Product'
counter_culture :category,
column_name: ->(model) { model.product.visible? ? 'products_count' : nil },
column_names: {
Product.visible => 'products_count'
},
touch: true
end
end
after(:each) do
puts '### Deleting database'
`rm database.db`
end
let(:create_ar_product!) do
Product.create(name: 'Product1', visible: true)
end
let(:create_ar_categories!) do
Category.create(name: 'Category1')
Category.create(name: 'Category2')
end
describe 'AR' do
before(:each) do
class Product < ActiveRecord::Base
has_many :categories_products, dependent: :destroy
has_many :categories, through: :categories_products, class_name: 'Category'
# before_create { puts "before_create #{self.class.name} id: #{id}" }
# after_create { puts "after_create #{self.class.name} id: #{id}" }
# before_save { puts "before_save #{self.class.name} id: #{id}" }
# after_save { puts "after_save #{self.class.name} id: #{id}" }
# after_destroy { puts "after_destroy #{self.class.name} id: #{id}" }
# before_destroy { puts "before_destroy #{self.class.name} id: #{id}" }
# after_commit { puts "after_commit #{self.class.name} id: #{id}" }
# before_update { puts "before_update #{self.class.name} id: #{id}" }
# after_update { puts "after_update #{self.class.name} id: #{id}" }
end
class Category < ActiveRecord::Base
has_many :categories_products
has_many :products, through: :categories_products, class_name: 'Product'
end
class CategoriesProduct < ActiveRecord::Base
belongs_to :product
belongs_to :category
# before_update do
# puts "before_update #{self.class.name} id: #{id} category_id: #{category_id} product: #{product_id}"
# end
# after_update do
# puts "after_update #{self.class.name} id: #{id} category_id: #{category_id} product: #{product_id}"
# end
# before_create do
# puts "before_create #{self.class.name} id: #{id} category_id: #{category_id} product: #{product_id}"
# end
# after_create do
# puts "after_create #{self.class.name} id: #{id} category_id: #{category_id} product: #{product_id}"
# end
# before_save do
# puts "before_save #{self.class.name} id: #{id} category_id: #{category_id} product: #{product_id}"
# end
# after_save do
# puts "after_save #{self.class.name} id: #{id} category_id: #{category_id} product: #{product_id}"
# end
# after_destroy do
# puts "after_destroy #{self.class.name} id: #{id} category_id: #{category_id} product: #{product_id}"
# end
# before_destroy do
# puts "before_destroy #{self.class.name} id: #{id} category_id: #{category_id} product: #{product_id}"
# end
# after_commit do
# puts "after_commit #{self.class.name} id: #{id} category_id: #{category_id} product: #{product_id}"
# end
end
create_ar_product!
create_ar_categories!
end
let(:product) { Product.first }
let(:category) { Category.first }
let(:new_category) { Category.last }
context 'base testing' do
it 'assigns product to category' do
product.categories << category
expect(Category.find(category.id).products).to include(product)
end
it 'deletes properly' do
product.categories << category
puts "categories.count before: #{product.categories.count}"
product.categories.destroy(product.categories.last)
puts "categories.count after: #{product.categories.count}"
expect(category.reload.products_count).to eql 0
end
it 'count products' do
product.categories << category
expect(category.reload.products.count).to eql 1
end
end
context 'counter_culture' do
it 'starts with a clean database' do
expect(CategoriesProduct.count).to eql 0
expect(Category.first.products_count).to eql 0
expect(Category.first.products.count).to eql 0
expect(Category.last.products.count).to eql 0
expect(Category.last.products_count).to eql 0
end
it 'via <<"' do
product.categories << category
expect(category.reload.products_count).to eql 1
end
it 'via "update"' do
product.update(categories: [category])
expect(category.reload.products_count).to eql 1
end
context 'recounting' do
it 'via "update"' do
product.update(categories: [new_category])
expect(category.reload.products_count).to eql 0
expect(new_category.reload.products_count).to eql 1
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment