Skip to content

Commit

Permalink
Add support for json column to Sequel container backend
Browse files Browse the repository at this point in the history
  • Loading branch information
shioyama committed Mar 16, 2018
1 parent 4619e0c commit 94bd11a
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 14 deletions.
22 changes: 19 additions & 3 deletions lib/mobility/backends/sequel/container.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ module Backends
class Sequel::Container
include Sequel

require 'mobility/backends/sequel/container/query_methods'
require 'mobility/backends/sequel/container/json_query_methods'
require 'mobility/backends/sequel/container/jsonb_query_methods'

# @return [Symbol] name of container column
attr_reader :column_name
Expand Down Expand Up @@ -47,6 +48,12 @@ def write(locale, value, _ = nil)
# @option options [Symbol] column_name (:translations) Name of column on which to store translations
def self.configure(options)
options[:column_name] ||= :translations
options[:column_name] = options[:column_name].to_sym
column_name, db_schema = options[:column_name], options[:model_class].db_schema
options[:column_type] = db_schema[column_name] && (db_schema[column_name][:db_type]).to_sym
unless %i[json jsonb].include?(options[:column_type])
raise InvalidColumnType, "#{options[:column_name]} must be a column of type json or jsonb"
end
end
# @!endgroup
#
Expand All @@ -57,6 +64,8 @@ def each_locale
end
end

backend_class = self

setup do |attributes, options|
column_name = options[:column_name]
before_validation = Module.new do
Expand All @@ -73,9 +82,14 @@ def each_locale

plugin :defaults_setter
attributes.each { |attribute| default_values[attribute.to_sym] = {} }
end

setup_query_methods(QueryMethods)
query_methods = backend_class.const_get("#{options[:column_type].capitalize}QueryMethods")
extend(Module.new do
define_method ::Mobility.query_method do
super().with_extend(query_methods.new(attributes, options))
end
end)
end

private

Expand All @@ -94,6 +108,8 @@ def set_attribute_translation(locale, value)
end
translations[locale.to_s][attribute] = value
end

class InvalidColumnType < StandardError; end
end
end
end
34 changes: 34 additions & 0 deletions lib/mobility/backends/sequel/container/json_query_methods.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true
require "mobility/backends/sequel/pg_query_methods"
require "mobility/backends/sequel/query_methods"

Sequel.extension :pg_json, :pg_json_ops

module Mobility
module Backends
class Sequel::Container::JsonQueryMethods < Sequel::QueryMethods
include Sequel::PgQueryMethods
attr_reader :column_name

def initialize(attributes, options)
super
@column_name = options[:column_name]
define_query_methods
end

private

def matches(key, value, locale)
build_op(column_name)[locale].get_text(key.to_s) =~ value.to_s
end

def has_locale(key, locale)
build_op(column_name)[locale].get_text(key.to_s) !~ nil
end

def build_op(key)
::Sequel.pg_json_op(key)
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

module Mobility
module Backends
class Sequel::Container::QueryMethods < Sequel::QueryMethods
class Sequel::Container::JsonbQueryMethods < Sequel::QueryMethods
include Sequel::PgQueryMethods
attr_reader :column_name

Expand Down
3 changes: 2 additions & 1 deletion spec/mobility/backends/active_record/container_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@
StringColumnPost.extend Mobility
expect {
StringColumnPost.translates :title, backend: :container, column_name: :foo
}.to raise_error(Mobility::Backends::ActiveRecord::Container::InvalidColumnType)
}.to raise_error(Mobility::Backends::ActiveRecord::Container::InvalidColumnType,
"foo must be a column of type json or jsonb")
end
end
end if Mobility::Loaded::ActiveRecord
34 changes: 25 additions & 9 deletions spec/mobility/backends/sequel/container_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,35 @@
end
end

context "with a different column_name" do
context "with a json column_name" do
before(:all) do
DB.create_table!(:foo_posts) { primary_key :id; jsonb :foo, default: '""'; TrueClass :published }
DB.create_table!(:json_container_posts) { primary_key :id; json :json_translations, default: '{}'; TrueClass :published }
end
before(:each) do
stub_const 'FooPost', Class.new(Sequel::Model)
FooPost.dataset = DB[:foo_posts]
FooPost.extend Mobility
FooPost.translates :title, :content, backend: :container, presence: false, cache: false, column_name: :foo
stub_const 'JsonContainerPost', Class.new(Sequel::Model)
JsonContainerPost.dataset = DB[:json_container_posts]
JsonContainerPost.extend Mobility
JsonContainerPost.translates :title, :content, backend: :container, presence: false, cache: false, column_name: :json_translations
end
after(:all) { DB.drop_table?(:foo_posts) }
after(:all) { DB.drop_table?(:json_container_posts) }

include_accessor_examples 'FooPost'
include_querying_examples 'FooPost'
include_accessor_examples 'JsonContainerPost'
include_querying_examples 'JsonContainerPost'
end

context "with a non-json/jsonb column" do
before(:all) do
DB.create_table!(:string_column_posts) { primary_key :id; String :foo, default: ''; TrueClass :published }
end
after(:all) { DB.drop_table?(:string_column_posts) }

it "raises InvalidColumnType exception" do
stub_const 'StringColumnPost', Class.new(Sequel::Model)
StringColumnPost.dataset = DB[:string_column_posts]
StringColumnPost.extend Mobility
expect { StringColumnPost.translates :title, backend: :container, column_name: :foo
}.to raise_error(Mobility::Backends::Sequel::Container::InvalidColumnType,
"foo must be a column of type json or jsonb")
end
end
end if Mobility::Loaded::Sequel && ENV['DB'] == 'postgres'

0 comments on commit 94bd11a

Please sign in to comment.