Skip to content

Commit

Permalink
feat: add rename collection decorator support (#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolasalexandre9 authored Mar 22, 2024
1 parent 765ef50 commit e0cad85
Show file tree
Hide file tree
Showing 11 changed files with 485 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,15 @@ def remove_field(*names)
end
end

# Rename fields from the exported schema.
# @param current_name the current name of the field or the relation in a given collection
# @param new_name the new name of the field or the relation
# @example
# rename_field('currentFieldOrRelationName', 'newFieldOrRelationName')
def rename_field(current_name, new_name)
push_customization { @stack.rename_field.get_collection(@name).rename_field(current_name, new_name) }
end

private

def push_customization(&customization)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@ def add_datasource(datasource, options)
datasource = publication_decorator
end

# TODO: add rename behavior
if options[:rename]
rename_collection_decorator = Decorators::RenameCollection::RenameCollectionDatasourceDecorator.new(
datasource
)
rename_collection_decorator.rename_collections(options[:rename])
datasource = rename_collection_decorator
end

datasource.collections.each_value do |collection|
@composite_datasource.add_collection(collection)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
module ForestAdminDatasourceCustomizer
module Decorators
module RenameCollection
class RenameCollectionDatasourceDecorator < ForestAdminDatasourceToolkit::Decorators::DatasourceDecorator
include ForestAdminDatasourceToolkit
include ForestAdminDatasourceToolkit::Decorators
include ForestAdminDatasourceToolkit::Components::Query::ConditionTree

def initialize(child_datasource)
@from_child_name = {}
@to_child_name = {}
super(child_datasource, RenameCollectionDecorator)
end

def collections
@child_datasource.collections.to_h do |name, _collection|
[name, method(:get_collection).super_method.call(name)]
end
end

def get_collection(name)
# Collection has been renamed, user is using the new name
return super(@to_child_name[name]) if @to_child_name.key?(name)

# Collection has been renamed, user is using the old name
if @from_child_name.key?(name)
raise Exceptions::ForestException, "Collection '#{name}' has been renamed to '#{@from_child_name[name]}'"
end

# Collection has not been renamed
super(name)
end

def rename_collections(renames = [])
renames.each do |current_name, new_name|
rename_collection(current_name, new_name)
end
end

def rename_collection(current_name, new_name)
# Check collection exists
get_collection(current_name)

return unless current_name != new_name

# Check new name is not already used
if collections.any? { |name, _collection| name == new_name }
raise Exceptions::ForestException,
"The given new collection name '#{new_name}' is already defined"
end

# Check we don't rename a collection twice
if @to_child_name[current_name]
raise Exceptions::ForestException,
"Cannot rename a collection twice: #{@to_child_name[current_name]}->#{current_name}->#{new_name}"
end

@from_child_name[current_name] = new_name
@to_child_name[new_name] = current_name

collections.each_value(&:mark_schema_as_dirty)
end

def get_collection_name(child_name)
@from_child_name[child_name] || child_name
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module ForestAdminDatasourceCustomizer
module Decorators
module RenameCollection
class RenameCollectionDecorator < ForestAdminDatasourceToolkit::Decorators::CollectionDecorator
include ForestAdminDatasourceToolkit::Decorators
include ForestAdminDatasourceToolkit::Components::Query::ConditionTree

def name
datasource.get_collection_name(super)
end

def refine_schema(sub_schema)
fields = {}

sub_schema[:fields].each do |name, old_schema|
if old_schema.type != 'Column'
old_schema.foreign_collection = datasource.get_collection_name(old_schema.foreign_collection)
if old_schema.type == 'ManyToMany'
old_schema.through_collection = datasource.get_collection_name(old_schema.through_collection)
end
end

fields[name] = old_schema
end

sub_schema
end

# rubocop:disable Lint/UselessMethodDefinition
def mark_schema_as_dirty
super
end
# rubocop:enable Lint/UselessMethodDefinition
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,20 @@ def rename_field(current_name, new_name)
def refine_schema(sub_schema)
fields = {}

sub_schema[:fields].each do |old_name, schema|
case schema.type
sub_schema[:fields].each do |old_name, old_schema|
case old_schema.type
when 'ManyToOne'
schema.foreign_key = from_child_collection[schema.foreign_key] || schema.foreign_key
old_schema.foreign_key = from_child_collection[old_schema.foreign_key] || old_schema.foreign_key
when 'OneToMany', 'OneToOne'
relation = datasource.get_collection(schema.foreign_collection)
schema.origin_key = relation.from_child_collection[schema.origin_key] || schema.origin_key
relation = datasource.get_collection(old_schema.foreign_collection)
old_schema.origin_key = relation.from_child_collection[old_schema.origin_key] || old_schema.origin_key
when 'ManyToMany'
through = datasource.get_collection(schema.through_collection)
schema.foreign_key = through.from_child_collection[schema.foreign_key] || schema.foreign_key
schema.origin_key = through.from_child_collection[schema.origin_key] || schema.origin_key
through = datasource.get_collection(old_schema.through_collection)
old_schema.foreign_key = through.from_child_collection[old_schema.foreign_key] || old_schema.foreign_key
old_schema.origin_key = through.from_child_collection[old_schema.origin_key] || old_schema.origin_key
end

fields[from_child_collection[old_name] || old_name] = schema
fields[from_child_collection[old_name] || old_name] = old_schema
end

sub_schema[:fields] = fields
Expand All @@ -69,7 +69,7 @@ def refine_filter(_caller, filter = nil)
end

def create(caller, data)
record = super(
record = @child_collection.create(
caller,
record_to_child_collection(data)
)
Expand All @@ -79,18 +79,18 @@ def create(caller, data)

def list(caller, filter, projection)
child_projection = projection.replace { |field| path_to_child_collection(field) }
records = super(caller, filter, child_projection)
records = @child_collection.list(caller, filter, child_projection)
return records if child_projection == projection

records.map { |record| record_from_child_collection(record) }
end

def update(caller, filter, patch)
super(caller, filter, record_to_child_collection(patch))
@child_collection.update(caller, filter, record_to_child_collection(patch))
end

def aggregate(caller, filter, aggregation, limit = nil)
rows = super(
rows = @child_collection.aggregate(
caller,
filter,
aggregation.replace_fields { |field| path_to_child_collection(field) },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -417,5 +417,17 @@ module ForestAdminDatasourceCustomizer
expect(publication_collection.fields).not_to have_key('name_in_read_only')
end
end

context 'when using rename_field' do
it 'replace rename a field' do
customizer = described_class.new(@datasource_customizer, @datasource_customizer.stack, 'person')
customizer.rename_field('name', 'renamed_name')
@datasource_customizer.datasource({})

rename_collection = @datasource_customizer.stack.rename_field.get_collection('person')

expect(rename_collection.schema[:fields]).to have_key('renamed_name')
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,25 @@ module ForestAdminDatasourceCustomizer
customized = described_class.new
.add_datasource(datasource, {})
.remove_collection('collection')
customized.stack.apply_queued_customizations({})

expect(customized.collections).to be_empty
end
end

context 'when rename a collection' do
it 'rename the collection into the datasource' do
customized = described_class.new
.add_datasource(
datasource,
{
rename: { 'collection' => 'renamed_collection' }
}
)
customized.stack.apply_queued_customizations({})

expect(customized.collections.key?('renamed_collection')).to be(true)
end
end
end
end
Loading

0 comments on commit e0cad85

Please sign in to comment.