├── test ├── dummy │ ├── lib │ │ └── assets │ │ │ └── .keep │ ├── public │ │ ├── favicon.ico │ │ ├── apple-touch-icon.png │ │ ├── apple-touch-icon-precomposed.png │ │ ├── 500.html │ │ ├── 422.html │ │ └── 404.html │ ├── app │ │ ├── assets │ │ │ ├── images │ │ │ │ └── .keep │ │ │ ├── config │ │ │ │ └── manifest.js │ │ │ └── stylesheets │ │ │ │ └── application.css │ │ ├── controllers │ │ │ ├── concerns │ │ │ │ └── .keep │ │ │ ├── static_pages_controller.rb │ │ │ └── application_controller.rb │ │ ├── views │ │ │ ├── layouts │ │ │ │ ├── mailer.text.erb │ │ │ │ ├── admin.html.erb │ │ │ │ ├── mailer.html.erb │ │ │ │ └── application.html.erb │ │ │ └── static_pages │ │ │ │ └── home.html.erb │ │ ├── helpers │ │ │ └── application_helper.rb │ │ ├── models │ │ │ ├── application_record.rb │ │ │ └── user.rb │ │ ├── channels │ │ │ └── application_cable │ │ │ │ ├── channel.rb │ │ │ │ └── connection.rb │ │ ├── mailers │ │ │ └── application_mailer.rb │ │ ├── jobs │ │ │ └── application_job.rb │ │ └── javascript │ │ │ └── packs │ │ │ └── application.js │ ├── db │ │ ├── seeds.rb │ │ ├── test.sqlite3 │ │ ├── migrate │ │ │ ├── 02_create_action_text_tables.rb │ │ │ ├── 01_create_users.rb │ │ │ └── 03_create_active_storage_tables.active_storage.rb │ │ └── schema.rb │ ├── bin │ │ ├── rake │ │ ├── rails │ │ └── setup │ ├── config │ │ ├── routes.rb │ │ ├── environment.rb │ │ ├── initializers │ │ │ ├── mime_types.rb │ │ │ ├── application_controller_renderer.rb │ │ │ ├── cookies_serializer.rb │ │ │ ├── filter_parameter_logging.rb │ │ │ ├── permissions_policy.rb │ │ │ ├── assets.rb │ │ │ ├── wrap_parameters.rb │ │ │ ├── backtrace_silencers.rb │ │ │ ├── inflections.rb │ │ │ ├── content_security_policy.rb │ │ │ ├── effective_addresses.rb │ │ │ └── devise.rb │ │ ├── cable.yml │ │ ├── boot.rb │ │ ├── database.yml │ │ ├── application.rb │ │ ├── locales │ │ │ └── en.yml │ │ ├── storage.yml │ │ ├── puma.rb │ │ └── environments │ │ │ ├── test.rb │ │ │ ├── development.rb │ │ │ └── production.rb │ ├── config.ru │ ├── Rakefile │ └── log │ │ └── test.log ├── effective_addresses_test.rb ├── models │ └── addresses_test.rb ├── support │ ├── effective_addresses_test_builder.rb │ └── effective_addresses_test_helper.rb └── test_helper.rb ├── Gemfile ├── app ├── assets │ └── javascripts │ │ ├── effective_addresses.js │ │ └── effective_addresses │ │ ├── shipping_address_same_as_billing.js.coffee │ │ └── address_fields.js.coffee ├── views │ └── effective │ │ └── addresses │ │ ├── _subregions.html.haml │ │ ├── _address.html.haml │ │ ├── _formtastic.html.haml │ │ ├── _form_with.html.haml │ │ └── _simple_form.html.haml ├── controllers │ └── effective │ │ └── addresses_controller.rb ├── helpers │ └── effective_addresses_helper.rb └── models │ ├── effective │ └── address.rb │ └── concerns │ └── acts_as_addressable.rb ├── lib ├── effective_addresses │ ├── version.rb │ └── engine.rb ├── validators │ ├── effective_address_valid_validator.rb │ └── effective_address_full_name_presence_validator.rb ├── effective_addresses.rb └── generators │ └── effective_addresses │ └── install_generator.rb ├── .gitignore ├── config ├── routes.rb ├── locales │ └── simple_form.en.yml └── effective_addresses.rb ├── Rakefile ├── bin └── rails ├── db └── migrate │ └── 101_create_effective_addresses.rb ├── MIT-LICENSE ├── effective_addresses.gemspec ├── .circleci └── config.yml ├── Gemfile.lock └── README.md /test/dummy/lib/assets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/dummy/public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/dummy/app/assets/images/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/dummy/public/apple-touch-icon.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/dummy/app/controllers/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/dummy/db/seeds.rb: -------------------------------------------------------------------------------- 1 | puts 'Nothing here' 2 | -------------------------------------------------------------------------------- /test/dummy/public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/dummy/app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'http://rubygems.org' 2 | ruby '3.1.2' 3 | 4 | gemspec 5 | -------------------------------------------------------------------------------- /test/dummy/app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /test/dummy/app/views/static_pages/home.html.erb: -------------------------------------------------------------------------------- 1 |

Hello effective world

2 | -------------------------------------------------------------------------------- /app/assets/javascripts/effective_addresses.js: -------------------------------------------------------------------------------- 1 | //= require_tree ./effective_addresses 2 | -------------------------------------------------------------------------------- /lib/effective_addresses/version.rb: -------------------------------------------------------------------------------- 1 | module EffectiveAddresses 2 | VERSION = '1.11.5'.freeze 3 | end 4 | -------------------------------------------------------------------------------- /test/dummy/db/test.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/code-and-effect/effective_addresses/HEAD/test/dummy/db/test.sqlite3 -------------------------------------------------------------------------------- /app/views/effective/addresses/_subregions.html.haml: -------------------------------------------------------------------------------- 1 | = options_for_select(effective_address_regions_collection(@subregions)) 2 | -------------------------------------------------------------------------------- /test/dummy/bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative "../config/boot" 3 | require "rake" 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /test/dummy/app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | self.abstract_class = true 3 | end 4 | -------------------------------------------------------------------------------- /test/dummy/config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | devise_for :users 3 | root to: 'static_pages#home' 4 | end 5 | -------------------------------------------------------------------------------- /test/dummy/app/controllers/static_pages_controller.rb: -------------------------------------------------------------------------------- 1 | class StaticPagesController < ApplicationController 2 | def home 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /test/dummy/app/channels/application_cable/channel.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Channel < ActionCable::Channel::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /test/dummy/app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link_tree ../images 2 | //= link_directory ../stylesheets .css 3 | //= link effective_addresses_manifest.js 4 | -------------------------------------------------------------------------------- /test/dummy/app/channels/application_cable/connection.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Connection < ActionCable::Connection::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /test/dummy/app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | class ApplicationMailer < ActionMailer::Base 2 | default from: 'from@example.com' 3 | layout 'mailer' 4 | end 5 | -------------------------------------------------------------------------------- /test/dummy/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../config/application', __dir__) 3 | require_relative "../config/boot" 4 | require "rails/commands" 5 | -------------------------------------------------------------------------------- /test/dummy/config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative "application" 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | .bundle/ 3 | tmp/ 4 | log/*.log 5 | pkg/ 6 | spec/dummy/db/*.sqlite3 7 | spec/dummy/log/*.log 8 | spec/dummy/tmp/ 9 | spec/dummy/.sass-cache 10 | .idea 11 | -------------------------------------------------------------------------------- /test/dummy/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | 3 | def authorize!(action, resource) 4 | true 5 | end 6 | 7 | end 8 | -------------------------------------------------------------------------------- /test/dummy/config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative "config/environment" 4 | 5 | run Rails.application 6 | Rails.application.load_server 7 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /test/effective_addresses_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class EffectiveAddressesTest < ActiveSupport::TestCase 4 | test "it has a version number" do 5 | assert EffectiveAddresses::VERSION 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /test/models/addresses_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class AddressesTest < ActiveSupport::TestCase 4 | test 'is valid' do 5 | address = build_effective_address 6 | assert address.valid? 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /test/dummy/config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: test 6 | 7 | production: 8 | adapter: redis 9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 10 | channel_prefix: dummy_production 11 | -------------------------------------------------------------------------------- /test/dummy/Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative "config/application" 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /test/dummy/config/boot.rb: -------------------------------------------------------------------------------- 1 | # Set up gems listed in the Gemfile. 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__) 3 | 4 | require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) 5 | $LOAD_PATH.unshift File.expand_path('../../../lib', __dir__) 6 | -------------------------------------------------------------------------------- /lib/validators/effective_address_valid_validator.rb: -------------------------------------------------------------------------------- 1 | class EffectiveAddressValidValidator < ActiveModel::EachValidator 2 | def validate_each(record, attribute, value) 3 | if value.present? && !value.empty? && !value.valid? 4 | record.errors[attribute] << 'is invalid' 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # ActiveSupport::Reloader.to_prepare do 4 | # ApplicationController.renderer.defaults.merge!( 5 | # http_host: 'example.org', 6 | # https: false 7 | # ) 8 | # end 9 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Specify a serializer for the signed and encrypted cookie jars. 4 | # Valid options are :json, :marshal, and :hybrid. 5 | Rails.application.config.action_dispatch.cookies_serializer = :json 6 | -------------------------------------------------------------------------------- /test/dummy/app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | # Automatically retry jobs that encountered a deadlock 3 | # retry_on ActiveRecord::Deadlocked 4 | 5 | # Most jobs are safe to ignore if the underlying records are no longer available 6 | # discard_on ActiveJob::DeserializationError 7 | end 8 | -------------------------------------------------------------------------------- /test/dummy/app/views/layouts/admin.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dummy 5 | <%= csrf_meta_tags %> 6 | <%= csp_meta_tag %> 7 | 8 | <%= stylesheet_link_tag 'application', media: 'all' %> 9 | 10 | 11 | 12 | <%= yield %> 13 | 14 | 15 | -------------------------------------------------------------------------------- /test/dummy/app/views/layouts/mailer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [ 5 | :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn 6 | ] 7 | -------------------------------------------------------------------------------- /test/dummy/app/models/user.rb: -------------------------------------------------------------------------------- 1 | class User < ApplicationRecord 2 | devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable 3 | 4 | acts_as_addressable :billing 5 | 6 | # effective_addresses_organization_user 7 | # effective_addresses_user 8 | 9 | def to_s 10 | "#{first_name} #{last_name}" 11 | end 12 | 13 | end 14 | -------------------------------------------------------------------------------- /lib/validators/effective_address_full_name_presence_validator.rb: -------------------------------------------------------------------------------- 1 | class EffectiveAddressFullNamePresenceValidator < ActiveModel::EachValidator 2 | def validate_each(record, attribute, value) 3 | if value.present? && !value.empty? && value.full_name.blank? 4 | record.errors[attribute] << 'is invalid' 5 | value.errors[:full_name] << "can't be blank" 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | EffectiveAddresses::Engine.routes.draw do 4 | scope :module => 'effective' do 5 | match 'addresses/subregions/:country_code', to: 'addresses#subregions', as: 'address_subregions', via: :get 6 | end 7 | end 8 | 9 | Rails.application.routes.draw do 10 | mount EffectiveAddresses::Engine => '/', :as => 'effective_addresses' 11 | end 12 | -------------------------------------------------------------------------------- /test/dummy/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dummy 5 | 6 | <%= csrf_meta_tags %> 7 | <%= csp_meta_tag %> 8 | 9 | <%= stylesheet_link_tag 'application', media: 'all' %> 10 | 11 | 12 | 13 | <%= yield %> 14 | 15 | 16 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/setup" 2 | 3 | APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__) 4 | load "rails/tasks/engine.rake" 5 | 6 | load "rails/tasks/statistics.rake" 7 | 8 | require "bundler/gem_tasks" 9 | 10 | require "rake/testtask" 11 | 12 | Rake::TestTask.new(:test) do |t| 13 | t.libs << 'test' 14 | t.pattern = 'test/**/*_test.rb' 15 | t.verbose = false 16 | end 17 | 18 | task default: :test 19 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/permissions_policy.rb: -------------------------------------------------------------------------------- 1 | # Define an application-wide HTTP permissions policy. For further 2 | # information see https://developers.google.com/web/updates/2018/06/feature-policy 3 | # 4 | # Rails.application.config.permissions_policy do |f| 5 | # f.camera :none 6 | # f.gyroscope :none 7 | # f.microphone :none 8 | # f.usb :none 9 | # f.fullscreen :self 10 | # f.payment :self, "https://secure.example.com" 11 | # end 12 | -------------------------------------------------------------------------------- /app/controllers/effective/addresses_controller.rb: -------------------------------------------------------------------------------- 1 | module Effective 2 | class AddressesController < ApplicationController 3 | skip_authorization_check if defined?(CanCan) 4 | 5 | def subregions 6 | @subregions = Carmen::Country.coded(params[:country_code]).try(:subregions) 7 | 8 | if @subregions.present? 9 | render partial: 'effective/addresses/subregions' 10 | else 11 | render body: "" 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/views/effective/addresses/_address.html.haml: -------------------------------------------------------------------------------- 1 | - if address.full_name.present? 2 | = address.full_name 3 | %br 4 | 5 | - if defined?(email) && email.present? 6 | = mail_to(email) 7 | %br 8 | 9 | = address.address1 10 | %br 11 | 12 | - if address.address2.present? 13 | = address.address2 14 | %br 15 | 16 | - if address.try(:address3).present? 17 | = address.address3 18 | %br 19 | 20 | = [address.city.presence, address.state_code.presence, ' ' + address.postal_code.presence].compact.join(' ').html_safe 21 | 22 | %br 23 | = address.country.to_s 24 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = '1.0' 5 | 6 | # Add additional assets to the asset load path. 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | 9 | # Precompile additional assets. 10 | # application.js, application.css, and all non-JS/CSS in the app/assets 11 | # folder are already added. 12 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 13 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /test/dummy/db/migrate/02_create_action_text_tables.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from action_text (originally 20180528164100) 2 | class CreateActionTextTables < ActiveRecord::Migration[6.0] 3 | def change 4 | create_table :action_text_rich_texts do |t| 5 | t.string :name, null: false 6 | t.text :body, size: :long 7 | t.references :record, null: false, polymorphic: true, index: false 8 | 9 | t.timestamps 10 | 11 | t.index [ :record_type, :record_id, :name ], name: "index_action_text_rich_texts_uniqueness", unique: true 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code 7 | # by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'". 8 | Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"] 9 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # This command will automatically be run when you run "rails" with Rails gems 3 | # installed from the root of your application. 4 | 5 | ENGINE_ROOT = File.expand_path('..', __dir__) 6 | ENGINE_PATH = File.expand_path('../lib/effective_events/engine', __dir__) 7 | APP_PATH = File.expand_path('../test/dummy/config/application', __dir__) 8 | 9 | # Set up gems listed in the Gemfile. 10 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 11 | require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE']) 12 | 13 | require 'rails/all' 14 | require 'rails/engine/commands' 15 | -------------------------------------------------------------------------------- /config/locales/simple_form.en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | simple_form: 3 | labels: 4 | defaults: 5 | full_name: Full name 6 | address1: Address 1 7 | address2: Address 2 8 | address3: Address 3 9 | country_code: Country 10 | state_code: Province / State 11 | postal_code: Postal / Zip code 12 | 13 | # hints: 14 | # defaults: 15 | 16 | placeholders: 17 | defaults: 18 | full_name: Full name 19 | address1: Address 20 | city: City 21 | postal_code: Postal / Zip code 22 | 23 | prompts: 24 | defaults: 25 | country_code: Choose country... 26 | state_code: Please choose country first 27 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /db/migrate/101_create_effective_addresses.rb: -------------------------------------------------------------------------------- 1 | class CreateEffectiveAddresses < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :addresses do |t| 4 | t.string :addressable_type 5 | t.integer :addressable_id 6 | 7 | t.string :category, :limit => 64 8 | 9 | t.string :full_name 10 | 11 | t.string :address1 12 | t.string :address2 13 | t.string :address3 14 | 15 | t.string :city 16 | t.string :state_code 17 | t.string :country_code 18 | t.string :postal_code 19 | 20 | t.datetime :updated_at 21 | t.datetime :created_at 22 | end 23 | 24 | add_index :addresses, [:addressable_type, :addressable_id] 25 | add_index :addresses, :addressable_id 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /test/dummy/config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite. Versions 3.8.0 and up are supported. 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem 'sqlite3' 6 | # 7 | default: &default 8 | adapter: sqlite3 9 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 10 | timeout: 5000 11 | migration_paths: db/migrate ../../db/migrate 12 | 13 | development: 14 | <<: *default 15 | database: db/development.sqlite3 16 | 17 | # Warning: The database defined as "test" will be erased and 18 | # re-generated from your development database when you run "rake". 19 | # Do not set this db to the same as development or production. 20 | test: 21 | <<: *default 22 | database: db/test.sqlite3 23 | 24 | production: 25 | <<: *default 26 | database: db/production.sqlite3 27 | -------------------------------------------------------------------------------- /lib/effective_addresses.rb: -------------------------------------------------------------------------------- 1 | require 'carmen' 2 | require 'effective_resources' 3 | require 'effective_addresses/engine' 4 | require 'effective_addresses/version' 5 | 6 | module EffectiveAddresses 7 | 8 | def self.config_keys 9 | [ 10 | :addresses_table_name, 11 | :country_codes, 12 | :country_codes_priority, 13 | :use_full_name, 14 | :use_address3, 15 | :simple_form_options, 16 | :validate_postal_code_format, 17 | :pre_selected_country, 18 | :pre_selected_state 19 | ] 20 | end 21 | 22 | include EffectiveGem 23 | 24 | def self.permitted_params 25 | [ 26 | :address1, :address2, :address3, :city, :country_code, :state_code, :postal_code, 27 | :full_name, :shipping_address_same_as_billing 28 | ] 29 | end 30 | 31 | end 32 | -------------------------------------------------------------------------------- /test/dummy/app/javascript/packs/application.js: -------------------------------------------------------------------------------- 1 | // This is a manifest file that'll be compiled into application.js, which will include all the files 2 | // listed below. 3 | // 4 | // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, 5 | // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. 6 | // 7 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the 8 | // compiled file. JavaScript code in this file should be added after the last require_* statement. 9 | // 10 | // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details 11 | // about supported directives. 12 | // 13 | //= require rails-ujs 14 | //= require activestorage 15 | //= require_tree . 16 | -------------------------------------------------------------------------------- /lib/effective_addresses/engine.rb: -------------------------------------------------------------------------------- 1 | module EffectiveAddresses 2 | class Engine < ::Rails::Engine 3 | engine_name 'effective_addresses' 4 | 5 | config.autoload_paths += Dir["#{config.root}/lib/validators"] 6 | config.eager_load_paths += Dir["#{config.root}/lib/validators"] 7 | 8 | # Include acts_as_addressable concern and allow any ActiveRecord object to call it 9 | initializer 'effective_addresses.active_record' do |app| 10 | app.config.to_prepare do 11 | ActiveRecord::Base.extend(ActsAsAddressable::Base) 12 | end 13 | end 14 | 15 | # Set up our default configuration options. 16 | initializer 'effective_addresses.defaults', before: :load_config_initializers do |app| 17 | eval File.read("#{config.root}/config/effective_addresses.rb") 18 | end 19 | 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /test/dummy/app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, 6 | * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS 10 | * files in this directory. Styles in this file should be added after the last require_* statement. 11 | * It is generally better to create a new file per style scope. 12 | * 13 | *= require_tree . 14 | *= require_self 15 | */ 16 | -------------------------------------------------------------------------------- /test/dummy/config/application.rb: -------------------------------------------------------------------------------- 1 | require_relative "boot" 2 | 3 | require "rails/all" 4 | 5 | # Require the gems listed in Gemfile, including any gems 6 | # you've limited to :test, :development, or :production. 7 | Bundler.require(*Rails.groups) 8 | 9 | require 'devise' 10 | require "effective_test_bot" 11 | 12 | module Dummy 13 | class Application < Rails::Application 14 | config.load_defaults Rails::VERSION::STRING.to_f 15 | 16 | # Configuration for the application, engines, and railties goes here. 17 | # 18 | # These settings can be overridden in specific environments using the files 19 | # in config/environments, which are processed later. 20 | # 21 | # config.time_zone = "Central Time (US & Canada)" 22 | # config.eager_load_paths << Rails.root.join("extras") 23 | 24 | config.active_job.queue_adapter = :inline 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /app/assets/javascripts/effective_addresses/shipping_address_same_as_billing.js.coffee: -------------------------------------------------------------------------------- 1 | $(document).on 'change', "input[name$='[shipping_address][shipping_address_same_as_billing]']", (event) -> 2 | $obj = $(event.currentTarget) 3 | 4 | shipping_fields = $obj.closest('form').find(" 5 | div[class*='_shipping_address_full_name'], 6 | div[class*='_shipping_address_address1'], 7 | div[class*='_shipping_address_address2'], 8 | div[class*='_shipping_address_address3'], 9 | div[class*='_shipping_address_city'], 10 | div[class*='_shipping_address_country_code'], 11 | div[class*='_shipping_address_state_code'], 12 | div[class*='_shipping_address_postal_code'], 13 | div[class*='shipping_address_form_group'] 14 | ") 15 | 16 | if $obj.is(':checked') 17 | shipping_fields.hide().find('input,select').prop('disabled', true).prop('required', true) 18 | else 19 | shipping_fields.show().find('input,select').removeAttr('disabled').removeAttr('required') 20 | 21 | 22 | -------------------------------------------------------------------------------- /test/dummy/db/migrate/01_create_users.rb: -------------------------------------------------------------------------------- 1 | class CreateUsers < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :users do |t| 4 | # Devise 5 | t.string :encrypted_password, null: false, default: '' 6 | t.string :reset_password_token 7 | t.datetime :reset_password_sent_at 8 | t.datetime :remember_created_at 9 | t.integer :sign_in_count, default: 0, null: false 10 | t.datetime :current_sign_in_at 11 | t.datetime :last_sign_in_at 12 | t.string :current_sign_in_ip 13 | t.string :last_sign_in_ip 14 | t.datetime :confirmed_at 15 | t.datetime :confirmation_sent_at 16 | t.string :unconfirmed_email 17 | 18 | # User fields 19 | t.string :email, null: false, default: '' 20 | t.string :first_name 21 | t.string :last_name 22 | t.integer :roles_mask 23 | 24 | t.timestamps 25 | end 26 | 27 | add_index :users, :email, unique: true 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /test/dummy/config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # The following keys must be escaped otherwise they will not be retrieved by 20 | # the default I18n backend: 21 | # 22 | # true, false, on, off, yes, no 23 | # 24 | # Instead, surround them with single quotes. 25 | # 26 | # en: 27 | # 'true': 'foo' 28 | # 29 | # To learn more, please read the Rails Internationalization guide 30 | # available at https://guides.rubyonrails.org/i18n.html. 31 | 32 | en: 33 | hello: "Hello world" 34 | -------------------------------------------------------------------------------- /lib/generators/effective_addresses/install_generator.rb: -------------------------------------------------------------------------------- 1 | module EffectiveAddresses 2 | module Generators 3 | class InstallGenerator < Rails::Generators::Base 4 | include Rails::Generators::Migration 5 | 6 | desc 'Creates an EffectiveAddresses initializer in your application.' 7 | 8 | source_root File.expand_path('../../templates', __FILE__) 9 | 10 | def self.next_migration_number(dirname) 11 | if not ActiveRecord::Base.timestamped_migrations 12 | Time.new.utc.strftime("%Y%m%d%H%M%S") 13 | else 14 | "%.3d" % (current_migration_number(dirname) + 1) 15 | end 16 | end 17 | 18 | def copy_initializer 19 | template ('../' * 3) + 'config/effective_addresses.rb', 'config/initializers/effective_addresses.rb' 20 | end 21 | 22 | def create_migration_file 23 | migration_template ('../' * 3) + 'db/migrate/101_create_effective_addresses.rb', 'db/migrate/create_effective_addresses.rb' 24 | end 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2023 Code and Effect Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /test/dummy/bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "fileutils" 3 | 4 | # path to your application root. 5 | APP_ROOT = File.expand_path('..', __dir__) 6 | 7 | def system!(*args) 8 | system(*args) || abort("\n== Command #{args} failed ==") 9 | end 10 | 11 | FileUtils.chdir APP_ROOT do 12 | # This script is a way to set up or update your development environment automatically. 13 | # This script is idempotent, so that you can run it at any time and get an expectable outcome. 14 | # Add necessary setup steps to this file. 15 | 16 | puts '== Installing dependencies ==' 17 | system! 'gem install bundler --conservative' 18 | system('bundle check') || system!('bundle install') 19 | 20 | # puts "\n== Copying sample files ==" 21 | # unless File.exist?('config/database.yml') 22 | # FileUtils.cp 'config/database.yml.sample', 'config/database.yml' 23 | # end 24 | 25 | puts "\n== Preparing database ==" 26 | system! 'bin/rails db:prepare' 27 | 28 | puts "\n== Removing old logs and tempfiles ==" 29 | system! 'bin/rails log:clear tmp:clear' 30 | 31 | puts "\n== Restarting application server ==" 32 | system! 'bin/rails restart' 33 | end 34 | -------------------------------------------------------------------------------- /test/support/effective_addresses_test_builder.rb: -------------------------------------------------------------------------------- 1 | module EffectiveAddressesTestBuilder 2 | 3 | def build_effective_address(addressable: nil) 4 | address = Effective::Address.new( 5 | category: 'billing', 6 | address1: '123 Fake Street', 7 | city: 'Edmonton', 8 | country: 'CA', 9 | province: 'AB', 10 | postal_code: 'H0H0H0' 11 | ) 12 | 13 | address.assign_attributes(addressable: addressable || build_user) 14 | 15 | address 16 | end 17 | 18 | def build_user 19 | @user_index ||= 0 20 | @user_index += 1 21 | 22 | User.new( 23 | email: "user#{@user_index}@example.com", 24 | password: 'rubicon2020', 25 | password_confirmation: 'rubicon2020', 26 | first_name: 'Test', 27 | last_name: 'User' 28 | ) 29 | end 30 | 31 | def build_user_with_address 32 | user = build_user() 33 | 34 | user.addresses.build( 35 | addressable: user, 36 | category: 'billing', 37 | full_name: 'Test User', 38 | address1: '1234 Fake Street', 39 | city: 'Victoria', 40 | state_code: 'BC', 41 | country_code: 'CA', 42 | postal_code: 'H0H0H0' 43 | ) 44 | 45 | user.save! 46 | user 47 | end 48 | 49 | end 50 | -------------------------------------------------------------------------------- /test/dummy/config/storage.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: <%= Rails.root.join("tmp/storage") %> 4 | 5 | local: 6 | service: Disk 7 | root: <%= Rails.root.join("storage") %> 8 | 9 | # Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) 10 | # amazon: 11 | # service: S3 12 | # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> 13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> 14 | # region: us-east-1 15 | # bucket: your_own_bucket 16 | 17 | # Remember not to checkin your GCS keyfile to a repository 18 | # google: 19 | # service: GCS 20 | # project: your_project 21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> 22 | # bucket: your_own_bucket 23 | 24 | # Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) 25 | # microsoft: 26 | # service: AzureStorage 27 | # storage_account_name: your_account_name 28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> 29 | # container: your_container_name 30 | 31 | # mirror: 32 | # service: Mirror 33 | # primary: local 34 | # mirrors: [ amazon, google, microsoft ] 35 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # Configure Rails Environment 2 | ENV["RAILS_ENV"] = "test" 3 | 4 | require_relative "../test/dummy/config/environment" 5 | ActiveRecord::Migrator.migrations_paths = [File.expand_path("../test/dummy/db/migrate", __dir__)] 6 | ActiveRecord::Migrator.migrations_paths << File.expand_path('../db/migrate', __dir__) 7 | require "rails/test_help" 8 | 9 | # Filter out the backtrace from minitest while preserving the one from other libraries. 10 | Minitest.backtrace_filter = Minitest::BacktraceFilter.new 11 | 12 | # Load fixtures from the engine 13 | if ActiveSupport::TestCase.respond_to?(:fixture_path=) 14 | ActiveSupport::TestCase.fixture_path = File.expand_path("fixtures", __dir__) 15 | ActionDispatch::IntegrationTest.fixture_path = ActiveSupport::TestCase.fixture_path 16 | ActiveSupport::TestCase.file_fixture_path = ActiveSupport::TestCase.fixture_path + "/files" 17 | ActiveSupport::TestCase.fixtures :all 18 | end 19 | 20 | # Custom Test Helpers 21 | require 'support/effective_addresses_test_builder' 22 | require 'support/effective_addresses_test_helper' 23 | require 'pry-byebug' 24 | 25 | class ActiveSupport::TestCase 26 | include Warden::Test::Helpers 27 | 28 | # For stub_any_instance 29 | include EffectiveTestBot::DSL 30 | 31 | include EffectiveAddressesTestBuilder 32 | include EffectiveAddressesTestHelper 33 | end 34 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/content_security_policy.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Define an application-wide content security policy 4 | # For further information see the following documentation 5 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy 6 | 7 | # Rails.application.config.content_security_policy do |policy| 8 | # policy.default_src :self, :https 9 | # policy.font_src :self, :https, :data 10 | # policy.img_src :self, :https, :data 11 | # policy.object_src :none 12 | # policy.script_src :self, :https 13 | # policy.style_src :self, :https 14 | 15 | # # Specify URI for violation reports 16 | # # policy.report_uri "/csp-violation-report-endpoint" 17 | # end 18 | 19 | # If you are using UJS then enable automatic nonce generation 20 | # Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } 21 | 22 | # Set the nonce only to specific directives 23 | # Rails.application.config.content_security_policy_nonce_directives = %w(script-src) 24 | 25 | # Report CSP violations to a specified URI 26 | # For further information see the following documentation: 27 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only 28 | # Rails.application.config.content_security_policy_report_only = true 29 | -------------------------------------------------------------------------------- /effective_addresses.gemspec: -------------------------------------------------------------------------------- 1 | $:.push File.expand_path('../lib', __FILE__) 2 | 3 | # Maintain your gem's version: 4 | require 'effective_addresses/version' 5 | 6 | # Describe your gem and declare its dependencies: 7 | Gem::Specification.new do |s| 8 | s.name = 'effective_addresses' 9 | s.version = EffectiveAddresses::VERSION 10 | s.authors = ['Code and Effect'] 11 | s.email = ['info@codeandeffect.com'] 12 | s.homepage = 'https://github.com/code-and-effect/effective_addresses' 13 | s.summary = 'Extend any ActiveRecord object to have one or more named addresses. Includes a geographic region-aware custom form input backed by Carmen.' 14 | s.description = 'Extend any ActiveRecord object to have one or more named addresses. Includes a geographic region-aware custom form input backed by Carmen.' 15 | s.licenses = ['MIT'] 16 | 17 | s.files = Dir['{app,config,db,lib}/**/*'] + ['MIT-LICENSE', 'README.md'] 18 | 19 | s.add_dependency 'rails' 20 | s.add_dependency 'effective_resources' 21 | s.add_dependency 'carmen' 22 | s.add_dependency 'coffee-rails' 23 | 24 | s.add_development_dependency 'sqlite3' 25 | s.add_development_dependency 'devise' 26 | s.add_development_dependency 'pry-byebug' 27 | s.add_development_dependency 'effective_test_bot' 28 | s.add_development_dependency 'effective_developer' # Optional but suggested 29 | s.add_development_dependency 'psych', '< 4' 30 | end 31 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 # use CircleCI 2.1 2 | 3 | # Orbs and containers control the docker image each job is run in. 4 | orbs: 5 | ruby: circleci/ruby@2.0.1 6 | browser-tools: circleci/browser-tools@1.4.3 7 | 8 | container: &container 9 | docker: 10 | - image: cimg/ruby:3.1.2-browsers # images: https://hub.docker.com/r/circleci/ruby/tags 11 | environment: 12 | RAILS_ENV: test 13 | - image: cimg/postgres:15.1 14 | 15 | workflows: 16 | version: 2 17 | test: 18 | jobs: 19 | - test 20 | 21 | jobs: 22 | test: 23 | <<: *container 24 | steps: 25 | - checkout 26 | 27 | - run: 28 | name: Configure Bundler 29 | command: | 30 | echo 'export BUNDLER_VERSION=$(cat Gemfile.lock | tail -1 | tr -d " ")' >> $BASH_ENV 31 | source $BASH_ENV 32 | gem install bundler 33 | 34 | - restore_cache: 35 | key: effective-gem-{{ checksum "Gemfile.lock" }} 36 | 37 | - run: 38 | name: Install Bundle 39 | command: | 40 | bundle install --jobs=4 --retry=3 41 | 42 | - save_cache: 43 | key: effective-gem-{{ checksum "Gemfile.lock" }} 44 | paths: 45 | - ./vendor/bundle 46 | 47 | - run: 48 | name: Run Unit Tests 49 | command: bundle exec rails test 50 | 51 | - run: 52 | name: All Tests Passed 53 | command: echo "All Tests Passed" 54 | -------------------------------------------------------------------------------- /test/dummy/db/migrate/03_create_active_storage_tables.active_storage.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from active_storage (originally 20170806125915) 2 | class CreateActiveStorageTables < ActiveRecord::Migration[5.2] 3 | def change 4 | create_table :active_storage_blobs do |t| 5 | t.string :key, null: false 6 | t.string :filename, null: false 7 | t.string :content_type 8 | t.text :metadata 9 | t.string :service_name, null: false 10 | t.bigint :byte_size, null: false 11 | t.string :checksum, null: false 12 | t.datetime :created_at, null: false 13 | 14 | t.index [ :key ], unique: true 15 | end 16 | 17 | create_table :active_storage_attachments do |t| 18 | t.string :name, null: false 19 | t.references :record, null: false, polymorphic: true, index: false 20 | t.references :blob, null: false 21 | 22 | t.datetime :created_at, null: false 23 | 24 | t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true 25 | t.foreign_key :active_storage_blobs, column: :blob_id 26 | end 27 | 28 | create_table :active_storage_variant_records do |t| 29 | t.belongs_to :blob, null: false, index: false 30 | t.string :variation_digest, null: false 31 | 32 | t.index %i[ blob_id variation_digest ], name: "index_active_storage_variant_records_uniqueness", unique: true 33 | t.foreign_key :active_storage_blobs, column: :blob_id 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /config/effective_addresses.rb: -------------------------------------------------------------------------------- 1 | EffectiveAddresses.setup do |config| 2 | # Display Full Name on Address forms, and validate presence by default 3 | # (can be overridden on a per address basis) 4 | config.use_full_name = true 5 | 6 | # A 3rd address field 7 | config.use_address3 = false 8 | 9 | # Country codes to display in country_select dropdowns. 10 | config.country_codes = :all 11 | #config.country_codes = ['US', 'CA'] # Or you can be more selective... 12 | 13 | # Select these countries ontop of the others 14 | # config.country_codes_priority = ['US', 'CA'] 15 | 16 | # Force this country to be preselected on any new address forms. 17 | # Valid values are: country code, country name, or nil. 18 | # Leave nil if using Geocoder for IP based discovery. 19 | config.pre_selected_country = nil 20 | 21 | # Force this state to be preselected on any new address forms. 22 | # Must also define pre_selected_country for this to take affect 23 | # Valid values are: state code, state name, or nil. 24 | # Leave nil if using Geocoder for IP based discovery. 25 | config.pre_selected_state = nil 26 | 27 | # Validate that the postal/zip code format is correct for these countries 28 | # Right now, only US and Canada are supported 29 | config.validate_postal_code_format = ['US', 'CA'] 30 | 31 | # SimpleForm Options 32 | # This Hash of options will be passed into any simple_form_for() calls 33 | config.simple_form_options = {} 34 | 35 | # config.simple_form_options = { 36 | # :html => {:class => ['form-horizontal']}, 37 | # :wrapper => :horizontal_form, 38 | # :wrapper_mappings => { 39 | # :boolean => :horizontal_boolean, 40 | # :check_boxes => :horizontal_radio_and_checkboxes, 41 | # :radio_buttons => :horizontal_radio_and_checkboxes 42 | # } 43 | # } 44 | end 45 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/effective_addresses.rb: -------------------------------------------------------------------------------- 1 | EffectiveAddresses.setup do |config| 2 | # Display Full Name on Address forms, and validate presence by default 3 | # (can be overridden on a per address basis) 4 | config.use_full_name = true 5 | 6 | # A 3rd address field 7 | config.use_address3 = false 8 | 9 | # Country codes to display in country_select dropdowns. 10 | config.country_codes = :all 11 | #config.country_codes = ['US', 'CA'] # Or you can be more selective... 12 | 13 | # Select these countries ontop of the others 14 | # config.country_codes_priority = ['US', 'CA'] 15 | 16 | # Force this country to be preselected on any new address forms. 17 | # Valid values are: country code, country name, or nil. 18 | # Leave nil if using Geocoder for IP based discovery. 19 | config.pre_selected_country = nil 20 | 21 | # Force this state to be preselected on any new address forms. 22 | # Must also define pre_selected_country for this to take affect 23 | # Valid values are: state code, state name, or nil. 24 | # Leave nil if using Geocoder for IP based discovery. 25 | config.pre_selected_state = nil 26 | 27 | # Validate that the postal/zip code format is correct for these countries 28 | # Right now, only US and Canada are supported 29 | config.validate_postal_code_format = ['US', 'CA'] 30 | 31 | # SimpleForm Options 32 | # This Hash of options will be passed into any simple_form_for() calls 33 | config.simple_form_options = {} 34 | 35 | # config.simple_form_options = { 36 | # :html => {:class => ['form-horizontal']}, 37 | # :wrapper => :horizontal_form, 38 | # :wrapper_mappings => { 39 | # :boolean => :horizontal_boolean, 40 | # :check_boxes => :horizontal_radio_and_checkboxes, 41 | # :radio_buttons => :horizontal_radio_and_checkboxes 42 | # } 43 | # } 44 | end 45 | -------------------------------------------------------------------------------- /test/dummy/public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

We're sorry, but something went wrong.

62 |
63 |

If you are the application owner check the logs for more information.

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /test/dummy/config/puma.rb: -------------------------------------------------------------------------------- 1 | # Puma can serve each request in a thread from an internal thread pool. 2 | # The `threads` method setting takes two numbers: a minimum and maximum. 3 | # Any libraries that use thread pools should be configured to match 4 | # the maximum value specified for Puma. Default is set to 5 threads for minimum 5 | # and maximum; this matches the default thread size of Active Record. 6 | # 7 | max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } 8 | min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } 9 | threads min_threads_count, max_threads_count 10 | 11 | # Specifies the `worker_timeout` threshold that Puma will use to wait before 12 | # terminating a worker in development environments. 13 | # 14 | worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development" 15 | 16 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000. 17 | # 18 | port ENV.fetch("PORT") { 3000 } 19 | 20 | # Specifies the `environment` that Puma will run in. 21 | # 22 | environment ENV.fetch("RAILS_ENV") { "development" } 23 | 24 | # Specifies the `pidfile` that Puma will use. 25 | pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } 26 | 27 | # Specifies the number of `workers` to boot in clustered mode. 28 | # Workers are forked web server processes. If using threads and workers together 29 | # the concurrency of the application would be max `threads` * `workers`. 30 | # Workers do not work on JRuby or Windows (both of which do not support 31 | # processes). 32 | # 33 | # workers ENV.fetch("WEB_CONCURRENCY") { 2 } 34 | 35 | # Use the `preload_app!` method when specifying a `workers` number. 36 | # This directive tells Puma to first boot the application and load code 37 | # before forking the application. This takes advantage of Copy On Write 38 | # process behavior so workers use less memory. 39 | # 40 | # preload_app! 41 | 42 | # Allow puma to be restarted by `rails restart` command. 43 | plugin :tmp_restart 44 | -------------------------------------------------------------------------------- /test/dummy/public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The change you wanted was rejected.

62 |

Maybe you tried to change something you didn't have access to.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /test/dummy/public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The page you were looking for doesn't exist.

62 |

You may have mistyped the address or the page may have moved.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /test/support/effective_addresses_test_helper.rb: -------------------------------------------------------------------------------- 1 | module EffectiveAddressesTestHelper 2 | 3 | def sign_in(user = create_user!) 4 | login_as(user, scope: :user); user 5 | end 6 | 7 | def as_user(user, &block) 8 | sign_in(user); yield; logout(:user) 9 | end 10 | 11 | def with_time_travel(date, &block) 12 | begin 13 | Timecop.travel(date); yield 14 | ensure 15 | Timecop.return 16 | end 17 | end 18 | 19 | # assert_email :new_user_sign_up 20 | # assert_email :new_user_sign_up, to: 'newuser@example.com' 21 | # assert_email from: 'admin@example.com' 22 | def assert_email(action = nil, to: nil, from: nil, subject: nil, body: nil, message: nil, count: nil, &block) 23 | retval = nil 24 | 25 | if block_given? 26 | before = ActionMailer::Base.deliveries.length 27 | retval = yield 28 | 29 | difference = (ActionMailer::Base.deliveries.length - before) 30 | 31 | if count.present? 32 | assert (difference == count), "(assert_email) Expected #{count} email to have been delivered, but #{difference} were instead" 33 | else 34 | assert (difference > 0), "(assert_email) Expected at least one email to have been delivered" 35 | end 36 | end 37 | 38 | if (action || to || from || subject || body).nil? 39 | assert ActionMailer::Base.deliveries.present?, message || "(assert_email) Expected email to have been delivered" 40 | return retval 41 | end 42 | 43 | actions = ActionMailer::Base.instance_variable_get(:@mailer_actions) 44 | 45 | ActionMailer::Base.deliveries.each do |message| 46 | matches = true 47 | 48 | matches &&= (actions.include?(action.to_s)) if action 49 | matches &&= (Array(message.to).include?(to)) if to 50 | matches &&= (Array(message.from).include?(from)) if from 51 | matches &&= (message.subject == subject) if subject 52 | matches &&= (message.body == body) if body 53 | 54 | return retval if matches 55 | end 56 | 57 | expected = [ 58 | ("action: #{action}" if action), 59 | ("to: #{to}" if to), 60 | ("from: {from}" if from), 61 | ("subject: #{subject}" if subject), 62 | ("body: #{body}" if body), 63 | ].compact.to_sentence 64 | 65 | assert false, message || "(assert_email) Expected email with #{expected} to have been delivered" 66 | end 67 | 68 | end 69 | -------------------------------------------------------------------------------- /app/assets/javascripts/effective_addresses/address_fields.js.coffee: -------------------------------------------------------------------------------- 1 | loadSubregions = ($countrySelect, clearPostalCode = false) -> 2 | $.each $countrySelect, (index, countrySelector) -> 3 | $particularCountrySelect = $(countrySelector) 4 | countryCode = $particularCountrySelect.val() 5 | uuid = $particularCountrySelect.data('effective-address-country') 6 | 7 | $nestedFields = $particularCountrySelect.closest('.nested-fields') 8 | $form = $particularCountrySelect.closest('form') 9 | 10 | $container = if $nestedFields.length == 0 then $form else $nestedFields 11 | 12 | # clear postal_code values on country change if it is turned on 13 | $container.find("input[data-effective-address-postal-code='#{uuid}']").val('') if clearPostalCode 14 | 15 | # load state options 16 | url = "/addresses/subregions/#{countryCode}" 17 | $stateSelect = $container.find("select[data-effective-address-state='#{uuid}']:first") 18 | 19 | if countryCode.length == 0 20 | $stateSelect.prop('disabled', true).addClass('disabled').parent('.form-group').addClass('disabled').find('label').addClass('disabled') 21 | reinitialize($stateSelect, 'Please choose country first') 22 | else 23 | $stateSelect.removeAttr('disabled').parent('.form-group').removeClass('disabled').find('.disabled').removeClass('disabled') 24 | reinitialize($stateSelect, 'Loading...') 25 | 26 | $stateSelect.load url, -> 27 | stateSelectAvailable = $(@).find('option:last').val().length > 0 28 | if stateSelectAvailable 29 | $(@).prop('required', true) 30 | $(@).removeAttr('disabled') 31 | reinitialize($stateSelect, 'Please choose', true) 32 | else 33 | $(@).removeAttr('required') 34 | $(@).prop('disabled', true) 35 | reinitialize($stateSelect, 'None exist', true) 36 | 37 | $(document).on 'change', 'select[data-effective-address-country]', -> loadSubregions($(@), true) 38 | 39 | reinitialize = ($stateSelect, placeholder, keepOptions = false) -> 40 | if $stateSelect.hasClass('effective_select') == false 41 | $stateSelect.html("") unless keepOptions 42 | return 43 | 44 | $stateSelect.html('') unless keepOptions 45 | 46 | opts = $stateSelect.data('input-js-options') 47 | opts['placeholder'] = placeholder 48 | $stateSelect.data('input-js-options', opts) 49 | 50 | $stateSelect.select2().trigger('select2:reinitialize') 51 | -------------------------------------------------------------------------------- /test/dummy/config/environments/test.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | # The test environment is used exclusively to run your application's 4 | # test suite. You never need to work with it otherwise. Remember that 5 | # your test database is "scratch space" for the test suite and is wiped 6 | # and recreated between test runs. Don't rely on the data there! 7 | 8 | Rails.application.configure do 9 | # Settings specified here will take precedence over those in config/application.rb. 10 | 11 | config.cache_classes = true 12 | 13 | # Do not eager load code on boot. This avoids loading your whole application 14 | # just for the purpose of running a single test. If you are using a tool that 15 | # preloads Rails for running tests, you may have to set it to true. 16 | config.eager_load = false 17 | 18 | # Configure public file server for tests with Cache-Control for performance. 19 | config.public_file_server.enabled = true 20 | config.public_file_server.headers = { 21 | 'Cache-Control' => "public, max-age=#{1.hour.to_i}" 22 | } 23 | 24 | # Show full error reports and disable caching. 25 | config.consider_all_requests_local = true 26 | config.action_controller.perform_caching = false 27 | config.cache_store = :null_store 28 | 29 | # Raise exceptions instead of rendering exception templates. 30 | config.action_dispatch.show_exceptions = false 31 | 32 | # Disable request forgery protection in test environment. 33 | config.action_controller.allow_forgery_protection = false 34 | 35 | # Store uploaded files on the local file system in a temporary directory. 36 | config.active_storage.service = :test 37 | 38 | config.action_mailer.perform_caching = false 39 | 40 | # Tell Action Mailer not to deliver emails to the real world. 41 | # The :test delivery method accumulates sent emails in the 42 | # ActionMailer::Base.deliveries array. 43 | config.action_mailer.delivery_method = :test 44 | 45 | # Print deprecation notices to the stderr. 46 | config.active_support.deprecation = :stderr 47 | 48 | # Raise exceptions for disallowed deprecations. 49 | config.active_support.disallowed_deprecation = :raise 50 | 51 | # Tell Active Support which deprecation messages to disallow. 52 | config.active_support.disallowed_deprecation_warnings = [] 53 | 54 | # Raises error for missing translations. 55 | # config.i18n.raise_on_missing_translations = true 56 | 57 | # Annotate rendered view with file names. 58 | # config.action_view.annotate_rendered_view_with_filenames = true 59 | 60 | config.action_mailer.default_url_options = { host: 'http://localhost', port: 3000 } 61 | end 62 | -------------------------------------------------------------------------------- /app/views/effective/addresses/_formtastic.html.haml: -------------------------------------------------------------------------------- 1 | = f.semantic_fields_for method, (address || f.object.send(method) || f.object.addresses.build(:category => method.to_s.gsub('_address', ''))) do |fa| 2 | - uuid = fa.object_id 3 | - method = method.to_sym 4 | 5 | - if ((f.object.errors.include?(method) && !f.object.errors.include?(:addresses)) rescue false) 6 | - fa.object.errors.add(:address1, f.object.errors[method].first) 7 | 8 | - field_order.each do |field| 9 | 10 | - case field 11 | - when :full_name 12 | - if local_assigns[:use_full_name] || EffectiveAddresses.use_full_name || fa.object.errors.include?(:full_name) 13 | = fa.input :full_name, :required => true, :label => 'Full name', :placeholder => 'Full name' 14 | 15 | - when :address1 16 | = fa.input :address1, :placeholder => 'Address', :label => "Address" 17 | 18 | - when :address2 19 | = fa.input :address2, :label => false 20 | 21 | - when :address3 22 | = fa.input :address3, :label => false 23 | 24 | - when :city 25 | = fa.input :city, :placeholder => 'City' 26 | 27 | - when :country_code 28 | = fa.input :country_code, 29 | :as => (defined?(EffectiveFormInputs) ? :effective_select : :select), 30 | :label => 'Country', 31 | :prompt => 'Country...', 32 | :collection => options_for_select(effective_address_regions_collection()), 33 | :input_html => { 'data-effective-address-country' => uuid }, 34 | :input_js => { placeholder: 'Please choose' } 35 | 36 | - when :state_code 37 | - if fa.object.country_code.present? 38 | = fa.input :state_code, 39 | :as => (defined?(EffectiveFormInputs) ? :effective_select : :select), 40 | :label => 'Province / State', 41 | :collection => options_for_select(effective_address_regions_collection(Carmen::Country.coded(fa.object.country_code).try(:subregions))), 42 | :prompt => 'please select a country', 43 | :input_html => { 'data-effective-address-state' => uuid }, 44 | :input_js => { :placeholder => 'Please choose' } 45 | - else 46 | = fa.input :state_code, 47 | :as => (defined?(EffectiveFormInputs) ? :effective_select : :select), 48 | :label => 'Province / State', 49 | :collection => [], 50 | :prompt => 'please select a country', 51 | :input_html => {:disabled => 'disabled', 'data-effective-address-state' => uuid}, 52 | :input_js => { :placeholder => 'Please choose country first' } 53 | 54 | - when :postal_code 55 | = fa.input :postal_code, :label => 'Postal / Zip code', :placeholder => 'Postal / Zip code' 56 | -------------------------------------------------------------------------------- /test/dummy/config/environments/development.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | Rails.application.configure do 4 | # Settings specified here will take precedence over those in config/application.rb. 5 | 6 | # In the development environment your application's code is reloaded any time 7 | # it changes. This slows down response time but is perfect for development 8 | # since you don't have to restart the web server when you make code changes. 9 | config.cache_classes = false 10 | 11 | # Do not eager load code on boot. 12 | config.eager_load = false 13 | 14 | # Show full error reports. 15 | config.consider_all_requests_local = true 16 | 17 | # Enable/disable caching. By default caching is disabled. 18 | # Run rails dev:cache to toggle caching. 19 | if Rails.root.join('tmp', 'caching-dev.txt').exist? 20 | config.action_controller.perform_caching = true 21 | config.action_controller.enable_fragment_cache_logging = true 22 | 23 | config.cache_store = :memory_store 24 | config.public_file_server.headers = { 25 | 'Cache-Control' => "public, max-age=#{2.days.to_i}" 26 | } 27 | else 28 | config.action_controller.perform_caching = false 29 | 30 | config.cache_store = :null_store 31 | end 32 | 33 | # Store uploaded files on the local file system (see config/storage.yml for options). 34 | config.active_storage.service = :local 35 | 36 | # Don't care if the mailer can't send. 37 | config.action_mailer.raise_delivery_errors = false 38 | 39 | config.action_mailer.perform_caching = false 40 | 41 | # Print deprecation notices to the Rails logger. 42 | config.active_support.deprecation = :log 43 | 44 | # Raise exceptions for disallowed deprecations. 45 | config.active_support.disallowed_deprecation = :raise 46 | 47 | # Tell Active Support which deprecation messages to disallow. 48 | config.active_support.disallowed_deprecation_warnings = [] 49 | 50 | # Raise an error on page load if there are pending migrations. 51 | config.active_record.migration_error = :page_load 52 | 53 | # Highlight code that triggered database queries in logs. 54 | config.active_record.verbose_query_logs = true 55 | 56 | # Debug mode disables concatenation and preprocessing of assets. 57 | # This option may cause significant delays in view rendering with a large 58 | # number of complex assets. 59 | config.assets.debug = true 60 | 61 | # Suppress logger output for asset requests. 62 | config.assets.quiet = true 63 | 64 | # Raises error for missing translations. 65 | # config.i18n.raise_on_missing_translations = true 66 | 67 | # Annotate rendered view with file names. 68 | # config.action_view.annotate_rendered_view_with_filenames = true 69 | 70 | # Use an evented file watcher to asynchronously detect changes in source code, 71 | # routes, locales, etc. This feature depends on the listen gem. 72 | # config.file_watcher = ActiveSupport::EventedFileUpdateChecker 73 | 74 | # Uncomment if you wish to allow Action Cable access from any origin. 75 | # config.action_cable.disable_request_forgery_protection = true 76 | end 77 | -------------------------------------------------------------------------------- /app/views/effective/addresses/_form_with.html.haml: -------------------------------------------------------------------------------- 1 | = f.fields_for method, (address || f.object.send(method) || f.object.addresses.build(category: method.to_s.gsub('_address', ''))) do |fa| 2 | - uuid = fa.object_id 3 | - method = method.to_sym 4 | - same_as_billing = (fa.object.category == 'shipping') && f.object.try(:shipping_address_same_as_billing?) 5 | - required = (required && !same_as_billing) 6 | - wrapper_options = { class: "form-group #{method}_form_group", style: ('display: none;' if same_as_billing) } 7 | 8 | - if ((f.object.errors.include?(method) && !f.object.errors.include?(:addresses)) rescue false) 9 | = f.errors method 10 | 11 | - if fa.object.category == 'shipping' && f.object.respond_to?(:shipping_address_same_as_billing?) 12 | = fa.check_box :shipping_address_same_as_billing, 13 | label: 'Shipping address is same as billing address', 14 | required: false, 15 | feedback: false, 16 | input_html: { checked: same_as_billing } 17 | 18 | - if local_assigns[:use_full_name] || EffectiveAddresses.use_full_name || fa.object.errors.include?(:full_name) 19 | = fa.text_field :full_name, 20 | required: required, 21 | disabled: same_as_billing, 22 | wrapper: wrapper_options 23 | 24 | = fa.text_field :address1, 25 | label: (local_assigns[:label] || method.to_s.titleize), 26 | required: required, 27 | disabled: same_as_billing, 28 | wrapper: wrapper_options 29 | 30 | = fa.text_field :address2, 31 | label: false, 32 | required: false, 33 | disabled: same_as_billing, 34 | wrapper: wrapper_options 35 | 36 | - if EffectiveAddresses.use_address3 37 | = fa.text_field :address3, 38 | label: false, 39 | required: false, 40 | disabled: same_as_billing, 41 | wrapper: wrapper_options 42 | 43 | = fa.text_field :city, 44 | required: required, 45 | disabled: same_as_billing, 46 | input_html: { 'data-effective-address-city' => uuid }, 47 | wrapper: wrapper_options 48 | 49 | .row 50 | .col-md-4 51 | = fa.select :country_code, effective_address_regions_collection(resource: fa.object), 52 | label: 'Country', 53 | required: required, 54 | disabled: same_as_billing, 55 | input_html: { 'data-effective-address-country' => uuid }, 56 | wrapper: wrapper_options 57 | 58 | .col-md-5 59 | - subregions = Carmen::Country.coded(fa.object.country_code).try(:subregions) if fa.object.country_code.present? 60 | 61 | - if subregions.present? 62 | = fa.select :state_code, effective_address_regions_collection(subregions), 63 | label: 'State / Province', 64 | required: required, 65 | disabled: same_as_billing, 66 | input_html: { 'data-effective-address-state' => uuid }, 67 | wrapper: wrapper_options 68 | - else 69 | = fa.select :state_code, [], 70 | label: 'State / Province', 71 | required: required, 72 | disabled: true, 73 | input_html: { 'data-effective-address-state' => uuid }, 74 | input_js: { placeholder: 'Please choose country first' }, 75 | wrapper: wrapper_options 76 | 77 | .col-md-3 78 | = fa.text_field :postal_code, 79 | label: 'Postal Code', 80 | required: required, 81 | disabled: same_as_billing, 82 | input_html: { 'data-effective-address-postal-code' => uuid }, 83 | wrapper: wrapper_options 84 | -------------------------------------------------------------------------------- /app/helpers/effective_addresses_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module EffectiveAddressesHelper 4 | def effective_address_fields(form, method = 'billing', options = {}) 5 | method = (method.to_s.include?('_address') ? method.to_s : "#{method}_address") 6 | 7 | required = (form.object._validators[method.to_sym].any? { |v| v.kind_of?(ActiveRecord::Validations::PresenceValidator) && (v.options[:if].blank? || (v.options[:if].respond_to?(:call) ? f.object.instance_exec(&v.options[:if]) : v.options[:if])) } rescue true) 8 | 9 | address = form.object.send(method) || form.object.addresses.build(category: method.to_s.gsub('_address', '')) 10 | 11 | effective_address_pre_select(address) if address.new_record? 12 | 13 | opts = { required: required, field_order: [:full_name, :address1, :address2, :city, :country_code, :state_code, :postal_code] }.merge(options).merge({:f => form, :address => address, :method => method}) 14 | 15 | case form.class.name 16 | when 'Effective::FormBuilder' 17 | render partial: 'effective/addresses/form_with', locals: opts 18 | when 'Effective::TableBuilder' 19 | form.effective_address(method, options) 20 | when 'SimpleForm::FormBuilder' 21 | render partial: 'effective/addresses/simple_form', locals: opts 22 | when 'Formtastic::FormBuilder' 23 | render partial: 'effective/addresses/formtastic', locals: opts 24 | else 25 | raise 'Unsupported FormBuilder. You must use formtastic, simpleform or effective_bootstrap. Sorry.' 26 | end 27 | end 28 | 29 | def effective_address_pre_select(address) 30 | if address.country.blank? && EffectiveAddresses.pre_selected_country.present? 31 | address.country = EffectiveAddresses.pre_selected_country 32 | end 33 | 34 | if address.state.blank? && EffectiveAddresses.pre_selected_state.present? 35 | address.state = EffectiveAddresses.pre_selected_state 36 | end 37 | 38 | if defined?(Geocoder) && request.try(:location).present? 39 | location = request.location 40 | address.country = location.country_code 41 | address.state = location.state_code 42 | address.postal_code = location.postal_code 43 | address.city = location.city 44 | end 45 | 46 | address 47 | end 48 | 49 | def effective_address_regions_collection(regions = nil, resource: nil) 50 | countries = if regions.present? 51 | regions 52 | elsif EffectiveAddresses.country_codes == :all 53 | Carmen::Country.all 54 | else 55 | Carmen::Country.all.select { |c| (EffectiveAddresses.country_codes || []).include?(c.code) } 56 | end 57 | 58 | if regions.blank? && EffectiveAddresses.country_codes_priority.present? 59 | countries = countries.reject { |c| EffectiveAddresses.country_codes_priority.include?(c.code) } 60 | end 61 | 62 | countries = countries.map { |c| [c.name, c.code] }.sort! { |a, b| a.first <=> b.first } 63 | 64 | if regions.blank? && EffectiveAddresses.country_codes_priority.present? 65 | priorities = EffectiveAddresses.country_codes_priority.map do |code| 66 | country = Carmen::Country.coded(code) 67 | [country.name, country.code] 68 | end 69 | 70 | unless EffectiveAddresses.country_codes.kind_of?(Array) 71 | priorities << ['-------------------', '-', disabled: :disabled] 72 | end 73 | 74 | countries.unshift(*priorities) 75 | end 76 | 77 | # Special behaviour if the address has CAN, we treat it as CA 78 | if regions.blank? && resource.present? && resource.country_code == 'CAN' 79 | ca = countries.index { |_, code| code == 'CA' } 80 | 81 | if ca.present? 82 | countries[ca] = ['Canada', 'CAN'] 83 | end 84 | end 85 | 86 | countries 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /test/dummy/db/schema.rb: -------------------------------------------------------------------------------- 1 | # This file is auto-generated from the current state of the database. Instead 2 | # of editing this file, please use the migrations feature of Active Record to 3 | # incrementally modify your database, and then regenerate this schema definition. 4 | # 5 | # This file is the source Rails uses to define your schema when running `bin/rails 6 | # db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to 7 | # be faster and is potentially less error prone than running all of your 8 | # migrations from scratch. Old migrations may fail to apply correctly if those 9 | # migrations use external dependencies or application code. 10 | # 11 | # It's strongly recommended that you check this file into your version control system. 12 | 13 | ActiveRecord::Schema.define(version: 101) do 14 | 15 | create_table "action_text_rich_texts", force: :cascade do |t| 16 | t.string "name", null: false 17 | t.text "body" 18 | t.string "record_type", null: false 19 | t.integer "record_id", null: false 20 | t.datetime "created_at", precision: 6, null: false 21 | t.datetime "updated_at", precision: 6, null: false 22 | t.index ["record_type", "record_id", "name"], name: "index_action_text_rich_texts_uniqueness", unique: true 23 | end 24 | 25 | create_table "active_storage_attachments", force: :cascade do |t| 26 | t.string "name", null: false 27 | t.string "record_type", null: false 28 | t.integer "record_id", null: false 29 | t.integer "blob_id", null: false 30 | t.datetime "created_at", null: false 31 | t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" 32 | t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true 33 | end 34 | 35 | create_table "active_storage_blobs", force: :cascade do |t| 36 | t.string "key", null: false 37 | t.string "filename", null: false 38 | t.string "content_type" 39 | t.text "metadata" 40 | t.string "service_name", null: false 41 | t.bigint "byte_size", null: false 42 | t.string "checksum", null: false 43 | t.datetime "created_at", null: false 44 | t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true 45 | end 46 | 47 | create_table "active_storage_variant_records", force: :cascade do |t| 48 | t.integer "blob_id", null: false 49 | t.string "variation_digest", null: false 50 | t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true 51 | end 52 | 53 | create_table "addresses", force: :cascade do |t| 54 | t.string "addressable_type" 55 | t.integer "addressable_id" 56 | t.string "category", limit: 64 57 | t.string "full_name" 58 | t.string "address1" 59 | t.string "address2" 60 | t.string "address3" 61 | t.string "city" 62 | t.string "state_code" 63 | t.string "country_code" 64 | t.string "postal_code" 65 | t.datetime "updated_at" 66 | t.datetime "created_at" 67 | t.index ["addressable_id"], name: "index_addresses_on_addressable_id" 68 | t.index ["addressable_type", "addressable_id"], name: "index_addresses_on_addressable_type_and_addressable_id" 69 | end 70 | 71 | create_table "users", force: :cascade do |t| 72 | t.string "encrypted_password", default: "", null: false 73 | t.string "reset_password_token" 74 | t.datetime "reset_password_sent_at" 75 | t.datetime "remember_created_at" 76 | t.integer "sign_in_count", default: 0, null: false 77 | t.datetime "current_sign_in_at" 78 | t.datetime "last_sign_in_at" 79 | t.string "current_sign_in_ip" 80 | t.string "last_sign_in_ip" 81 | t.datetime "confirmed_at" 82 | t.datetime "confirmation_sent_at" 83 | t.string "unconfirmed_email" 84 | t.string "email", default: "", null: false 85 | t.string "first_name" 86 | t.string "last_name" 87 | t.integer "roles_mask" 88 | t.datetime "created_at", precision: 6, null: false 89 | t.datetime "updated_at", precision: 6, null: false 90 | t.index ["email"], name: "index_users_on_email", unique: true 91 | end 92 | 93 | add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" 94 | add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" 95 | end 96 | -------------------------------------------------------------------------------- /app/views/effective/addresses/_simple_form.html.haml: -------------------------------------------------------------------------------- 1 | = f.simple_fields_for method, (address || f.object.send(method) || f.object.addresses.build(:category => method.to_s.gsub('_address', ''))), (EffectiveAddresses.simple_form_options || {}) do |fa| 2 | - uuid = fa.object_id 3 | - method = method.to_sym 4 | - shipping_address_same_as_billing = (fa.object.category == 'shipping') && (f.object.try(:shipping_address_same_as_billing?) || false) 5 | 6 | - if ((f.object.errors.include?(method) && !f.object.errors.include?(:addresses)) rescue false) 7 | - fa.object.errors.add(:address1, f.object.errors[method].first) 8 | 9 | - if fa.object.category == 'shipping' && f.object.respond_to?(:shipping_address_same_as_billing?) 10 | = fa.input :shipping_address_same_as_billing, 11 | as: :boolean, 12 | label: 'Shipping address is same as billing address', 13 | required: false, 14 | input_html: { checked: shipping_address_same_as_billing } 15 | 16 | - field_order.each do |field| 17 | 18 | - case field 19 | - when :full_name 20 | - if local_assigns[:use_full_name] || EffectiveAddresses.use_full_name || fa.object.errors.include?(:full_name) 21 | = fa.input :full_name, 22 | required: required, 23 | disabled: shipping_address_same_as_billing, 24 | wrapper_html: { style: ('display: none;' if shipping_address_same_as_billing) } 25 | 26 | - when :address1 27 | = fa.input :address1, 28 | label: 'Address', 29 | required: required, 30 | disabled: shipping_address_same_as_billing, 31 | wrapper_html: { style: ('display: none;' if shipping_address_same_as_billing) } 32 | 33 | - when :address2 34 | = fa.input :address2, 35 | label: (Array((f.options[:html] || {})[:class]).flatten.include?('form-horizontal') ? ' '.html_safe : false), 36 | required: false, 37 | disabled: shipping_address_same_as_billing, 38 | wrapper_html: { style: ('display: none;' if shipping_address_same_as_billing) } 39 | 40 | - when :city 41 | = fa.input :city, 42 | required: required, 43 | input_html: { 'data-effective-address-city' => uuid }, 44 | disabled: shipping_address_same_as_billing, 45 | wrapper_html: { style: ('display: none;' if shipping_address_same_as_billing) } 46 | 47 | - when :country_code 48 | = fa.input :country_code, 49 | as: (defined?(EffectiveFormInputs) ? :effective_select : :select), 50 | required: required, 51 | collection: effective_address_regions_collection(), 52 | input_html: {'data-effective-address-country' => uuid}, 53 | disabled: shipping_address_same_as_billing, 54 | wrapper_html: { style: ('display: none;' if shipping_address_same_as_billing) } 55 | 56 | - when :state_code 57 | - if fa.object.try(:country_code).present? 58 | = fa.input :state_code, 59 | as: (defined?(EffectiveFormInputs) ? :effective_select : :select), 60 | required: required, 61 | collection: effective_address_regions_collection(Carmen::Country.coded(fa.object.country_code).try(:subregions)), 62 | prompt: 'Please choose', 63 | input_html: {'data-effective-address-state' => uuid}, 64 | input_js: { placeholder: 'Please choose' }, 65 | disabled: shipping_address_same_as_billing, 66 | wrapper_html: { style: ('display: none;' if shipping_address_same_as_billing) } 67 | - else 68 | = fa.input :state_code, 69 | as: (defined?(EffectiveFormInputs) ? :effective_select : :select), 70 | required: required, 71 | collection: [], 72 | prompt: 'Please choose a country first', 73 | input_html: { 'data-effective-address-state' => uuid }, 74 | input_js: { placeholder: 'Please choose country first' }, 75 | disabled: true, 76 | wrapper_html: { style: ('display: none;' if shipping_address_same_as_billing) } 77 | 78 | - when :postal_code 79 | = fa.input :postal_code, 80 | required: required, 81 | input_html: { 'data-effective-address-postal-code' => uuid }, 82 | disabled: shipping_address_same_as_billing, 83 | wrapper_html: { style: ('display: none;' if shipping_address_same_as_billing) } 84 | -------------------------------------------------------------------------------- /test/dummy/config/environments/production.rb: -------------------------------------------------------------------------------- 1 | require "active_support/core_ext/integer/time" 2 | 3 | Rails.application.configure do 4 | # Settings specified here will take precedence over those in config/application.rb. 5 | 6 | # Code is not reloaded between requests. 7 | config.cache_classes = true 8 | 9 | # Eager load code on boot. This eager loads most of Rails and 10 | # your application in memory, allowing both threaded web servers 11 | # and those relying on copy on write to perform better. 12 | # Rake tasks automatically ignore this option for performance. 13 | config.eager_load = true 14 | 15 | # Full error reports are disabled and caching is turned on. 16 | config.consider_all_requests_local = false 17 | config.action_controller.perform_caching = true 18 | 19 | # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] 20 | # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). 21 | # config.require_master_key = true 22 | 23 | # Disable serving static files from the `/public` folder by default since 24 | # Apache or NGINX already handles this. 25 | config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? 26 | 27 | # Compress CSS using a preprocessor. 28 | # config.assets.css_compressor = :sass 29 | 30 | # Do not fallback to assets pipeline if a precompiled asset is missed. 31 | config.assets.compile = false 32 | 33 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 34 | # config.asset_host = 'http://assets.example.com' 35 | 36 | # Specifies the header that your server uses for sending files. 37 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache 38 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX 39 | 40 | # Store uploaded files on the local file system (see config/storage.yml for options). 41 | config.active_storage.service = :local 42 | 43 | # Mount Action Cable outside main process or domain. 44 | # config.action_cable.mount_path = nil 45 | # config.action_cable.url = 'wss://example.com/cable' 46 | # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] 47 | 48 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 49 | # config.force_ssl = true 50 | 51 | # Include generic and useful information about system operation, but avoid logging too much 52 | # information to avoid inadvertent exposure of personally identifiable information (PII). 53 | config.log_level = :info 54 | 55 | # Prepend all log lines with the following tags. 56 | config.log_tags = [ :request_id ] 57 | 58 | # Use a different cache store in production. 59 | # config.cache_store = :mem_cache_store 60 | 61 | # Use a real queuing backend for Active Job (and separate queues per environment). 62 | # config.active_job.queue_adapter = :resque 63 | # config.active_job.queue_name_prefix = "dummy_production" 64 | 65 | config.action_mailer.perform_caching = false 66 | 67 | # Ignore bad email addresses and do not raise email delivery errors. 68 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 69 | # config.action_mailer.raise_delivery_errors = false 70 | 71 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 72 | # the I18n.default_locale when a translation cannot be found). 73 | config.i18n.fallbacks = true 74 | 75 | # Send deprecation notices to registered listeners. 76 | config.active_support.deprecation = :notify 77 | 78 | # Log disallowed deprecations. 79 | config.active_support.disallowed_deprecation = :log 80 | 81 | # Tell Active Support which deprecation messages to disallow. 82 | config.active_support.disallowed_deprecation_warnings = [] 83 | 84 | # Use default logging formatter so that PID and timestamp are not suppressed. 85 | config.log_formatter = ::Logger::Formatter.new 86 | 87 | # Use a different logger for distributed setups. 88 | # require "syslog/logger" 89 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') 90 | 91 | if ENV["RAILS_LOG_TO_STDOUT"].present? 92 | logger = ActiveSupport::Logger.new(STDOUT) 93 | logger.formatter = config.log_formatter 94 | config.logger = ActiveSupport::TaggedLogging.new(logger) 95 | end 96 | 97 | # Do not dump schema after migrations. 98 | config.active_record.dump_schema_after_migration = false 99 | 100 | # Inserts middleware to perform automatic connection switching. 101 | # The `database_selector` hash is used to pass options to the DatabaseSelector 102 | # middleware. The `delay` is used to determine how long to wait after a write 103 | # to send a subsequent read to the primary. 104 | # 105 | # The `database_resolver` class is used by the middleware to determine which 106 | # database is appropriate to use based on the time delay. 107 | # 108 | # The `database_resolver_context` class is used by the middleware to set 109 | # timestamps for the last write to the primary. The resolver uses the context 110 | # class timestamps to determine how long to wait before reading from the 111 | # replica. 112 | # 113 | # By default Rails will store a last write timestamp in the session. The 114 | # DatabaseSelector middleware is designed as such you can define your own 115 | # strategy for connection switching and pass that into the middleware through 116 | # these configuration options. 117 | # config.active_record.database_selector = { delay: 2.seconds } 118 | # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver 119 | # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session 120 | end 121 | -------------------------------------------------------------------------------- /app/models/effective/address.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Effective 4 | class Address < ActiveRecord::Base 5 | self.table_name = (EffectiveAddresses.addresses_table_name || :addresses).to_s 6 | 7 | attr_accessor :shipping_address_same_as_billing 8 | 9 | POSTAL_CODE_CA = /\A[A-Z]{1}\d{1}[A-Z]{1}\ \d{1}[A-Z]{1}\d{1}\z/ # Matches 'T5Z 2B1' 10 | POSTAL_CODE_US = /\A\d{5}(-\d{4})?\z/ # matches 5 digits plus optional hyphen and 4 digits 11 | 12 | belongs_to :addressable, polymorphic: true, touch: true 13 | 14 | log_changes(to: :addressable) if respond_to?(:log_changes) 15 | 16 | effective_resource do 17 | category :string 18 | 19 | full_name :string 20 | address1 :string 21 | address2 :string 22 | address3 :string 23 | 24 | city :string 25 | state_code :string 26 | country_code :string 27 | postal_code :string 28 | 29 | shipping_address_same_as_billing permitted: true 30 | 31 | timestamps 32 | end 33 | 34 | validates :category, :address1, :city, :country_code, :postal_code, presence: true, if: Proc.new { |address| address.present? } 35 | validates :state_code, presence: true, if: Proc.new { |address| address.present? && (address.country_code.blank? || Carmen::Country.coded(address.country_code).try(:subregions).present?) } 36 | 37 | validates_format_of :postal_code, :with => POSTAL_CODE_CA, 38 | :if => proc { |address| Array(EffectiveAddresses.validate_postal_code_format).include?('CA') && address.country_code == 'CA' }, 39 | :allow_blank => true, # We're already checking for presence above 40 | :message => 'is an invalid Canadian postal code' 41 | 42 | validates_format_of :postal_code, :with => POSTAL_CODE_US, 43 | :if => proc { |address| Array(EffectiveAddresses.validate_postal_code_format).include?('US') && address.country_code == 'US' }, 44 | :allow_blank => true, # We're already checking for presence above 45 | :message => 'is an invalid United States zip code' 46 | 47 | scope :sorted, -> { order(:updated_at) } 48 | scope :billing, -> { where(:category => 'billing') } 49 | scope :shipping, -> { where(:category => 'shipping') } 50 | 51 | def first_name 52 | full_name.split(' ').first rescue full_name 53 | end 54 | 55 | def last_name 56 | full_name.gsub(first_name, '').strip rescue full_name 57 | end 58 | 59 | def country 60 | Carmen::Country.coded(country_code).name rescue '' 61 | end 62 | 63 | def state 64 | Carmen::Country.coded(country_code).subregions.coded(state_code).name rescue '' 65 | end 66 | alias_method :province, :state 67 | 68 | def country=(country_string) 69 | value = Carmen::Country.named(country_string) || Carmen::Country.coded(country_string.try(:upcase)) 70 | self.country_code = value.code if value.present? 71 | end 72 | 73 | def state=(state_string) 74 | if country.present? 75 | subregions = (Carmen::Country.coded(country_code).subregions rescue nil) 76 | 77 | if subregions.present? 78 | value = subregions.named(state_string) || subregions.coded(state_string.try(:upcase)) 79 | else 80 | value = nil 81 | end 82 | 83 | self.state_code = value.code if value.present? 84 | else 85 | Rails.logger.info 'No country set. Try calling country= before state=' 86 | puts 'No country set. Try calling country= before state=' 87 | end 88 | end 89 | alias_method :province=, :state= 90 | 91 | # If the country is Canada or US, enforce the correct postal code/zip code format 92 | def postal_code=(code) 93 | if code.presence.kind_of?(String) 94 | if country_code == 'CA' 95 | code = code.upcase.gsub(/[^A-Z0-9]/, '') 96 | code = code.insert(3, ' ') if code.length == 6 97 | elsif country_code == 'US' 98 | code = code.gsub(/[^0-9]/, '') 99 | code = code.insert(5, '-') if code.length == 9 100 | end 101 | end 102 | 103 | super(code) 104 | end 105 | 106 | def postal_code_looks_canadian? 107 | postal_code.to_s.match(POSTAL_CODE_CA).present? 108 | end 109 | 110 | def postal_code_looks_american? 111 | postal_code.to_s.match(POSTAL_CODE_US).present? 112 | end 113 | 114 | def ==(other_address) 115 | self_attrs = self.attributes 116 | other_attrs = other_address.respond_to?(:attributes) ? other_address.attributes : {} 117 | 118 | [self_attrs, other_attrs].each { |attrs| attrs.except!('id', 'created_at', 'updated_at', 'addressable_type', 'addressable_id', 'category') } 119 | 120 | self_attrs == other_attrs 121 | end 122 | 123 | # An address may be set with a category but nothing else 124 | def blank? 125 | address1.blank? && address2.blank? && city.blank? && postal_code.blank? 126 | end 127 | alias_method :empty?, :blank? 128 | 129 | def present? 130 | !blank? 131 | end 132 | 133 | def to_s 134 | output = '' 135 | output += "#{full_name}\n" if full_name.present? 136 | output += "#{address1}\n" if address1.present? 137 | output += "#{address2}\n" if address2.present? 138 | output += "#{address3}\n" if respond_to?(:address3) && address3.present? 139 | output += [city.presence, state_code.presence, " #{postal_code.presence}"].compact.join(' ') 140 | output += "\n" 141 | output += country.to_s 142 | output 143 | end 144 | 145 | def to_html 146 | to_s.gsub(/\n/, "
\n").gsub(' ', '  ').html_safe 147 | end 148 | 149 | def shipping_address_same_as_billing? 150 | EffectiveResources.truthy?(shipping_address_same_as_billing) 151 | end 152 | end 153 | end 154 | -------------------------------------------------------------------------------- /app/models/concerns/acts_as_addressable.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # ActsAsAddressable 4 | 5 | module ActsAsAddressable 6 | extend ActiveSupport::Concern 7 | 8 | module Base 9 | def acts_as_addressable(*options) 10 | @acts_as_addressable_opts = options || [] 11 | include ::ActsAsAddressable 12 | end 13 | end 14 | 15 | included do 16 | has_many :addresses, -> { order(:updated_at) }, as: :addressable, class_name: 'Effective::Address', dependent: :delete_all, autosave: true 17 | 18 | scope :deep_effective_addresses, -> { includes(:addresses) } 19 | 20 | # Normalize categories 21 | categories = @acts_as_addressable_opts.try(:flatten) || [] 22 | 23 | if categories.first.kind_of?(Hash) 24 | categories = categories.first.transform_keys { |category| category.to_s.gsub('_address', '') } 25 | else 26 | categories = categories.map { |category| category.to_s.gsub('_address', '') } 27 | end 28 | 29 | # Categories can be either: 30 | # {'billing'=>{:singular=>true}, 'shipping'=>{:singular=>true}} 31 | # or 32 | # {'billing' => true, 'shipping' => true} 33 | # or 34 | # ['billing', 'shipping'] 35 | 36 | categories.each do |category, options = {}| 37 | # Define our two getter methods 38 | self.send(:define_method, "#{category}_address") { effective_address(category) } 39 | self.send(:define_method, "#{category}_addresses") { effective_addresses(category) } 40 | 41 | # Define our setter method 42 | if options.kind_of?(Hash) && options[:singular] 43 | self.send(:define_method, "#{category}_address=") { |atts| set_singular_effective_address(category, atts) } 44 | else 45 | self.send(:define_method, "#{category}_address=") { |atts| set_effective_address(category, atts) } 46 | end 47 | 48 | # Consider validations now 49 | validates "#{category}_address", effective_address_valid: true 50 | 51 | case options 52 | when Hash 53 | validates("#{category}_address", presence: true) if options[:presence] 54 | validates("#{category}_address", effective_address_full_name_presence: true) if options[:use_full_name] 55 | when TrueClass 56 | validates "#{category}_address", presence: true 57 | validates "#{category}_address", effective_address_full_name_presence: true, if: -> { EffectiveAddresses.use_full_name } 58 | when FalseClass 59 | # Nothing to do 60 | else 61 | raise 'Unexpected options. Expected a Hash or Boolean' 62 | end 63 | end 64 | 65 | # [:billing_address, :shipping_address] 66 | address_names = (categories.respond_to?(:keys) ? categories.keys : categories).map { |category| (category.to_s + '_address').to_sym } 67 | 68 | if address_names.include?(:billing_address) && address_names.include?(:shipping_address) 69 | self.send(:define_method, :shipping_address_same_as_billing?) { billing_address == shipping_address } 70 | end 71 | 72 | self.send(:define_method, :effective_address_names) { address_names } 73 | end 74 | 75 | module ClassMethods 76 | end 77 | 78 | def effective_addresses(category) 79 | category = category.to_s 80 | addresses.select { |address| address.category == category } 81 | end 82 | 83 | def effective_address(category) 84 | effective_addresses(category).last 85 | end 86 | 87 | def set_effective_address(category, obj) 88 | return if obj.blank? 89 | 90 | raise "#{category}_address= expected an Effective::Address or Hash" unless obj.kind_of?(Effective::Address) || obj.kind_of?(Hash) 91 | 92 | address = (obj.kind_of?(Effective::Address) ? obj : Effective::Address.new(obj)) 93 | 94 | if category == 'shipping' && address.shipping_address_same_as_billing? && respond_to?(:billing_address) 95 | address = effective_address('billing') 96 | end 97 | 98 | # Prevents duplicates from being created 99 | return effective_address(category) if address == effective_address(category) 100 | 101 | (self.addresses.build).tap do |existing| 102 | existing.addressable = self 103 | existing.category = category.to_s 104 | existing.full_name = address.full_name 105 | existing.address1 = address.address1 106 | existing.address2 = address.address2 107 | existing.address3 = address.address3 if address.respond_to?(:address3) 108 | existing.city = address.city 109 | existing.state_code = address.state_code 110 | existing.country_code = address.country_code 111 | existing.postal_code = address.postal_code 112 | existing.shipping_address_same_as_billing = address.shipping_address_same_as_billing? 113 | end 114 | end 115 | 116 | def set_singular_effective_address(category, obj) 117 | return if obj.blank? 118 | 119 | raise "#{category}_address= expected an Effective::Address or Hash" unless obj.kind_of?(Effective::Address) || obj.kind_of?(Hash) 120 | 121 | address = (obj.kind_of?(Effective::Address) ? obj : Effective::Address.new(obj)) 122 | 123 | if category == 'shipping' && address.shipping_address_same_as_billing? && respond_to?(:billing_address) 124 | address = effective_address('billing') 125 | end 126 | 127 | # This wouldn't create duplicates anyway 128 | return effective_address(category) if address == effective_address(category) 129 | 130 | (effective_address(category) || self.addresses.build).tap do |existing| 131 | existing.addressable = self 132 | existing.category = category.to_s 133 | existing.full_name = address.full_name 134 | existing.address1 = address.address1 135 | existing.address2 = address.address2 136 | existing.address3 = address.address3 if address.respond_to?(:address3) 137 | existing.city = address.city 138 | existing.state_code = address.state_code 139 | existing.country_code = address.country_code 140 | existing.postal_code = address.postal_code 141 | existing.shipping_address_same_as_billing = address.shipping_address_same_as_billing? 142 | end 143 | end 144 | 145 | end 146 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | effective_addresses (1.10.4) 5 | carmen 6 | coffee-rails 7 | effective_resources 8 | rails 9 | 10 | GEM 11 | remote: http://rubygems.org/ 12 | specs: 13 | actioncable (6.1.7.6) 14 | actionpack (= 6.1.7.6) 15 | activesupport (= 6.1.7.6) 16 | nio4r (~> 2.0) 17 | websocket-driver (>= 0.6.1) 18 | actionmailbox (6.1.7.6) 19 | actionpack (= 6.1.7.6) 20 | activejob (= 6.1.7.6) 21 | activerecord (= 6.1.7.6) 22 | activestorage (= 6.1.7.6) 23 | activesupport (= 6.1.7.6) 24 | mail (>= 2.7.1) 25 | actionmailer (6.1.7.6) 26 | actionpack (= 6.1.7.6) 27 | actionview (= 6.1.7.6) 28 | activejob (= 6.1.7.6) 29 | activesupport (= 6.1.7.6) 30 | mail (~> 2.5, >= 2.5.4) 31 | rails-dom-testing (~> 2.0) 32 | actionpack (6.1.7.6) 33 | actionview (= 6.1.7.6) 34 | activesupport (= 6.1.7.6) 35 | rack (~> 2.0, >= 2.0.9) 36 | rack-test (>= 0.6.3) 37 | rails-dom-testing (~> 2.0) 38 | rails-html-sanitizer (~> 1.0, >= 1.2.0) 39 | actiontext (6.1.7.6) 40 | actionpack (= 6.1.7.6) 41 | activerecord (= 6.1.7.6) 42 | activestorage (= 6.1.7.6) 43 | activesupport (= 6.1.7.6) 44 | nokogiri (>= 1.8.5) 45 | actionview (6.1.7.6) 46 | activesupport (= 6.1.7.6) 47 | builder (~> 3.1) 48 | erubi (~> 1.4) 49 | rails-dom-testing (~> 2.0) 50 | rails-html-sanitizer (~> 1.1, >= 1.2.0) 51 | activejob (6.1.7.6) 52 | activesupport (= 6.1.7.6) 53 | globalid (>= 0.3.6) 54 | activemodel (6.1.7.6) 55 | activesupport (= 6.1.7.6) 56 | activerecord (6.1.7.6) 57 | activemodel (= 6.1.7.6) 58 | activesupport (= 6.1.7.6) 59 | activestorage (6.1.7.6) 60 | actionpack (= 6.1.7.6) 61 | activejob (= 6.1.7.6) 62 | activerecord (= 6.1.7.6) 63 | activesupport (= 6.1.7.6) 64 | marcel (~> 1.0) 65 | mini_mime (>= 1.1.0) 66 | activesupport (6.1.7.6) 67 | concurrent-ruby (~> 1.0, >= 1.0.2) 68 | i18n (>= 1.6, < 2) 69 | minitest (>= 5.1) 70 | tzinfo (~> 2.0) 71 | zeitwerk (~> 2.3) 72 | addressable (2.8.5) 73 | public_suffix (>= 2.0.2, < 6.0) 74 | ansi (1.5.0) 75 | bcrypt (3.1.19) 76 | builder (3.2.4) 77 | byebug (11.1.3) 78 | capybara (3.39.2) 79 | addressable 80 | matrix 81 | mini_mime (>= 0.1.3) 82 | nokogiri (~> 1.8) 83 | rack (>= 1.6.0) 84 | rack-test (>= 0.6.3) 85 | regexp_parser (>= 1.5, < 3.0) 86 | xpath (~> 3.2) 87 | carmen (1.1.3) 88 | activesupport (>= 3.0.0) 89 | coderay (1.1.3) 90 | coffee-rails (5.0.0) 91 | coffee-script (>= 2.2.0) 92 | railties (>= 5.2.0) 93 | coffee-script (2.4.1) 94 | coffee-script-source 95 | execjs 96 | coffee-script-source (1.12.2) 97 | concurrent-ruby (1.2.2) 98 | crass (1.0.6) 99 | date (3.3.3) 100 | devise (4.9.2) 101 | bcrypt (~> 3.0) 102 | orm_adapter (~> 0.1) 103 | railties (>= 4.1.0) 104 | responders 105 | warden (~> 1.2.3) 106 | effective_developer (0.7.6) 107 | effective_resources 108 | rails (>= 3.2.0) 109 | effective_resources (2.8.7) 110 | rails (>= 4.0.0) 111 | effective_test_bot (1.4.0) 112 | capybara 113 | effective_resources 114 | faker 115 | minitest-fail-fast 116 | minitest-reporters 117 | rails 118 | selenium-webdriver 119 | timecop 120 | erubi (1.12.0) 121 | execjs (2.8.1) 122 | faker (3.2.1) 123 | i18n (>= 1.8.11, < 2) 124 | globalid (1.1.0) 125 | activesupport (>= 5.0) 126 | i18n (1.14.1) 127 | concurrent-ruby (~> 1.0) 128 | loofah (2.21.3) 129 | crass (~> 1.0.2) 130 | nokogiri (>= 1.12.0) 131 | mail (2.8.1) 132 | mini_mime (>= 0.1.1) 133 | net-imap 134 | net-pop 135 | net-smtp 136 | marcel (1.0.2) 137 | matrix (0.4.2) 138 | method_source (1.0.0) 139 | mini_mime (1.1.5) 140 | minitest (5.19.0) 141 | minitest-fail-fast (0.1.0) 142 | minitest (~> 5) 143 | minitest-reporters (1.6.1) 144 | ansi 145 | builder 146 | minitest (>= 5.0) 147 | ruby-progressbar 148 | net-imap (0.3.7) 149 | date 150 | net-protocol 151 | net-pop (0.1.2) 152 | net-protocol 153 | net-protocol (0.2.1) 154 | timeout 155 | net-smtp (0.3.3) 156 | net-protocol 157 | nio4r (2.5.9) 158 | nokogiri (1.15.4-arm64-darwin) 159 | racc (~> 1.4) 160 | orm_adapter (0.5.0) 161 | pry (0.14.2) 162 | coderay (~> 1.1) 163 | method_source (~> 1.0) 164 | pry-byebug (3.10.1) 165 | byebug (~> 11.0) 166 | pry (>= 0.13, < 0.15) 167 | psych (3.3.4) 168 | public_suffix (5.0.3) 169 | racc (1.7.1) 170 | rack (2.2.8) 171 | rack-test (2.1.0) 172 | rack (>= 1.3) 173 | rails (6.1.7.6) 174 | actioncable (= 6.1.7.6) 175 | actionmailbox (= 6.1.7.6) 176 | actionmailer (= 6.1.7.6) 177 | actionpack (= 6.1.7.6) 178 | actiontext (= 6.1.7.6) 179 | actionview (= 6.1.7.6) 180 | activejob (= 6.1.7.6) 181 | activemodel (= 6.1.7.6) 182 | activerecord (= 6.1.7.6) 183 | activestorage (= 6.1.7.6) 184 | activesupport (= 6.1.7.6) 185 | bundler (>= 1.15.0) 186 | railties (= 6.1.7.6) 187 | sprockets-rails (>= 2.0.0) 188 | rails-dom-testing (2.2.0) 189 | activesupport (>= 5.0.0) 190 | minitest 191 | nokogiri (>= 1.6) 192 | rails-html-sanitizer (1.6.0) 193 | loofah (~> 2.21) 194 | nokogiri (~> 1.14) 195 | railties (6.1.7.6) 196 | actionpack (= 6.1.7.6) 197 | activesupport (= 6.1.7.6) 198 | method_source 199 | rake (>= 12.2) 200 | thor (~> 1.0) 201 | rake (13.0.6) 202 | regexp_parser (2.8.1) 203 | responders (3.1.0) 204 | actionpack (>= 5.2) 205 | railties (>= 5.2) 206 | rexml (3.2.6) 207 | ruby-progressbar (1.13.0) 208 | rubyzip (2.3.2) 209 | selenium-webdriver (4.11.0) 210 | rexml (~> 3.2, >= 3.2.5) 211 | rubyzip (>= 1.2.2, < 3.0) 212 | websocket (~> 1.0) 213 | sprockets (4.2.0) 214 | concurrent-ruby (~> 1.0) 215 | rack (>= 2.2.4, < 4) 216 | sprockets-rails (3.4.2) 217 | actionpack (>= 5.2) 218 | activesupport (>= 5.2) 219 | sprockets (>= 3.0.0) 220 | sqlite3 (1.6.3-arm64-darwin) 221 | thor (1.2.2) 222 | timecop (0.9.8) 223 | timeout (0.4.0) 224 | tzinfo (2.0.6) 225 | concurrent-ruby (~> 1.0) 226 | warden (1.2.9) 227 | rack (>= 2.0.9) 228 | websocket (1.2.9) 229 | websocket-driver (0.7.6) 230 | websocket-extensions (>= 0.1.0) 231 | websocket-extensions (0.1.5) 232 | xpath (3.2.0) 233 | nokogiri (~> 1.8) 234 | zeitwerk (2.6.11) 235 | 236 | PLATFORMS 237 | arm64-darwin-22 238 | 239 | DEPENDENCIES 240 | devise 241 | effective_addresses! 242 | effective_developer 243 | effective_test_bot 244 | pry-byebug 245 | psych (< 4) 246 | sqlite3 247 | 248 | RUBY VERSION 249 | ruby 3.1.2p20 250 | 251 | BUNDLED WITH 252 | 2.4.12 253 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Effective Addresses 2 | 3 | Extend any ActiveRecord object to have one or more named addresses. Includes a geographic region-aware custom form input backed by Carmen. 4 | 5 | Creates methods such as `user.billing_address` and `user.billing_address=` for dealing with a has_many :addresses relationship as a single method. 6 | 7 | Adds region-aware validations for provinces/states and postal codes. 8 | 9 | Includes a Formtastic and SimpleForm one-liner method to drop in address fields to any form. 10 | 11 | Uses the Carmen gem internally so when a Country is selected, an AJAX request populates the province/state fields as appropriate. 12 | 13 | ## Getting Started 14 | 15 | Add to your Gemfile: 16 | 17 | ```ruby 18 | gem 'effective_addresses' 19 | ``` 20 | 21 | Run the bundle command to install it: 22 | 23 | ```console 24 | bundle install 25 | ``` 26 | 27 | If you're using effective_addresses from within a rails engine (optional): 28 | 29 | ```ruby 30 | require 'effective_addresses' 31 | ``` 32 | 33 | Then run the generator: 34 | 35 | ```ruby 36 | rails generate effective_addresses:install 37 | ``` 38 | 39 | The generator will install an initializer which describes all configuration options and creates a database migration. 40 | 41 | If you want to tweak the table name (to use something other than the default `addresses`), manually adjust both the configuration file and the migration now. 42 | 43 | Then migrate the database: 44 | 45 | ```ruby 46 | rake db:migrate 47 | ``` 48 | 49 | And require the javascript in your application.js: 50 | 51 | ```ruby 52 | //= require effective_addresses 53 | ``` 54 | 55 | 56 | ## Usage 57 | 58 | ### Model 59 | 60 | Add the mixin to your existing model and specify the name or names of the addresses it should respond to: 61 | 62 | ```ruby 63 | class User 64 | acts_as_addressable :billing 65 | end 66 | ``` 67 | 68 | This adds the following getters and setters: 69 | 70 | ```ruby 71 | @user.billing_address 72 | @user.billing_address= 73 | @user.billing_addresses 74 | ``` 75 | 76 | Calling `user.billing_address` will return a single `Effective::Address` object. Calling `user.billing_addresses` will return an array of `Effective:Address` objects. 77 | 78 | You can also specify a `:presence` validation as follows: 79 | 80 | ```ruby 81 | class User 82 | acts_as_addressable :billing => true, :shipping => false 83 | end 84 | ``` 85 | 86 | or 87 | 88 | ```ruby 89 | class User 90 | acts_as_addressable :billing => {:presence => true} 91 | end 92 | ``` 93 | 94 | or 95 | 96 | ```ruby 97 | class User 98 | acts_as_addressable :billing 99 | 100 | validates_presence_of :billing_address 101 | end 102 | ``` 103 | 104 | This means when a User is created, it will not be valid unless a billing_address exist and is valid. 105 | 106 | 107 | ### Full Name 108 | 109 | Sometimes you want to collect a `full_name` field with your addresses, such as in the case of a mailing address; other times, it's an unnecessary field. 110 | 111 | When you specify the config option `config.use_full_name = true` all, any calls to `effective_address_fields` form helper will display the full_name input, and the model will `validate_presence_of :full_name`. 112 | 113 | 114 | ### Address Validations 115 | 116 | Address1, City, Country and Postal/Zip Code are all required fields. 117 | 118 | If the selected Country has provinces/states (not all countries do), then the province/state field will be required. 119 | 120 | If the country is Canada or United States, then the postal/zip code formatting will be enforced. 121 | 122 | This validation on the postal code/zip format can be disabled via the config/initializers `validate_postal_code_format` setting 123 | 124 | Canadian postal codes will be automatically upcased and formatted to a consistent format: `T5Z 3A4` (capitalized with a single space). 125 | 126 | 127 | ### Multiple Addresses 128 | 129 | Everytime an address is changed, an additional address record is created. The latest address will always be returned by: 130 | 131 | ```ruby 132 | @user.billing_address 133 | ``` 134 | 135 | You can find all past addresses (including the current one) by: 136 | 137 | ```ruby 138 | @user.billing_addresses 139 | ``` 140 | 141 | ### Strong Parameters 142 | 143 | Make your controller aware of the `acts_as_addressable` passed parameters: 144 | 145 | ```ruby 146 | def permitted_params 147 | params.require(:base_object).permit( 148 | :billing_address => EffectiveAddresses.permitted_params, 149 | :shipping_address => EffectiveAddresses.permitted_params 150 | ) 151 | end 152 | ``` 153 | 154 | The actual permitted parameters are: 155 | 156 | ```ruby 157 | [:full_name, :address1, :address2, :city, :country_code, :state_code, :postal_code] 158 | ``` 159 | 160 | ### Form Helpers 161 | 162 | Use the helper in a Formtastic or SimpleForm form to quickly create the address fields. Currently only supports Formtastic and SimpleForm. 163 | 164 | When you select a country from the select input an AJAX GET request will be made to `effective_addresses.address_subregions_path` (`/addresses/subregions/:country_code`) 165 | which populates the province/state dropdown with the selected country's states or provinces. 166 | 167 | 168 | #### Formtastic 169 | 170 | ```ruby 171 | = semantic_form_for @user do |f| 172 | %h3 Billing Address 173 | = effective_address_fields(f, :billing_address) 174 | 175 | = f.action :submit 176 | ``` 177 | 178 | #### SimpleForm 179 | 180 | ```ruby 181 | = simple_form_for @user do |f| 182 | %h3 Billing Address 183 | = effective_address_fields(f, :billing_address) 184 | 185 | = f.submit 'Save' 186 | ``` 187 | 188 | #### Field Ordering 189 | You may choose to order fields different than the default, such as putting the country first. You can do so with the `:field_order` option, for example: 190 | ```ruby 191 | = simple_form_for @user do |f| 192 | %h3 Billing Address 193 | = effective_address_fields(f, :billing_address, :field_order => [:country_code, :full_name, :address1, :address2, :city, :state_code, :postal_code]) 194 | 195 | = f.submit 'Save' 196 | ``` 197 | 198 | ## Geocoder option 199 | 200 | Effective addresses has an optional integration with [Geocoder](https://github.com/alexreisner/geocoder). At it's simplest, this provides preselection and prefill of `country`, `state`, `city`, and `postal_code` based on the user's IP address. See [Geocoder](https://github.com/alexreisner/geocoder) for 201 | a complete list of possibilities. 202 | 203 | ### Installation and Setup 204 | 205 | ```ruby 206 | gem 'geocoder' 207 | ``` 208 | 209 | Add `config/initializer/geocoder.rb`, below is a sample: 210 | 211 | ```ruby 212 | Geocoder.configure( 213 | # Remote IP address geocoding service (see below for supported options): 214 | # https://github.com/alexreisner/geocoder#ip-address-services 215 | ip_lookup: :telize, 216 | 217 | # Local IP address file database: 218 | # 1. gem 'maxminddb' 219 | # 2. download database: http://dev.maxmind.com/geoip/geoip2/geolite2/ 220 | # 3. save file in db/geocoder 221 | # ip_lookup: :geoip2, 222 | # geoip2: { file: File.expand_path('../../db/geocoder/GeoLite2-City.mmdb', File.dirname(__FILE__)) }, 223 | 224 | cache: Rails.cache, 225 | cache_prefix: 'geocoder:' 226 | ) 227 | 228 | # Provide a hardcoded ip of 1.2.3.4 when in developmnt/test and the ip address resolves as localhost 229 | if %w(development test).include? Rails.env 230 | module Geocoder 231 | module Request 232 | def geocoder_spoofable_ip_with_localhost_override 233 | ip_candidate = geocoder_spoofable_ip_without_localhost_override 234 | if ip_candidate == '127.0.0.1' 235 | '1.2.3.4' 236 | else 237 | ip_candidate 238 | end 239 | end 240 | alias_method_chain :geocoder_spoofable_ip, :localhost_override 241 | end 242 | end 243 | end 244 | ``` 245 | 246 | 247 | ## License 248 | 249 | MIT License. Copyright [Code and Effect Inc.](http://www.codeandeffect.com/) 250 | 251 | ## Testing 252 | 253 | The test suite for this gem is unfortunately not yet complete. 254 | 255 | Run tests by: 256 | 257 | ```ruby 258 | rake spec 259 | ``` 260 | 261 | ## Contributing 262 | 263 | 1. Fork it 264 | 2. Create your feature branch (`git checkout -b my-new-feature`) 265 | 3. Commit your changes (`git commit -am 'Add some feature'`) 266 | 4. Push to the branch (`git push origin my-new-feature`) 267 | 5. Bonus points for test coverage 268 | 6. Create new Pull Request 269 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/devise.rb: -------------------------------------------------------------------------------- 1 | require 'devise' 2 | # frozen_string_literal: true 3 | 4 | # Assuming you have not yet modified this file, each configuration option below 5 | # is set to its default value. Note that some are commented out while others 6 | # are not: uncommented lines are intended to protect your configuration from 7 | # breaking changes in upgrades (i.e., in the event that future versions of 8 | # Devise change the default values for those options). 9 | # 10 | # Use this hook to configure devise mailer, warden hooks and so forth. 11 | # Many of these configuration options can be set straight in your model. 12 | Devise.setup do |config| 13 | # The secret key used by Devise. Devise uses this key to generate 14 | # random tokens. Changing this key will render invalid all existing 15 | # confirmation, reset password and unlock tokens in the database. 16 | # Devise will use the `secret_key_base` as its `secret_key` 17 | # by default. You can change it below and use your own secret key. 18 | # config.secret_key = '44e181f138a2b7eb1e31b3bda03b7744ecce032f6c98e6954e430a2f2fa15520946f9d63027e56b17be12c7af6efca3bec0c6e1ca380d91a5b4dcf4a1230da6a' 19 | 20 | # ==> Controller configuration 21 | # Configure the parent class to the devise controllers. 22 | # config.parent_controller = 'DeviseController' 23 | 24 | config.secret_key = 'de7819d525767ffd5c655873735f1c960a688fae4e174d63fe16df3aa894a2ef267a63495270e41f010281cf6252e428db5c7cc158faa4259fc0950b74a821b9' 25 | 26 | # ==> Mailer Configuration 27 | # Configure the e-mail address which will be shown in Devise::Mailer, 28 | # note that it will be overwritten if you use your own mailer class 29 | # with default "from" parameter. 30 | config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com' 31 | 32 | # Configure the class responsible to send e-mails. 33 | # config.mailer = 'Devise::Mailer' 34 | 35 | # Configure the parent class responsible to send e-mails. 36 | # config.parent_mailer = 'ActionMailer::Base' 37 | 38 | # ==> ORM configuration 39 | # Load and configure the ORM. Supports :active_record (default) and 40 | # :mongoid (bson_ext recommended) by default. Other ORMs may be 41 | # available as additional gems. 42 | require 'devise/orm/active_record' 43 | 44 | # ==> Configuration for any authentication mechanism 45 | # Configure which keys are used when authenticating a user. The default is 46 | # just :email. You can configure it to use [:username, :subdomain], so for 47 | # authenticating a user, both parameters are required. Remember that those 48 | # parameters are used only when authenticating and not when retrieving from 49 | # session. If you need permissions, you should implement that in a before filter. 50 | # You can also supply a hash where the value is a boolean determining whether 51 | # or not authentication should be aborted when the value is not present. 52 | # config.authentication_keys = [:email] 53 | 54 | # Configure parameters from the request object used for authentication. Each entry 55 | # given should be a request method and it will automatically be passed to the 56 | # find_for_authentication method and considered in your model lookup. For instance, 57 | # if you set :request_keys to [:subdomain], :subdomain will be used on authentication. 58 | # The same considerations mentioned for authentication_keys also apply to request_keys. 59 | # config.request_keys = [] 60 | 61 | # Configure which authentication keys should be case-insensitive. 62 | # These keys will be downcased upon creating or modifying a user and when used 63 | # to authenticate or find a user. Default is :email. 64 | config.case_insensitive_keys = [:email] 65 | 66 | # Configure which authentication keys should have whitespace stripped. 67 | # These keys will have whitespace before and after removed upon creating or 68 | # modifying a user and when used to authenticate or find a user. Default is :email. 69 | config.strip_whitespace_keys = [:email] 70 | 71 | # Tell if authentication through request.params is enabled. True by default. 72 | # It can be set to an array that will enable params authentication only for the 73 | # given strategies, for example, `config.params_authenticatable = [:database]` will 74 | # enable it only for database (email + password) authentication. 75 | # config.params_authenticatable = true 76 | 77 | # Tell if authentication through HTTP Auth is enabled. False by default. 78 | # It can be set to an array that will enable http authentication only for the 79 | # given strategies, for example, `config.http_authenticatable = [:database]` will 80 | # enable it only for database authentication. 81 | # For API-only applications to support authentication "out-of-the-box", you will likely want to 82 | # enable this with :database unless you are using a custom strategy. 83 | # The supported strategies are: 84 | # :database = Support basic authentication with authentication key + password 85 | # config.http_authenticatable = false 86 | 87 | # If 401 status code should be returned for AJAX requests. True by default. 88 | # config.http_authenticatable_on_xhr = true 89 | 90 | # The realm used in Http Basic Authentication. 'Application' by default. 91 | # config.http_authentication_realm = 'Application' 92 | 93 | # It will change confirmation, password recovery and other workflows 94 | # to behave the same regardless if the e-mail provided was right or wrong. 95 | # Does not affect registerable. 96 | # config.paranoid = true 97 | 98 | # By default Devise will store the user in session. You can skip storage for 99 | # particular strategies by setting this option. 100 | # Notice that if you are skipping storage for all authentication paths, you 101 | # may want to disable generating routes to Devise's sessions controller by 102 | # passing skip: :sessions to `devise_for` in your config/routes.rb 103 | config.skip_session_storage = [:http_auth] 104 | 105 | # By default, Devise cleans up the CSRF token on authentication to 106 | # avoid CSRF token fixation attacks. This means that, when using AJAX 107 | # requests for sign in and sign up, you need to get a new CSRF token 108 | # from the server. You can disable this option at your own risk. 109 | # config.clean_up_csrf_token_on_authentication = true 110 | 111 | # When false, Devise will not attempt to reload routes on eager load. 112 | # This can reduce the time taken to boot the app but if your application 113 | # requires the Devise mappings to be loaded during boot time the application 114 | # won't boot properly. 115 | # config.reload_routes = true 116 | 117 | # ==> Configuration for :database_authenticatable 118 | # For bcrypt, this is the cost for hashing the password and defaults to 12. If 119 | # using other algorithms, it sets how many times you want the password to be hashed. 120 | # The number of stretches used for generating the hashed password are stored 121 | # with the hashed password. This allows you to change the stretches without 122 | # invalidating existing passwords. 123 | # 124 | # Limiting the stretches to just one in testing will increase the performance of 125 | # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use 126 | # a value less than 10 in other environments. Note that, for bcrypt (the default 127 | # algorithm), the cost increases exponentially with the number of stretches (e.g. 128 | # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation). 129 | config.stretches = Rails.env.test? ? 1 : 12 130 | 131 | # Set up a pepper to generate the hashed password. 132 | # config.pepper = '6a5f75727f8d184a2c8f2d532eb0e8d7f6fcaea5b7dcb6587842b538bda86349c84e170fc964e63867a801df6d35259d03aed1aec2852898f6f80db1c34b6803' 133 | 134 | # Send a notification to the original email when the user's email is changed. 135 | # config.send_email_changed_notification = false 136 | 137 | # Send a notification email when the user's password is changed. 138 | # config.send_password_change_notification = false 139 | 140 | # ==> Configuration for :confirmable 141 | # A period that the user is allowed to access the website even without 142 | # confirming their account. For instance, if set to 2.days, the user will be 143 | # able to access the website for two days without confirming their account, 144 | # access will be blocked just in the third day. 145 | # You can also set it to nil, which will allow the user to access the website 146 | # without confirming their account. 147 | # Default is 0.days, meaning the user cannot access the website without 148 | # confirming their account. 149 | # config.allow_unconfirmed_access_for = 2.days 150 | 151 | # A period that the user is allowed to confirm their account before their 152 | # token becomes invalid. For example, if set to 3.days, the user can confirm 153 | # their account within 3 days after the mail was sent, but on the fourth day 154 | # their account can't be confirmed with the token any more. 155 | # Default is nil, meaning there is no restriction on how long a user can take 156 | # before confirming their account. 157 | # config.confirm_within = 3.days 158 | 159 | # If true, requires any email changes to be confirmed (exactly the same way as 160 | # initial account confirmation) to be applied. Requires additional unconfirmed_email 161 | # db field (see migrations). Until confirmed, new email is stored in 162 | # unconfirmed_email column, and copied to email column on successful confirmation. 163 | config.reconfirmable = true 164 | 165 | # Defines which key will be used when confirming an account 166 | # config.confirmation_keys = [:email] 167 | 168 | # ==> Configuration for :rememberable 169 | # The time the user will be remembered without asking for credentials again. 170 | # config.remember_for = 2.weeks 171 | 172 | # Invalidates all the remember me tokens when the user signs out. 173 | config.expire_all_remember_me_on_sign_out = true 174 | 175 | # If true, extends the user's remember period when remembered via cookie. 176 | # config.extend_remember_period = false 177 | 178 | # Options to be passed to the created cookie. For instance, you can set 179 | # secure: true in order to force SSL only cookies. 180 | # config.rememberable_options = {} 181 | 182 | # ==> Configuration for :validatable 183 | # Range for password length. 184 | config.password_length = 6..128 185 | 186 | # Email regex used to validate email formats. It simply asserts that 187 | # one (and only one) @ exists in the given string. This is mainly 188 | # to give user feedback and not to assert the e-mail validity. 189 | config.email_regexp = /\A[^@\s]+@[^@\s]+\z/ 190 | 191 | # ==> Configuration for :timeoutable 192 | # The time you want to timeout the user session without activity. After this 193 | # time the user will be asked for credentials again. Default is 30 minutes. 194 | # config.timeout_in = 30.minutes 195 | 196 | # ==> Configuration for :lockable 197 | # Defines which strategy will be used to lock an account. 198 | # :failed_attempts = Locks an account after a number of failed attempts to sign in. 199 | # :none = No lock strategy. You should handle locking by yourself. 200 | # config.lock_strategy = :failed_attempts 201 | 202 | # Defines which key will be used when locking and unlocking an account 203 | # config.unlock_keys = [:email] 204 | 205 | # Defines which strategy will be used to unlock an account. 206 | # :email = Sends an unlock link to the user email 207 | # :time = Re-enables login after a certain amount of time (see :unlock_in below) 208 | # :both = Enables both strategies 209 | # :none = No unlock strategy. You should handle unlocking by yourself. 210 | # config.unlock_strategy = :both 211 | 212 | # Number of authentication tries before locking an account if lock_strategy 213 | # is failed attempts. 214 | # config.maximum_attempts = 20 215 | 216 | # Time interval to unlock the account if :time is enabled as unlock_strategy. 217 | # config.unlock_in = 1.hour 218 | 219 | # Warn on the last attempt before the account is locked. 220 | # config.last_attempt_warning = true 221 | 222 | # ==> Configuration for :recoverable 223 | # 224 | # Defines which key will be used when recovering the password for an account 225 | # config.reset_password_keys = [:email] 226 | 227 | # Time interval you can reset your password with a reset password key. 228 | # Don't put a too small interval or your users won't have the time to 229 | # change their passwords. 230 | config.reset_password_within = 6.hours 231 | 232 | # When set to false, does not sign a user in automatically after their password is 233 | # reset. Defaults to true, so a user is signed in automatically after a reset. 234 | # config.sign_in_after_reset_password = true 235 | 236 | # ==> Configuration for :encryptable 237 | # Allow you to use another hashing or encryption algorithm besides bcrypt (default). 238 | # You can use :sha1, :sha512 or algorithms from others authentication tools as 239 | # :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20 240 | # for default behavior) and :restful_authentication_sha1 (then you should set 241 | # stretches to 10, and copy REST_AUTH_SITE_KEY to pepper). 242 | # 243 | # Require the `devise-encryptable` gem when using anything other than bcrypt 244 | # config.encryptor = :sha512 245 | 246 | # ==> Scopes configuration 247 | # Turn scoped views on. Before rendering "sessions/new", it will first check for 248 | # "users/sessions/new". It's turned off by default because it's slower if you 249 | # are using only default views. 250 | # config.scoped_views = false 251 | 252 | # Configure the default scope given to Warden. By default it's the first 253 | # devise role declared in your routes (usually :user). 254 | # config.default_scope = :user 255 | 256 | # Set this configuration to false if you want /users/sign_out to sign out 257 | # only the current scope. By default, Devise signs out all scopes. 258 | # config.sign_out_all_scopes = true 259 | 260 | # ==> Navigation configuration 261 | # Lists the formats that should be treated as navigational. Formats like 262 | # :html, should redirect to the sign in page when the user does not have 263 | # access, but formats like :xml or :json, should return 401. 264 | # 265 | # If you have any extra navigational formats, like :iphone or :mobile, you 266 | # should add them to the navigational formats lists. 267 | # 268 | # The "*/*" below is required to match Internet Explorer requests. 269 | # config.navigational_formats = ['*/*', :html] 270 | 271 | # The default HTTP method used to sign out a resource. Default is :delete. 272 | config.sign_out_via = :delete 273 | 274 | # ==> OmniAuth 275 | # Add a new OmniAuth provider. Check the wiki for more information on setting 276 | # up on your models and hooks. 277 | # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo' 278 | 279 | # ==> Warden configuration 280 | # If you want to use other strategies, that are not supported by Devise, or 281 | # change the failure app, you can configure them inside the config.warden block. 282 | # 283 | # config.warden do |manager| 284 | # manager.intercept_401 = false 285 | # manager.default_strategies(scope: :user).unshift :some_external_strategy 286 | # end 287 | 288 | # ==> Mountable engine configurations 289 | # When using Devise inside an engine, let's call it `MyEngine`, and this engine 290 | # is mountable, there are some extra configurations to be taken into account. 291 | # The following options are available, assuming the engine is mounted as: 292 | # 293 | # mount MyEngine, at: '/my_engine' 294 | # 295 | # The router that invoked `devise_for`, in the example above, would be: 296 | # config.router_name = :my_engine 297 | # 298 | # When using OmniAuth, Devise cannot automatically set OmniAuth path, 299 | # so you need to do it manually. For the users scope, it would be: 300 | # config.omniauth_path_prefix = '/my_engine/users/auth' 301 | 302 | # ==> Turbolinks configuration 303 | # If your app is using Turbolinks, Turbolinks::Controller needs to be included to make redirection work correctly: 304 | # 305 | # ActiveSupport.on_load(:devise_failure_app) do 306 | # include Turbolinks::Controller 307 | # end 308 | 309 | # ==> Configuration for :registerable 310 | 311 | # When set to false, does not sign a user in automatically after their password is 312 | # changed. Defaults to true, so a user is signed in automatically after changing a password. 313 | # config.sign_in_after_change_password = true 314 | end 315 | -------------------------------------------------------------------------------- /test/dummy/log/test.log: -------------------------------------------------------------------------------- 1 |  (0.5ms) SELECT sqlite_version(*) 2 |  (0.5ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL PRIMARY KEY) 3 |  (0.4ms) CREATE TABLE "ar_internal_metadata" ("key" varchar NOT NULL PRIMARY KEY, "value" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 4 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 5 |  (0.5ms) SELECT sqlite_version(*) 6 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 7 | Migrating to CreateUsers (1) 8 | TRANSACTION (0.0ms) begin transaction 9 |  (0.2ms) CREATE TABLE "users" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "encrypted_password" varchar DEFAULT '' NOT NULL, "reset_password_token" varchar, "reset_password_sent_at" datetime, "remember_created_at" datetime, "sign_in_count" integer DEFAULT 0 NOT NULL, "current_sign_in_at" datetime, "last_sign_in_at" datetime, "current_sign_in_ip" varchar, "last_sign_in_ip" varchar, "confirmed_at" datetime, "confirmation_sent_at" datetime, "unconfirmed_email" varchar, "email" varchar DEFAULT '' NOT NULL, "first_name" varchar, "last_name" varchar, "roles_mask" integer, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 10 |  (0.0ms) CREATE UNIQUE INDEX "index_users_on_email" ON "users" ("email") 11 | ActiveRecord::SchemaMigration Create (0.0ms) INSERT INTO "schema_migrations" ("version") VALUES (?) [["version", "1"]] 12 | TRANSACTION (0.6ms) commit transaction 13 | Migrating to CreateActionTextTables (2) 14 | TRANSACTION (0.0ms) begin transaction 15 |  (0.1ms) CREATE TABLE "action_text_rich_texts" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "body" text, "record_type" varchar NOT NULL, "record_id" integer NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 16 |  (0.0ms) CREATE UNIQUE INDEX "index_action_text_rich_texts_uniqueness" ON "action_text_rich_texts" ("record_type", "record_id", "name") 17 | ActiveRecord::SchemaMigration Create (0.0ms) INSERT INTO "schema_migrations" ("version") VALUES (?) [["version", "2"]] 18 | TRANSACTION (0.3ms) commit transaction 19 | Migrating to CreateActiveStorageTables (3) 20 | TRANSACTION (0.0ms) begin transaction 21 |  (0.1ms) CREATE TABLE "active_storage_blobs" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "key" varchar NOT NULL, "filename" varchar NOT NULL, "content_type" varchar, "metadata" text, "service_name" varchar NOT NULL, "byte_size" bigint NOT NULL, "checksum" varchar NOT NULL, "created_at" datetime NOT NULL) 22 |  (0.0ms) CREATE UNIQUE INDEX "index_active_storage_blobs_on_key" ON "active_storage_blobs" ("key") 23 |  (0.0ms) CREATE TABLE "active_storage_attachments" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "record_type" varchar NOT NULL, "record_id" integer NOT NULL, "blob_id" integer NOT NULL, "created_at" datetime NOT NULL, CONSTRAINT "fk_rails_c3b3935057" 24 | FOREIGN KEY ("blob_id") 25 | REFERENCES "active_storage_blobs" ("id") 26 | ) 27 |  (0.0ms) CREATE INDEX "index_active_storage_attachments_on_blob_id" ON "active_storage_attachments" ("blob_id") 28 |  (0.0ms) CREATE UNIQUE INDEX "index_active_storage_attachments_uniqueness" ON "active_storage_attachments" ("record_type", "record_id", "name", "blob_id") 29 |  (0.0ms) CREATE TABLE "active_storage_variant_records" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "blob_id" integer NOT NULL, "variation_digest" varchar NOT NULL, CONSTRAINT "fk_rails_993965df05" 30 | FOREIGN KEY ("blob_id") 31 | REFERENCES "active_storage_blobs" ("id") 32 | ) 33 |  (0.0ms) CREATE UNIQUE INDEX "index_active_storage_variant_records_uniqueness" ON "active_storage_variant_records" ("blob_id", "variation_digest") 34 | ActiveRecord::SchemaMigration Create (0.0ms) INSERT INTO "schema_migrations" ("version") VALUES (?) [["version", "3"]] 35 | TRANSACTION (0.3ms) commit transaction 36 | Migrating to CreateEffectiveAddresses (101) 37 | TRANSACTION (0.0ms) begin transaction 38 |  (0.1ms) CREATE TABLE "addresses" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "template_name" varchar, "subject" varchar, "from" varchar, "bcc" varchar, "cc" varchar, "content_type" varchar, "body" text, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 39 | ActiveRecord::SchemaMigration Create (0.0ms) INSERT INTO "schema_migrations" ("version") VALUES (?) [["version", "101"]] 40 | TRANSACTION (0.2ms) commit transaction 41 | ActiveRecord::InternalMetadata Load (0.0ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? LIMIT ? [["key", "environment"], ["LIMIT", 1]] 42 | TRANSACTION (0.0ms) begin transaction 43 | ActiveRecord::InternalMetadata Create (0.1ms) INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["key", "environment"], ["value", "test"], ["created_at", "2023-08-24 17:07:37.255418"], ["updated_at", "2023-08-24 17:07:37.255418"]] 44 | TRANSACTION (0.2ms) commit transaction 45 |  (0.0ms) SELECT sqlite_version(*) 46 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 47 |  (0.5ms) SELECT sqlite_version(*) 48 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 49 |  (0.5ms) SELECT sqlite_version(*) 50 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 51 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "environment"]] 52 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 53 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "environment"]] 54 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 55 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "environment"]] 56 |  (0.0ms) SELECT sqlite_version(*) 57 |  (0.0ms) SELECT sqlite_version(*) 58 |  (0.0ms) DROP TABLE IF EXISTS "action_text_rich_texts" 59 |  (0.8ms) CREATE TABLE "action_text_rich_texts" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "body" text, "record_type" varchar NOT NULL, "record_id" integer NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 60 |  (0.3ms) CREATE UNIQUE INDEX "index_action_text_rich_texts_uniqueness" ON "action_text_rich_texts" ("record_type", "record_id", "name") 61 |  (0.0ms) DROP TABLE IF EXISTS "active_storage_attachments" 62 |  (0.3ms) CREATE TABLE "active_storage_attachments" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "record_type" varchar NOT NULL, "record_id" integer NOT NULL, "blob_id" integer NOT NULL, "created_at" datetime NOT NULL) 63 |  (0.3ms) CREATE INDEX "index_active_storage_attachments_on_blob_id" ON "active_storage_attachments" ("blob_id") 64 |  (0.2ms) CREATE UNIQUE INDEX "index_active_storage_attachments_uniqueness" ON "active_storage_attachments" ("record_type", "record_id", "name", "blob_id") 65 |  (0.0ms) DROP TABLE IF EXISTS "active_storage_blobs" 66 |  (0.3ms) CREATE TABLE "active_storage_blobs" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "key" varchar NOT NULL, "filename" varchar NOT NULL, "content_type" varchar, "metadata" text, "service_name" varchar NOT NULL, "byte_size" bigint NOT NULL, "checksum" varchar NOT NULL, "created_at" datetime NOT NULL) 67 |  (0.2ms) CREATE UNIQUE INDEX "index_active_storage_blobs_on_key" ON "active_storage_blobs" ("key") 68 |  (0.0ms) DROP TABLE IF EXISTS "active_storage_variant_records" 69 |  (0.2ms) CREATE TABLE "active_storage_variant_records" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "blob_id" integer NOT NULL, "variation_digest" varchar NOT NULL) 70 |  (0.2ms) CREATE UNIQUE INDEX "index_active_storage_variant_records_uniqueness" ON "active_storage_variant_records" ("blob_id", "variation_digest") 71 |  (0.0ms) DROP TABLE IF EXISTS "addresses" 72 |  (0.3ms) CREATE TABLE "addresses" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "template_name" varchar, "subject" varchar, "from" varchar, "bcc" varchar, "cc" varchar, "content_type" varchar, "body" text, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 73 |  (0.0ms) DROP TABLE IF EXISTS "users" 74 |  (0.3ms) CREATE TABLE "users" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "encrypted_password" varchar DEFAULT '' NOT NULL, "reset_password_token" varchar, "reset_password_sent_at" datetime, "remember_created_at" datetime, "sign_in_count" integer DEFAULT 0 NOT NULL, "current_sign_in_at" datetime, "last_sign_in_at" datetime, "current_sign_in_ip" varchar, "last_sign_in_ip" varchar, "confirmed_at" datetime, "confirmation_sent_at" datetime, "unconfirmed_email" varchar, "email" varchar DEFAULT '' NOT NULL, "first_name" varchar, "last_name" varchar, "roles_mask" integer, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 75 |  (0.3ms) CREATE UNIQUE INDEX "index_users_on_email" ON "users" ("email") 76 | TRANSACTION (0.0ms) begin transaction 77 |  (0.0ms) PRAGMA foreign_keys 78 |  (0.0ms) PRAGMA defer_foreign_keys 79 |  (0.0ms) PRAGMA defer_foreign_keys = ON 80 |  (0.0ms) PRAGMA foreign_keys = OFF 81 |  (0.0ms) CREATE TEMPORARY TABLE "aactive_storage_attachments" ("id" integer NOT NULL PRIMARY KEY, "name" varchar NOT NULL, "record_type" varchar NOT NULL, "record_id" integer NOT NULL, "blob_id" integer NOT NULL, "created_at" datetime NOT NULL) 82 |  (0.0ms) CREATE UNIQUE INDEX "tindex_aactive_storage_attachments_uniqueness" ON "aactive_storage_attachments" ("record_type", "record_id", "name", "blob_id") 83 |  (0.0ms) CREATE INDEX "tindex_aactive_storage_attachments_on_blob_id" ON "aactive_storage_attachments" ("blob_id") 84 |  (0.0ms) INSERT INTO "aactive_storage_attachments" ("id","name","record_type","record_id","blob_id","created_at") 85 | SELECT "id","name","record_type","record_id","blob_id","created_at" FROM "active_storage_attachments" 86 |  (0.1ms) DROP TABLE "active_storage_attachments" 87 |  (0.0ms) CREATE TABLE "active_storage_attachments" ("id" integer NOT NULL PRIMARY KEY, "name" varchar NOT NULL, "record_type" varchar NOT NULL, "record_id" integer NOT NULL, "blob_id" integer NOT NULL, "created_at" datetime NOT NULL, CONSTRAINT "fk_rails_c3b3935057" 88 | FOREIGN KEY ("blob_id") 89 | REFERENCES "active_storage_blobs" ("id") 90 | ) 91 |  (0.0ms) CREATE INDEX "index_active_storage_attachments_on_blob_id" ON "active_storage_attachments" ("blob_id") 92 |  (0.0ms) CREATE UNIQUE INDEX "index_active_storage_attachments_uniqueness" ON "active_storage_attachments" ("record_type", "record_id", "name", "blob_id") 93 |  (0.0ms) INSERT INTO "active_storage_attachments" ("id","name","record_type","record_id","blob_id","created_at") 94 | SELECT "id","name","record_type","record_id","blob_id","created_at" FROM "aactive_storage_attachments" 95 |  (0.0ms) DROP TABLE "aactive_storage_attachments" 96 |  (0.0ms) PRAGMA defer_foreign_keys = 0 97 |  (0.0ms) PRAGMA foreign_keys = 1 98 | TRANSACTION (0.2ms) commit transaction 99 | TRANSACTION (0.0ms) begin transaction 100 |  (0.0ms) PRAGMA foreign_keys 101 |  (0.0ms) PRAGMA defer_foreign_keys 102 |  (0.0ms) PRAGMA defer_foreign_keys = ON 103 |  (0.0ms) PRAGMA foreign_keys = OFF 104 |  (0.0ms) CREATE TEMPORARY TABLE "aactive_storage_variant_records" ("id" integer NOT NULL PRIMARY KEY, "blob_id" integer NOT NULL, "variation_digest" varchar NOT NULL) 105 |  (0.0ms) CREATE UNIQUE INDEX "tindex_aactive_storage_variant_records_uniqueness" ON "aactive_storage_variant_records" ("blob_id", "variation_digest") 106 |  (0.0ms) INSERT INTO "aactive_storage_variant_records" ("id","blob_id","variation_digest") 107 | SELECT "id","blob_id","variation_digest" FROM "active_storage_variant_records" 108 |  (0.1ms) DROP TABLE "active_storage_variant_records" 109 |  (0.0ms) CREATE TABLE "active_storage_variant_records" ("id" integer NOT NULL PRIMARY KEY, "blob_id" integer NOT NULL, "variation_digest" varchar NOT NULL, CONSTRAINT "fk_rails_993965df05" 110 | FOREIGN KEY ("blob_id") 111 | REFERENCES "active_storage_blobs" ("id") 112 | ) 113 |  (0.0ms) CREATE UNIQUE INDEX "index_active_storage_variant_records_uniqueness" ON "active_storage_variant_records" ("blob_id", "variation_digest") 114 |  (0.0ms) INSERT INTO "active_storage_variant_records" ("id","blob_id","variation_digest") 115 | SELECT "id","blob_id","variation_digest" FROM "aactive_storage_variant_records" 116 |  (0.0ms) DROP TABLE "aactive_storage_variant_records" 117 |  (0.0ms) PRAGMA defer_foreign_keys = 0 118 |  (0.0ms) PRAGMA foreign_keys = 1 119 | TRANSACTION (0.3ms) commit transaction 120 |  (0.3ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL PRIMARY KEY) 121 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 122 |  (0.3ms) INSERT INTO "schema_migrations" (version) VALUES (101) 123 |  (0.3ms) INSERT INTO "schema_migrations" (version) VALUES 124 | (1), 125 | (2), 126 | (3); 127 | 128 |  129 |  (0.3ms) CREATE TABLE "ar_internal_metadata" ("key" varchar NOT NULL PRIMARY KEY, "value" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 130 | ActiveRecord::InternalMetadata Load (0.0ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? LIMIT ? [["key", "environment"], ["LIMIT", 1]] 131 | TRANSACTION (0.0ms) begin transaction 132 | ActiveRecord::InternalMetadata Create (0.1ms) INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["key", "environment"], ["value", "test"], ["created_at", "2023-08-24 17:07:40.774842"], ["updated_at", "2023-08-24 17:07:40.774842"]] 133 | TRANSACTION (0.2ms) commit transaction 134 | ActiveRecord::InternalMetadata Load (0.0ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? LIMIT ? [["key", "environment"], ["LIMIT", 1]] 135 | ActiveRecord::InternalMetadata Load (0.0ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? LIMIT ? [["key", "schema_sha1"], ["LIMIT", 1]] 136 | TRANSACTION (0.0ms) begin transaction 137 | ActiveRecord::InternalMetadata Create (0.1ms) INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["key", "schema_sha1"], ["value", "8730ac824095739ec3951b40a743a96e65e733a7"], ["created_at", "2023-08-24 17:07:40.775875"], ["updated_at", "2023-08-24 17:07:40.775875"]] 138 | TRANSACTION (0.2ms) commit transaction 139 |  (0.0ms) SELECT sqlite_version(*) 140 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 141 |  (0.5ms) SELECT sqlite_version(*) 142 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 143 |  (0.0ms) SELECT sqlite_version(*) 144 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 145 | TRANSACTION (0.0ms) begin transaction 146 | --------------------------------- 147 | AddressesTest: test_is_valid 148 | --------------------------------- 149 | TRANSACTION (0.0ms) rollback transaction 150 | TRANSACTION (0.0ms) begin transaction 151 | --------------------------------------------------------- 152 | EffectiveAddressesTest: test_it_has_a_version_number 153 | --------------------------------------------------------- 154 | TRANSACTION (0.0ms) rollback transaction 155 |  (0.4ms) SELECT sqlite_version(*) 156 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 157 |  (0.0ms) SELECT sqlite_version(*) 158 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 159 | TRANSACTION (0.0ms) begin transaction 160 | ---------------------------------------------------- 161 | EffectiveAddressesTest: test_it_has_a_version_number 162 | ---------------------------------------------------- 163 | TRANSACTION (0.0ms) rollback transaction 164 | TRANSACTION (0.0ms) begin transaction 165 | ---------------------------- 166 | AddressesTest: test_is_valid 167 | ---------------------------- 168 | TRANSACTION (0.0ms) rollback transaction 169 |  (0.5ms) SELECT sqlite_version(*) 170 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 171 |  (0.4ms) SELECT sqlite_version(*) 172 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 173 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "environment"]] 174 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 175 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "environment"]] 176 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 177 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "environment"]] 178 |  (0.0ms) SELECT sqlite_version(*) 179 |  (0.0ms) SELECT sqlite_version(*) 180 |  (0.0ms) DROP TABLE IF EXISTS "action_text_rich_texts" 181 |  (0.5ms) CREATE TABLE "action_text_rich_texts" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "body" text, "record_type" varchar NOT NULL, "record_id" integer NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 182 |  (0.4ms) CREATE UNIQUE INDEX "index_action_text_rich_texts_uniqueness" ON "action_text_rich_texts" ("record_type", "record_id", "name") 183 |  (0.0ms) DROP TABLE IF EXISTS "active_storage_attachments" 184 |  (0.3ms) CREATE TABLE "active_storage_attachments" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "record_type" varchar NOT NULL, "record_id" integer NOT NULL, "blob_id" integer NOT NULL, "created_at" datetime NOT NULL) 185 |  (0.3ms) CREATE INDEX "index_active_storage_attachments_on_blob_id" ON "active_storage_attachments" ("blob_id") 186 |  (0.3ms) CREATE UNIQUE INDEX "index_active_storage_attachments_uniqueness" ON "active_storage_attachments" ("record_type", "record_id", "name", "blob_id") 187 |  (0.0ms) DROP TABLE IF EXISTS "active_storage_blobs" 188 |  (0.3ms) CREATE TABLE "active_storage_blobs" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "key" varchar NOT NULL, "filename" varchar NOT NULL, "content_type" varchar, "metadata" text, "service_name" varchar NOT NULL, "byte_size" bigint NOT NULL, "checksum" varchar NOT NULL, "created_at" datetime NOT NULL) 189 |  (0.3ms) CREATE UNIQUE INDEX "index_active_storage_blobs_on_key" ON "active_storage_blobs" ("key") 190 |  (0.0ms) DROP TABLE IF EXISTS "active_storage_variant_records" 191 |  (0.3ms) CREATE TABLE "active_storage_variant_records" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "blob_id" integer NOT NULL, "variation_digest" varchar NOT NULL) 192 |  (0.3ms) CREATE UNIQUE INDEX "index_active_storage_variant_records_uniqueness" ON "active_storage_variant_records" ("blob_id", "variation_digest") 193 |  (0.0ms) DROP TABLE IF EXISTS "addresses" 194 |  (0.3ms) CREATE TABLE "addresses" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "template_name" varchar, "subject" varchar, "from" varchar, "bcc" varchar, "cc" varchar, "content_type" varchar, "body" text, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 195 |  (0.0ms) DROP TABLE IF EXISTS "users" 196 |  (0.3ms) CREATE TABLE "users" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "encrypted_password" varchar DEFAULT '' NOT NULL, "reset_password_token" varchar, "reset_password_sent_at" datetime, "remember_created_at" datetime, "sign_in_count" integer DEFAULT 0 NOT NULL, "current_sign_in_at" datetime, "last_sign_in_at" datetime, "current_sign_in_ip" varchar, "last_sign_in_ip" varchar, "confirmed_at" datetime, "confirmation_sent_at" datetime, "unconfirmed_email" varchar, "email" varchar DEFAULT '' NOT NULL, "first_name" varchar, "last_name" varchar, "roles_mask" integer, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 197 |  (0.3ms) CREATE UNIQUE INDEX "index_users_on_email" ON "users" ("email") 198 | TRANSACTION (0.0ms) begin transaction 199 |  (0.0ms) PRAGMA foreign_keys 200 |  (0.0ms) PRAGMA defer_foreign_keys 201 |  (0.0ms) PRAGMA defer_foreign_keys = ON 202 |  (0.0ms) PRAGMA foreign_keys = OFF 203 |  (0.0ms) CREATE TEMPORARY TABLE "aactive_storage_attachments" ("id" integer NOT NULL PRIMARY KEY, "name" varchar NOT NULL, "record_type" varchar NOT NULL, "record_id" integer NOT NULL, "blob_id" integer NOT NULL, "created_at" datetime NOT NULL) 204 |  (0.0ms) CREATE UNIQUE INDEX "tindex_aactive_storage_attachments_uniqueness" ON "aactive_storage_attachments" ("record_type", "record_id", "name", "blob_id") 205 |  (0.0ms) CREATE INDEX "tindex_aactive_storage_attachments_on_blob_id" ON "aactive_storage_attachments" ("blob_id") 206 |  (0.0ms) INSERT INTO "aactive_storage_attachments" ("id","name","record_type","record_id","blob_id","created_at") 207 | SELECT "id","name","record_type","record_id","blob_id","created_at" FROM "active_storage_attachments" 208 |  (0.1ms) DROP TABLE "active_storage_attachments" 209 |  (0.0ms) CREATE TABLE "active_storage_attachments" ("id" integer NOT NULL PRIMARY KEY, "name" varchar NOT NULL, "record_type" varchar NOT NULL, "record_id" integer NOT NULL, "blob_id" integer NOT NULL, "created_at" datetime NOT NULL, CONSTRAINT "fk_rails_c3b3935057" 210 | FOREIGN KEY ("blob_id") 211 | REFERENCES "active_storage_blobs" ("id") 212 | ) 213 |  (0.0ms) CREATE INDEX "index_active_storage_attachments_on_blob_id" ON "active_storage_attachments" ("blob_id") 214 |  (0.0ms) CREATE UNIQUE INDEX "index_active_storage_attachments_uniqueness" ON "active_storage_attachments" ("record_type", "record_id", "name", "blob_id") 215 |  (0.0ms) INSERT INTO "active_storage_attachments" ("id","name","record_type","record_id","blob_id","created_at") 216 | SELECT "id","name","record_type","record_id","blob_id","created_at" FROM "aactive_storage_attachments" 217 |  (0.0ms) DROP TABLE "aactive_storage_attachments" 218 |  (0.0ms) PRAGMA defer_foreign_keys = 0 219 |  (0.0ms) PRAGMA foreign_keys = 1 220 | TRANSACTION (0.2ms) commit transaction 221 | TRANSACTION (0.0ms) begin transaction 222 |  (0.0ms) PRAGMA foreign_keys 223 |  (0.0ms) PRAGMA defer_foreign_keys 224 |  (0.0ms) PRAGMA defer_foreign_keys = ON 225 |  (0.0ms) PRAGMA foreign_keys = OFF 226 |  (0.0ms) CREATE TEMPORARY TABLE "aactive_storage_variant_records" ("id" integer NOT NULL PRIMARY KEY, "blob_id" integer NOT NULL, "variation_digest" varchar NOT NULL) 227 |  (0.0ms) CREATE UNIQUE INDEX "tindex_aactive_storage_variant_records_uniqueness" ON "aactive_storage_variant_records" ("blob_id", "variation_digest") 228 |  (0.0ms) INSERT INTO "aactive_storage_variant_records" ("id","blob_id","variation_digest") 229 | SELECT "id","blob_id","variation_digest" FROM "active_storage_variant_records" 230 |  (0.1ms) DROP TABLE "active_storage_variant_records" 231 |  (0.0ms) CREATE TABLE "active_storage_variant_records" ("id" integer NOT NULL PRIMARY KEY, "blob_id" integer NOT NULL, "variation_digest" varchar NOT NULL, CONSTRAINT "fk_rails_993965df05" 232 | FOREIGN KEY ("blob_id") 233 | REFERENCES "active_storage_blobs" ("id") 234 | ) 235 |  (0.0ms) CREATE UNIQUE INDEX "index_active_storage_variant_records_uniqueness" ON "active_storage_variant_records" ("blob_id", "variation_digest") 236 |  (0.0ms) INSERT INTO "active_storage_variant_records" ("id","blob_id","variation_digest") 237 | SELECT "id","blob_id","variation_digest" FROM "aactive_storage_variant_records" 238 |  (0.0ms) DROP TABLE "aactive_storage_variant_records" 239 |  (0.0ms) PRAGMA defer_foreign_keys = 0 240 |  (0.0ms) PRAGMA foreign_keys = 1 241 | TRANSACTION (0.2ms) commit transaction 242 |  (0.2ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL PRIMARY KEY) 243 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 244 |  (0.3ms) INSERT INTO "schema_migrations" (version) VALUES (101) 245 |  (0.3ms) INSERT INTO "schema_migrations" (version) VALUES 246 | (1), 247 | (2), 248 | (3); 249 | 250 |  251 |  (0.3ms) CREATE TABLE "ar_internal_metadata" ("key" varchar NOT NULL PRIMARY KEY, "value" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 252 | ActiveRecord::InternalMetadata Load (0.0ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? LIMIT ? [["key", "environment"], ["LIMIT", 1]] 253 | TRANSACTION (0.0ms) begin transaction 254 | ActiveRecord::InternalMetadata Create (0.1ms) INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["key", "environment"], ["value", "test"], ["created_at", "2023-08-24 19:23:53.230738"], ["updated_at", "2023-08-24 19:23:53.230738"]] 255 | TRANSACTION (0.2ms) commit transaction 256 | ActiveRecord::InternalMetadata Load (0.0ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? LIMIT ? [["key", "environment"], ["LIMIT", 1]] 257 | ActiveRecord::InternalMetadata Load (0.0ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? LIMIT ? [["key", "schema_sha1"], ["LIMIT", 1]] 258 | TRANSACTION (0.0ms) begin transaction 259 | ActiveRecord::InternalMetadata Create (0.1ms) INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["key", "schema_sha1"], ["value", "def4b1225bdbc5ac194188fd106c08626bd7a918"], ["created_at", "2023-08-24 19:23:53.231900"], ["updated_at", "2023-08-24 19:23:53.231900"]] 260 | TRANSACTION (0.2ms) commit transaction 261 |  (0.0ms) SELECT sqlite_version(*) 262 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 263 | TRANSACTION (0.0ms) begin transaction 264 | ---------------------------- 265 | AddressesTest: test_is_valid 266 | ---------------------------- 267 | TRANSACTION (0.0ms) rollback transaction 268 | TRANSACTION (0.0ms) begin transaction 269 | ---------------------------------------------------- 270 | EffectiveAddressesTest: test_it_has_a_version_number 271 | ---------------------------------------------------- 272 | TRANSACTION (0.0ms) rollback transaction 273 |  (0.5ms) SELECT sqlite_version(*) 274 |  (0.1ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 275 |  (0.0ms) SELECT sqlite_version(*) 276 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 277 | TRANSACTION (0.0ms) begin transaction 278 | ---------------------------------------------------- 279 | EffectiveAddressesTest: test_it_has_a_version_number 280 | ---------------------------------------------------- 281 | TRANSACTION (0.0ms) rollback transaction 282 | TRANSACTION (0.0ms) begin transaction 283 | ---------------------------- 284 | AddressesTest: test_is_valid 285 | ---------------------------- 286 | TRANSACTION (0.0ms) rollback transaction 287 |  (0.4ms) SELECT sqlite_version(*) 288 |  (0.8ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL PRIMARY KEY) 289 |  (0.4ms) CREATE TABLE "ar_internal_metadata" ("key" varchar NOT NULL PRIMARY KEY, "value" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 290 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 291 |  (0.5ms) SELECT sqlite_version(*) 292 |  (0.2ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 293 | Migrating to CreateUsers (1) 294 | TRANSACTION (0.0ms) begin transaction 295 |  (0.3ms) CREATE TABLE "users" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "encrypted_password" varchar DEFAULT '' NOT NULL, "reset_password_token" varchar, "reset_password_sent_at" datetime, "remember_created_at" datetime, "sign_in_count" integer DEFAULT 0 NOT NULL, "current_sign_in_at" datetime, "last_sign_in_at" datetime, "current_sign_in_ip" varchar, "last_sign_in_ip" varchar, "confirmed_at" datetime, "confirmation_sent_at" datetime, "unconfirmed_email" varchar, "email" varchar DEFAULT '' NOT NULL, "first_name" varchar, "last_name" varchar, "roles_mask" integer, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 296 |  (0.0ms) CREATE UNIQUE INDEX "index_users_on_email" ON "users" ("email") 297 | ActiveRecord::SchemaMigration Create (0.0ms) INSERT INTO "schema_migrations" ("version") VALUES (?) [["version", "1"]] 298 | TRANSACTION (0.6ms) commit transaction 299 | Migrating to CreateActionTextTables (2) 300 | TRANSACTION (0.0ms) begin transaction 301 |  (0.1ms) CREATE TABLE "action_text_rich_texts" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "body" text, "record_type" varchar NOT NULL, "record_id" integer NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 302 |  (0.0ms) CREATE UNIQUE INDEX "index_action_text_rich_texts_uniqueness" ON "action_text_rich_texts" ("record_type", "record_id", "name") 303 | ActiveRecord::SchemaMigration Create (0.0ms) INSERT INTO "schema_migrations" ("version") VALUES (?) [["version", "2"]] 304 | TRANSACTION (0.3ms) commit transaction 305 | Migrating to CreateActiveStorageTables (3) 306 | TRANSACTION (0.0ms) begin transaction 307 |  (0.1ms) CREATE TABLE "active_storage_blobs" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "key" varchar NOT NULL, "filename" varchar NOT NULL, "content_type" varchar, "metadata" text, "service_name" varchar NOT NULL, "byte_size" bigint NOT NULL, "checksum" varchar NOT NULL, "created_at" datetime NOT NULL) 308 |  (0.0ms) CREATE UNIQUE INDEX "index_active_storage_blobs_on_key" ON "active_storage_blobs" ("key") 309 |  (0.0ms) CREATE TABLE "active_storage_attachments" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "record_type" varchar NOT NULL, "record_id" integer NOT NULL, "blob_id" integer NOT NULL, "created_at" datetime NOT NULL, CONSTRAINT "fk_rails_c3b3935057" 310 | FOREIGN KEY ("blob_id") 311 | REFERENCES "active_storage_blobs" ("id") 312 | ) 313 |  (0.0ms) CREATE INDEX "index_active_storage_attachments_on_blob_id" ON "active_storage_attachments" ("blob_id") 314 |  (0.0ms) CREATE UNIQUE INDEX "index_active_storage_attachments_uniqueness" ON "active_storage_attachments" ("record_type", "record_id", "name", "blob_id") 315 |  (0.0ms) CREATE TABLE "active_storage_variant_records" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "blob_id" integer NOT NULL, "variation_digest" varchar NOT NULL, CONSTRAINT "fk_rails_993965df05" 316 | FOREIGN KEY ("blob_id") 317 | REFERENCES "active_storage_blobs" ("id") 318 | ) 319 |  (0.0ms) CREATE UNIQUE INDEX "index_active_storage_variant_records_uniqueness" ON "active_storage_variant_records" ("blob_id", "variation_digest") 320 | ActiveRecord::SchemaMigration Create (0.0ms) INSERT INTO "schema_migrations" ("version") VALUES (?) [["version", "3"]] 321 | TRANSACTION (0.3ms) commit transaction 322 | Migrating to CreateEffectiveAddresses (101) 323 | TRANSACTION (0.0ms) begin transaction 324 |  (0.1ms) CREATE TABLE "addresses" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "addressable_type" varchar, "addressable_id" integer, "category" varchar(64), "full_name" varchar, "address1" varchar, "address2" varchar, "address3" varchar, "city" varchar, "state_code" varchar, "country_code" varchar, "postal_code" varchar, "updated_at" datetime, "created_at" datetime) 325 |  (0.0ms) CREATE INDEX "index_addresses_on_addressable_type_and_addressable_id" ON "addresses" ("addressable_type", "addressable_id") 326 |  (0.0ms) CREATE INDEX "index_addresses_on_addressable_id" ON "addresses" ("addressable_id") 327 | ActiveRecord::SchemaMigration Create (0.0ms) INSERT INTO "schema_migrations" ("version") VALUES (?) [["version", "101"]] 328 | TRANSACTION (0.2ms) commit transaction 329 | ActiveRecord::InternalMetadata Load (0.0ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? LIMIT ? [["key", "environment"], ["LIMIT", 1]] 330 | TRANSACTION (0.0ms) begin transaction 331 | ActiveRecord::InternalMetadata Create (0.1ms) INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["key", "environment"], ["value", "test"], ["created_at", "2023-08-24 19:24:53.925111"], ["updated_at", "2023-08-24 19:24:53.925111"]] 332 | TRANSACTION (0.2ms) commit transaction 333 |  (0.0ms) SELECT sqlite_version(*) 334 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 335 |  (0.4ms) SELECT sqlite_version(*) 336 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 337 |  (0.6ms) SELECT sqlite_version(*) 338 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 339 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "environment"]] 340 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 341 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "environment"]] 342 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 343 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "environment"]] 344 |  (0.0ms) SELECT sqlite_version(*) 345 |  (0.0ms) SELECT sqlite_version(*) 346 |  (0.0ms) DROP TABLE IF EXISTS "action_text_rich_texts" 347 |  (0.8ms) CREATE TABLE "action_text_rich_texts" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "body" text, "record_type" varchar NOT NULL, "record_id" integer NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 348 |  (0.4ms) CREATE UNIQUE INDEX "index_action_text_rich_texts_uniqueness" ON "action_text_rich_texts" ("record_type", "record_id", "name") 349 |  (0.0ms) DROP TABLE IF EXISTS "active_storage_attachments" 350 |  (0.3ms) CREATE TABLE "active_storage_attachments" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "record_type" varchar NOT NULL, "record_id" integer NOT NULL, "blob_id" integer NOT NULL, "created_at" datetime NOT NULL) 351 |  (0.3ms) CREATE INDEX "index_active_storage_attachments_on_blob_id" ON "active_storage_attachments" ("blob_id") 352 |  (0.3ms) CREATE UNIQUE INDEX "index_active_storage_attachments_uniqueness" ON "active_storage_attachments" ("record_type", "record_id", "name", "blob_id") 353 |  (0.0ms) DROP TABLE IF EXISTS "active_storage_blobs" 354 |  (0.3ms) CREATE TABLE "active_storage_blobs" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "key" varchar NOT NULL, "filename" varchar NOT NULL, "content_type" varchar, "metadata" text, "service_name" varchar NOT NULL, "byte_size" bigint NOT NULL, "checksum" varchar NOT NULL, "created_at" datetime NOT NULL) 355 |  (0.2ms) CREATE UNIQUE INDEX "index_active_storage_blobs_on_key" ON "active_storage_blobs" ("key") 356 |  (0.0ms) DROP TABLE IF EXISTS "active_storage_variant_records" 357 |  (0.3ms) CREATE TABLE "active_storage_variant_records" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "blob_id" integer NOT NULL, "variation_digest" varchar NOT NULL) 358 |  (0.3ms) CREATE UNIQUE INDEX "index_active_storage_variant_records_uniqueness" ON "active_storage_variant_records" ("blob_id", "variation_digest") 359 |  (0.0ms) DROP TABLE IF EXISTS "addresses" 360 |  (0.2ms) CREATE TABLE "addresses" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "addressable_type" varchar, "addressable_id" integer, "category" varchar(64), "full_name" varchar, "address1" varchar, "address2" varchar, "address3" varchar, "city" varchar, "state_code" varchar, "country_code" varchar, "postal_code" varchar, "updated_at" datetime, "created_at" datetime) 361 |  (0.3ms) CREATE INDEX "index_addresses_on_addressable_id" ON "addresses" ("addressable_id") 362 |  (0.2ms) CREATE INDEX "index_addresses_on_addressable_type_and_addressable_id" ON "addresses" ("addressable_type", "addressable_id") 363 |  (0.0ms) DROP TABLE IF EXISTS "users" 364 |  (0.3ms) CREATE TABLE "users" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "encrypted_password" varchar DEFAULT '' NOT NULL, "reset_password_token" varchar, "reset_password_sent_at" datetime, "remember_created_at" datetime, "sign_in_count" integer DEFAULT 0 NOT NULL, "current_sign_in_at" datetime, "last_sign_in_at" datetime, "current_sign_in_ip" varchar, "last_sign_in_ip" varchar, "confirmed_at" datetime, "confirmation_sent_at" datetime, "unconfirmed_email" varchar, "email" varchar DEFAULT '' NOT NULL, "first_name" varchar, "last_name" varchar, "roles_mask" integer, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 365 |  (0.2ms) CREATE UNIQUE INDEX "index_users_on_email" ON "users" ("email") 366 | TRANSACTION (0.0ms) begin transaction 367 |  (0.0ms) PRAGMA foreign_keys 368 |  (0.0ms) PRAGMA defer_foreign_keys 369 |  (0.0ms) PRAGMA defer_foreign_keys = ON 370 |  (0.0ms) PRAGMA foreign_keys = OFF 371 |  (0.0ms) CREATE TEMPORARY TABLE "aactive_storage_attachments" ("id" integer NOT NULL PRIMARY KEY, "name" varchar NOT NULL, "record_type" varchar NOT NULL, "record_id" integer NOT NULL, "blob_id" integer NOT NULL, "created_at" datetime NOT NULL) 372 |  (0.0ms) CREATE UNIQUE INDEX "tindex_aactive_storage_attachments_uniqueness" ON "aactive_storage_attachments" ("record_type", "record_id", "name", "blob_id") 373 |  (0.0ms) CREATE INDEX "tindex_aactive_storage_attachments_on_blob_id" ON "aactive_storage_attachments" ("blob_id") 374 |  (0.0ms) INSERT INTO "aactive_storage_attachments" ("id","name","record_type","record_id","blob_id","created_at") 375 | SELECT "id","name","record_type","record_id","blob_id","created_at" FROM "active_storage_attachments" 376 |  (0.2ms) DROP TABLE "active_storage_attachments" 377 |  (0.0ms) CREATE TABLE "active_storage_attachments" ("id" integer NOT NULL PRIMARY KEY, "name" varchar NOT NULL, "record_type" varchar NOT NULL, "record_id" integer NOT NULL, "blob_id" integer NOT NULL, "created_at" datetime NOT NULL, CONSTRAINT "fk_rails_c3b3935057" 378 | FOREIGN KEY ("blob_id") 379 | REFERENCES "active_storage_blobs" ("id") 380 | ) 381 |  (0.0ms) CREATE INDEX "index_active_storage_attachments_on_blob_id" ON "active_storage_attachments" ("blob_id") 382 |  (0.0ms) CREATE UNIQUE INDEX "index_active_storage_attachments_uniqueness" ON "active_storage_attachments" ("record_type", "record_id", "name", "blob_id") 383 |  (0.0ms) INSERT INTO "active_storage_attachments" ("id","name","record_type","record_id","blob_id","created_at") 384 | SELECT "id","name","record_type","record_id","blob_id","created_at" FROM "aactive_storage_attachments" 385 |  (0.0ms) DROP TABLE "aactive_storage_attachments" 386 |  (0.0ms) PRAGMA defer_foreign_keys = 0 387 |  (0.0ms) PRAGMA foreign_keys = 1 388 | TRANSACTION (0.2ms) commit transaction 389 | TRANSACTION (0.0ms) begin transaction 390 |  (0.0ms) PRAGMA foreign_keys 391 |  (0.0ms) PRAGMA defer_foreign_keys 392 |  (0.0ms) PRAGMA defer_foreign_keys = ON 393 |  (0.0ms) PRAGMA foreign_keys = OFF 394 |  (0.0ms) CREATE TEMPORARY TABLE "aactive_storage_variant_records" ("id" integer NOT NULL PRIMARY KEY, "blob_id" integer NOT NULL, "variation_digest" varchar NOT NULL) 395 |  (0.0ms) CREATE UNIQUE INDEX "tindex_aactive_storage_variant_records_uniqueness" ON "aactive_storage_variant_records" ("blob_id", "variation_digest") 396 |  (0.0ms) INSERT INTO "aactive_storage_variant_records" ("id","blob_id","variation_digest") 397 | SELECT "id","blob_id","variation_digest" FROM "active_storage_variant_records" 398 |  (0.1ms) DROP TABLE "active_storage_variant_records" 399 |  (0.0ms) CREATE TABLE "active_storage_variant_records" ("id" integer NOT NULL PRIMARY KEY, "blob_id" integer NOT NULL, "variation_digest" varchar NOT NULL, CONSTRAINT "fk_rails_993965df05" 400 | FOREIGN KEY ("blob_id") 401 | REFERENCES "active_storage_blobs" ("id") 402 | ) 403 |  (0.0ms) CREATE UNIQUE INDEX "index_active_storage_variant_records_uniqueness" ON "active_storage_variant_records" ("blob_id", "variation_digest") 404 |  (0.0ms) INSERT INTO "active_storage_variant_records" ("id","blob_id","variation_digest") 405 | SELECT "id","blob_id","variation_digest" FROM "aactive_storage_variant_records" 406 |  (0.0ms) DROP TABLE "aactive_storage_variant_records" 407 |  (0.0ms) PRAGMA defer_foreign_keys = 0 408 |  (0.0ms) PRAGMA foreign_keys = 1 409 | TRANSACTION (0.2ms) commit transaction 410 |  (0.3ms) CREATE TABLE "schema_migrations" ("version" varchar NOT NULL PRIMARY KEY) 411 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 412 |  (0.3ms) INSERT INTO "schema_migrations" (version) VALUES (101) 413 |  (0.3ms) INSERT INTO "schema_migrations" (version) VALUES 414 | (1), 415 | (2), 416 | (3); 417 | 418 |  419 |  (0.3ms) CREATE TABLE "ar_internal_metadata" ("key" varchar NOT NULL PRIMARY KEY, "value" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL) 420 | ActiveRecord::InternalMetadata Load (0.0ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? LIMIT ? [["key", "environment"], ["LIMIT", 1]] 421 | TRANSACTION (0.0ms) begin transaction 422 | ActiveRecord::InternalMetadata Create (0.1ms) INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["key", "environment"], ["value", "test"], ["created_at", "2023-08-24 19:24:58.209927"], ["updated_at", "2023-08-24 19:24:58.209927"]] 423 | TRANSACTION (0.2ms) commit transaction 424 | ActiveRecord::InternalMetadata Load (0.0ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? LIMIT ? [["key", "environment"], ["LIMIT", 1]] 425 | ActiveRecord::InternalMetadata Load (0.0ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? LIMIT ? [["key", "schema_sha1"], ["LIMIT", 1]] 426 | TRANSACTION (0.0ms) begin transaction 427 | ActiveRecord::InternalMetadata Create (0.1ms) INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["key", "schema_sha1"], ["value", "e354c66628a82e4eac16ac05d7129535870d993f"], ["created_at", "2023-08-24 19:24:58.211188"], ["updated_at", "2023-08-24 19:24:58.211188"]] 428 | TRANSACTION (0.2ms) commit transaction 429 |  (0.0ms) SELECT sqlite_version(*) 430 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 431 | TRANSACTION (0.0ms) begin transaction 432 | ---------------------------- 433 | AddressesTest: test_is_valid 434 | ---------------------------- 435 | No country set. Try calling country= before state= 436 | TRANSACTION (0.0ms) rollback transaction 437 | TRANSACTION (0.0ms) begin transaction 438 | ---------------------------------------------------- 439 | EffectiveAddressesTest: test_it_has_a_version_number 440 | ---------------------------------------------------- 441 | TRANSACTION (0.0ms) rollback transaction 442 |  (0.5ms) SELECT sqlite_version(*) 443 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 444 |  (0.1ms) SELECT sqlite_version(*) 445 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 446 | TRANSACTION (0.0ms) begin transaction 447 | ---------------------------------------------------- 448 | EffectiveAddressesTest: test_it_has_a_version_number 449 | ---------------------------------------------------- 450 | TRANSACTION (0.0ms) rollback transaction 451 | TRANSACTION (0.0ms) begin transaction 452 | ---------------------------- 453 | AddressesTest: test_is_valid 454 | ---------------------------- 455 | No country set. Try calling country= before state= 456 | TRANSACTION (0.0ms) rollback transaction 457 |  (0.5ms) SELECT sqlite_version(*) 458 |  (0.1ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 459 |  (0.0ms) SELECT sqlite_version(*) 460 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 461 | TRANSACTION (0.1ms) begin transaction 462 | ---------------------------------------------------- 463 | EffectiveAddressesTest: test_it_has_a_version_number 464 | ---------------------------------------------------- 465 | TRANSACTION (0.0ms) rollback transaction 466 | TRANSACTION (0.0ms) begin transaction 467 | ---------------------------- 468 | AddressesTest: test_is_valid 469 | ---------------------------- 470 | TRANSACTION (0.0ms) rollback transaction 471 |  (0.5ms) SELECT sqlite_version(*) 472 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 473 |  (0.0ms) SELECT sqlite_version(*) 474 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 475 | TRANSACTION (0.0ms) begin transaction 476 | ---------------------------- 477 | AddressesTest: test_is_valid 478 | ---------------------------- 479 | No country set. Try calling country= before state= 480 | TRANSACTION (0.0ms) rollback transaction 481 | TRANSACTION (0.0ms) begin transaction 482 | ---------------------------------------------------- 483 | EffectiveAddressesTest: test_it_has_a_version_number 484 | ---------------------------------------------------- 485 | TRANSACTION (0.0ms) rollback transaction 486 |  (0.5ms) SELECT sqlite_version(*) 487 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 488 |  (0.0ms) SELECT sqlite_version(*) 489 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 490 | TRANSACTION (0.0ms) begin transaction 491 | ---------------------------- 492 | AddressesTest: test_is_valid 493 | ---------------------------- 494 | No country set. Try calling country= before state= 495 | TRANSACTION (0.1ms) rollback transaction 496 | TRANSACTION (0.0ms) begin transaction 497 | ---------------------------------------------------- 498 | EffectiveAddressesTest: test_it_has_a_version_number 499 | ---------------------------------------------------- 500 | TRANSACTION (0.0ms) rollback transaction 501 |  (0.4ms) SELECT sqlite_version(*) 502 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 503 |  (0.0ms) SELECT sqlite_version(*) 504 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 505 | TRANSACTION (0.0ms) begin transaction 506 | ---------------------------------------------------- 507 | EffectiveAddressesTest: test_it_has_a_version_number 508 | ---------------------------------------------------- 509 | TRANSACTION (0.0ms) rollback transaction 510 | TRANSACTION (0.0ms) begin transaction 511 | ---------------------------- 512 | AddressesTest: test_is_valid 513 | ---------------------------- 514 | TRANSACTION (0.0ms) rollback transaction 515 |  (0.5ms) SELECT sqlite_version(*) 516 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 517 |  (0.0ms) SELECT sqlite_version(*) 518 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 519 | TRANSACTION (0.0ms) begin transaction 520 | ---------------------------------------------------- 521 | EffectiveAddressesTest: test_it_has_a_version_number 522 | ---------------------------------------------------- 523 | TRANSACTION (0.0ms) rollback transaction 524 | TRANSACTION (0.0ms) begin transaction 525 | ---------------------------- 526 | AddressesTest: test_is_valid 527 | ---------------------------- 528 | TRANSACTION (0.0ms) rollback transaction 529 |  (0.5ms) SELECT sqlite_version(*) 530 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 531 |  (0.0ms) SELECT sqlite_version(*) 532 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 533 |  (0.5ms) SELECT sqlite_version(*) 534 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 535 |  (0.0ms) SELECT sqlite_version(*) 536 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 537 | TRANSACTION (0.0ms) begin transaction 538 | ---------------------------------------------------- 539 | EffectiveAddressesTest: test_it_has_a_version_number 540 | ---------------------------------------------------- 541 | TRANSACTION (0.0ms) rollback transaction 542 | TRANSACTION (0.0ms) begin transaction 543 | ---------------------------- 544 | AddressesTest: test_is_valid 545 | ---------------------------- 546 | TRANSACTION (0.0ms) rollback transaction 547 |  (0.6ms) SELECT sqlite_version(*) 548 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 549 |  (0.0ms) SELECT sqlite_version(*) 550 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 551 | TRANSACTION (0.0ms) begin transaction 552 | ---------------------------- 553 | AddressesTest: test_is_valid 554 | ---------------------------- 555 | TRANSACTION (0.0ms) rollback transaction 556 | TRANSACTION (0.0ms) begin transaction 557 | ---------------------------------------------------- 558 | EffectiveAddressesTest: test_it_has_a_version_number 559 | ---------------------------------------------------- 560 | TRANSACTION (0.0ms) rollback transaction 561 |  (0.4ms) SELECT sqlite_version(*) 562 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 563 |  (0.0ms) SELECT sqlite_version(*) 564 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 565 | TRANSACTION (0.1ms) begin transaction 566 | ---------------------------------------------------- 567 | EffectiveAddressesTest: test_it_has_a_version_number 568 | ---------------------------------------------------- 569 | TRANSACTION (0.0ms) rollback transaction 570 | TRANSACTION (0.0ms) begin transaction 571 | ---------------------------- 572 | AddressesTest: test_is_valid 573 | ---------------------------- 574 | TRANSACTION (0.0ms) rollback transaction 575 |  (0.5ms) SELECT sqlite_version(*) 576 |  (0.1ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 577 |  (0.0ms) SELECT sqlite_version(*) 578 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 579 | TRANSACTION (0.1ms) begin transaction 580 | ---------------------------------------------------- 581 | EffectiveAddressesTest: test_it_has_a_version_number 582 | ---------------------------------------------------- 583 | TRANSACTION (0.0ms) rollback transaction 584 | TRANSACTION (0.0ms) begin transaction 585 | ---------------------------- 586 | AddressesTest: test_is_valid 587 | ---------------------------- 588 | TRANSACTION (0.0ms) rollback transaction 589 |  (0.5ms) SELECT sqlite_version(*) 590 |  (0.1ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 591 |  (0.0ms) SELECT sqlite_version(*) 592 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 593 | TRANSACTION (0.1ms) begin transaction 594 | ---------------------------------------------------- 595 | EffectiveAddressesTest: test_it_has_a_version_number 596 | ---------------------------------------------------- 597 | TRANSACTION (0.1ms) rollback transaction 598 | TRANSACTION (0.0ms) begin transaction 599 | ---------------------------- 600 | AddressesTest: test_is_valid 601 | ---------------------------- 602 | TRANSACTION (0.0ms) rollback transaction 603 |  (0.5ms) SELECT sqlite_version(*) 604 |  (0.1ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 605 |  (0.0ms) SELECT sqlite_version(*) 606 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 607 | TRANSACTION (0.0ms) begin transaction 608 | ---------------------------------------------------- 609 | EffectiveAddressesTest: test_it_has_a_version_number 610 | ---------------------------------------------------- 611 | TRANSACTION (0.0ms) rollback transaction 612 | TRANSACTION (0.0ms) begin transaction 613 | ---------------------------- 614 | AddressesTest: test_is_valid 615 | ---------------------------- 616 | TRANSACTION (0.0ms) rollback transaction 617 |  (0.8ms) SELECT sqlite_version(*) 618 |  (0.1ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 619 |  (0.0ms) SELECT sqlite_version(*) 620 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 621 | TRANSACTION (0.1ms) begin transaction 622 | ---------------------------------------------------- 623 | EffectiveAddressesTest: test_it_has_a_version_number 624 | ---------------------------------------------------- 625 | TRANSACTION (0.0ms) rollback transaction 626 | TRANSACTION (0.0ms) begin transaction 627 | ---------------------------- 628 | AddressesTest: test_is_valid 629 | ---------------------------- 630 | TRANSACTION (0.0ms) rollback transaction 631 |  (0.4ms) SELECT sqlite_version(*) 632 |  (0.0ms) SELECT "ar_internal_metadata"."value" FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = ? [["key", "schema_sha1"]] 633 |  (0.0ms) SELECT sqlite_version(*) 634 |  (0.0ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC 635 | TRANSACTION (0.0ms) begin transaction 636 | ---------------------------------------------------- 637 | EffectiveAddressesTest: test_it_has_a_version_number 638 | ---------------------------------------------------- 639 | TRANSACTION (0.0ms) rollback transaction 640 | TRANSACTION (0.0ms) begin transaction 641 | ---------------------------- 642 | AddressesTest: test_is_valid 643 | ---------------------------- 644 | TRANSACTION (0.0ms) rollback transaction 645 | --------------------------------------------------------------------------------