Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support sqlite #17

Merged
merged 4 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .github/workflows/rspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,32 @@ jobs:
BUNDLE_JOBS: 4
BUNDLE_RETRY: 3
BUNDLE_GEMFILE: ${{ matrix.gemfile }}
DATABASE_URL: postgres://postgres:postgres@localhost:5432
POSTGRES_URL: postgres://postgres:postgres@localhost:5432
DB: ${{ matrix.db }}
DB_NAME: slotted_counters_test
CI: true
strategy:
fail-fast: false
matrix:
ruby: ["3.0"]
gemfile: ["gemfiles/rails7.gemfile"]
db: ["sqlite"]
include:
- ruby: "2.7"
gemfile: "gemfiles/rails6.gemfile"
db: "postgres"
- ruby: "3.1"
gemfile: "gemfiles/railsmaster.gemfile"
db: "postgres"
- ruby: "3.0"
gemfile: "gemfiles/rails7.gemfile"
db: "postgres"
- ruby: "2.7"
gemfile: "gemfiles/rails6.gemfile"
db: "sqlite"
- ruby: "3.1"
gemfile: "gemfiles/railsmaster.gemfile"
db: "sqlite"
services:
postgres:
image: postgres:14
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## master

- Add SQLite support [#17](https://github.com/evilmartians/activerecord-slotted_counters/pull/17) ([@prog-supdex][])

## 0.1.4 (2023-04-19)

- Fix "can't modify frozen String" for the pg adapter (ruby 2.7) [#15](https://github.com/evilmartians/activerecord-slotted_counters/pull/15) ([@LukinEgor][])
Expand All @@ -25,3 +27,4 @@
[@palkan]: https://github.com/palkan
[@LukinEgor]: https://github.com/LukinEgor
[@danielwestendorf]: https://github.com/danielwestendorf
[@prog-supdex]: https://github.com/prog-supdex
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Using `counter_cache: true` on `belongs_to` associations also works as expected.

## Limitations / TODO

- Gem supports only PostgreSQL for Rails 6
- Gem supports only PostgreSQL and SQLite3 for Rails 6

## Contributing

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,19 @@

module ActiveRecordSlottedCounters
module Adapters
class PgUpsert
class PgSqliteUpsert
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The adapter pattern means separating implementations, not mixing them up. Please, fix this. There should not be any changes to the existing PgUpsert class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah
I just thought that SQLite adapter has the same functionality, and maybe the apply? method could resolve it

but I got it, fixed it
and in that case, the duplication is not bad, because we have two different implementations

thanks

attr_reader :klass

def initialize(klass)
@klass = klass
end

def apply?
ActiveRecord::VERSION::MAJOR < 7 && klass.connection.adapter_name == ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::ADAPTER_NAME
return false if ActiveRecord::VERSION::MAJOR >= 7

adapter_name = klass.connection.adapter_name

postgresql_connection?(adapter_name) || sqlite_connection?(adapter_name)
end

def bulk_insert(attributes, on_duplicate: nil, unique_by: nil)
Expand Down Expand Up @@ -83,6 +87,18 @@ def quote_record(columns, record_values)
def quote_many_records(columns, data)
data.map { |values| quote_record(columns, values) }.join(",")
end

def postgresql_connection?(adapter_name)
return false unless defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)

adapter_name == ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::ADAPTER_NAME
end

def sqlite_connection?(adapter_name)
return false unless defined?(ActiveRecord::ConnectionAdapters::SQLite3Adapter)

adapter_name == ActiveRecord::ConnectionAdapters::SQLite3Adapter::ADAPTER_NAME
end
end
end
end
2 changes: 1 addition & 1 deletion lib/activerecord_slotted_counters/adapters/rails_upsert.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module ActiveRecordSlottedCounters
module Adapters
class RailsUpsert
attr_reader :klass
attr_reader :klass, :current_adapter_name
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where do we use current_adapter_name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, sorry, It was leaked from another branch
fixed


def initialize(klass)
@klass = klass
Expand Down
4 changes: 2 additions & 2 deletions lib/activerecord_slotted_counters/has_slotted_counter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
require "activerecord_slotted_counters/utils"

require "activerecord_slotted_counters/adapters/rails_upsert"
require "activerecord_slotted_counters/adapters/pg_upsert"
require "activerecord_slotted_counters/adapters/pg_sqlite_upsert"

module ActiveRecordSlottedCounters
class SlottedCounter < ::ActiveRecord::Base
Expand Down Expand Up @@ -42,7 +42,7 @@ def slotted_counter_db_adapter
def set_slotted_counter_db_adapter
available_adapters = [
ActiveRecordSlottedCounters::Adapters::RailsUpsert,
ActiveRecordSlottedCounters::Adapters::PgUpsert
ActiveRecordSlottedCounters::Adapters::PgSqliteUpsert
]

adapter = available_adapters
Expand Down
11 changes: 9 additions & 2 deletions spec/slotted_counter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,18 @@
def insert_association_sql(association_class, article_id)
association_table = association_class.arel_table
foreign_key = association_class.reflections["article"].foreign_key
current_date_sql_command =
if defined?(ActiveRecord::ConnectionAdapters::SQLite3Adapter)
"date('now')"
else
"now()"
end

insert_manager = Arel::InsertManager.new
insert_manager.insert([
[association_table[foreign_key], article_id],
[association_table[:created_at], Arel.sql("now()")],
[association_table[:updated_at], Arel.sql("now()")]
[association_table[:created_at], Arel.sql(current_date_sql_command)],
[association_table[:updated_at], Arel.sql(current_date_sql_command)]
])

insert_manager.to_sql
Expand Down
35 changes: 20 additions & 15 deletions spec/support/active_record_init.rb
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
# frozen_string_literal: true

connection_params =
if ENV.key?("DATABASE_URL")
{"url" => ENV["DATABASE_URL"]}
else
{
"host" => ENV.fetch("DB_HOST", "localhost"),
"username" => ENV.fetch("DB_USER", "postgres"),
"port" => ENV.fetch("DB_PORT", "9339").to_i
}
DB_CONFIG =
if ENV["DB"] == "postgres"
require "active_record/database_configurations"
url = ENV.fetch("POSTGRES_URL")

config = ActiveRecord::DatabaseConfigurations::UrlConfig.new(
"test",
"primary",
url,
{"database" => ENV.fetch("DB_NAME", "slotted_counters_test")}
)
config.respond_to?(:configuration_hash) ? config.configuration_hash : config.config
elsif ENV["DB"] == "sqlite"
# Make sure we don't have a DATABASE_URL set (it can be used by libs, e.g., database_cleaner)
ENV.delete("DATABASE_URL") if ENV["DATABASE_URL"]

{adapter: "sqlite3", database: ":memory:"}
end

ActiveRecord::Base.establish_connection(
{
"adapter" => "postgresql",
"database" => "slotted_counters_test"
}.merge(connection_params)
)
$stdout.puts "⚙️ Using #{DB_CONFIG[:adapter]} adapter for a database"

ActiveRecord::Base.establish_connection(**DB_CONFIG)

ActiveRecord::Schema.define do
create_table "views", force: :cascade do |t|
Expand Down
11 changes: 9 additions & 2 deletions spec/support/shared_examples_for_cache_counters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,18 @@
def insert_comment_sql(comment_class, article_id)
comment_table = comment_class.arel_table
foreign_key = comment_class.reflections["article"].foreign_key
current_date_sql_command =
if defined?(ActiveRecord::ConnectionAdapters::SQLite3Adapter)
"date('now')"
else
"now()"
end

insert_manager = Arel::InsertManager.new
insert_manager.insert([
[comment_table[foreign_key], article_id],
[comment_table[:created_at], Arel.sql("now()")],
[comment_table[:updated_at], Arel.sql("now()")]
[comment_table[:created_at], Arel.sql(current_date_sql_command)],
[comment_table[:updated_at], Arel.sql(current_date_sql_command)]
])

insert_manager.to_sql
Expand Down