Skip to content

Commit

Permalink
fix(relation): add support of has_and_belongs_to_many relations (#105)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolasalexandre9 authored Feb 20, 2025
1 parent 6774d27 commit 09eeca0
Show file tree
Hide file tree
Showing 11 changed files with 57 additions and 8 deletions.
5 changes: 4 additions & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require:
plugins:
- rubocop-performance
- rubocop-rspec

Expand Down Expand Up @@ -329,3 +329,6 @@ Lint/InterpolationCheck:
Lint/UnusedMethodArgument:
Exclude:
- 'packages/forest_admin_rails/config/initializers/forest_admin_error_subscriber.rb'

Style/RedundantParentheses:
Enabled: false
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def serialize(schema)

{
data: data,
included: included.reject!(&:empty?)&.flatten,
included: included.reject!(&:empty?)&.flatten || [],
meta: schema[:meta]
}
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ module Schema
expect(schema).to eq(
{
data: [],
included: nil,
included: [],
meta: {
liana: described_class::LIANA_NAME,
liana_version: described_class::LIANA_VERSION,
Expand Down Expand Up @@ -123,7 +123,7 @@ module Schema
expect(schema).to eq(
{
data: [],
included: nil,
included: [],
meta: json_schema[:meta]
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,18 @@ def fetch_associations
)
end
end
when :has_and_belongs_to_many
add_field(
association.name.to_s,
ForestAdminDatasourceToolkit::Schema::Relations::ManyToManySchema.new(
foreign_collection: format_model_name(association.klass.name),
origin_key: association.join_primary_key,
origin_key_target: association.join_foreign_key,
foreign_key: association.association_foreign_key,
foreign_key_target: association.association_primary_key,
through_collection: association.join_table.classify
)
)
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ def fetch_model(model)
@models << model unless model.abstract_class? ||
@models.include?(model) ||
!model.table_exists? ||
!primary_key?(model)
!primary_key?(model) ||
model.const_defined?(:VIRTUAL_THROUGH_COLLECTION)
end
end

Expand All @@ -101,19 +102,24 @@ def build_habtm(model)
if @habtm_models.key?(model.table_name)
@habtm_models[model.table_name].left_reflection = model.right_reflection
# when the second model is added, we can push the HABTM model to the models list
@models << make_through_model(
through_model = make_through_model(
model.table_name,
[
@habtm_models[model.table_name].left_reflection,
@habtm_models[model.table_name].right_reflection
]
)

add_collection(
Collection.new(self, through_model, support_polymorphic_relations: @support_polymorphic_relations)
)
else
@habtm_models[model.table_name] = model
end
end

def make_through_model(table_name, associations)
through_model_name = table_name.classify
through_model = Class.new(ActiveRecord::Base) do
class << self
attr_accessor :name, :table_name
Expand All @@ -124,13 +130,15 @@ def self.add_association(name, options)
end
end

through_model.name = table_name.singularize
through_model.name = through_model_name
through_model.table_name = table_name
through_model.primary_key = [associations[0].foreign_key, associations[1].foreign_key]
associations.each do |association|
through_model.add_association(association.name, association.options)
end

through_model.const_set(:VIRTUAL_THROUGH_COLLECTION, true)

through_model
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Company < ApplicationRecord
has_and_belongs_to_many :users
end
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class User < ApplicationRecord
belongs_to :car
has_one :address, as: :addressable
has_and_belongs_to_many :companies

enum :enum_field, { draft: 0, published: 1, archived: 2, trashed: 3 }
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class CreateCompanies < ActiveRecord::Migration[7.0]
def change
create_table :companies do |t|
t.column :name, :string
t.timestamps
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class CreateCompaniesUsers < ActiveRecord::Migration[7.0]
def change
create_table :companies_users, id: false do |t|
t.belongs_to :company
t.belongs_to :user
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ module ForestAdminDatasourceActiveRecord
expect(datasource.get_collection('User').schema[:fields].keys).not_to include('address')
expect(datasource.get_collection('Address').schema[:fields].keys).not_to include('addressable')
end

it 'add has_and_belongs_to_many relation' do
collection = described_class.new(datasource, Company)

expect(collection.schema[:fields].keys).to include('users')
end
end
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module ForestAdminDatasourceActiveRecord
describe Datasource do
it 'fetch all models' do
datasource = described_class.new({ adapter: 'sqlite3', database: 'db/database.db' })
expected = %w[User Order Check Category CarCheck Car Address]
expected = %w[User Order Check Category CarCheck Car Address Company CompaniesUser]

expect(datasource.collections.keys).to match_array(expected)
end
Expand Down

0 comments on commit 09eeca0

Please sign in to comment.