Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 3 additions & 2 deletions src/jennifer/model/relation_definition.cr
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ module Jennifer
# - *primary* - specify the name of the column to use as the primary key for the relation
# - *join_table* - specifies the name of the join table if the default based on lexical order isn't what you want
# - *association_foreign* - specifies the foreign key used for the association on the receiving side of the association
# - *association_primary* - specifies the primary key used for the association on the receiving side of the association
#
# The following methods for retrieval and query of a single associated object will be added:
#
Expand All @@ -238,11 +239,11 @@ module Jennifer
# - `#remove_association(rel)`
# - `#association_query`
# - `#association_reload`
macro has_and_belongs_to_many(name, klass, request = nil, foreign = nil, primary = nil, join_table = nil, association_foreign = nil)
macro has_and_belongs_to_many(name, klass, request = nil, foreign = nil, primary = nil, join_table = nil, association_foreign = nil, association_primary = nil)
{{"{% RELATION_NAMES << #{name.id.stringify} %}".id}}
RELATIONS["{{name.id}}"] =
::Jennifer::Relation::ManyToMany({{klass}}, {{@type}}).new("{{name.id}}", {{foreign}}, {{primary}},
{{klass}}.all{% if request %}.exec {{request}} {% end %}, {{join_table}}, {{association_foreign}})
{{klass}}.all{% if request %}.exec {{request}} {% end %}, {{join_table}}, {{association_foreign}}, {{association_primary}})

before_destroy :__{{name.id}}_clean

Expand Down
16 changes: 13 additions & 3 deletions src/jennifer/relation/many_to_many.cr
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
module Jennifer
module Relation
class ManyToMany(T, Q) < Base(T, Q)
getter join_table : String?, association_foreign : String?
getter join_table : String?, association_foreign : String?, association_primary : String?

def initialize(@name, foreign : String | Symbol?, primary : String | Symbol?, query, @join_table = nil, _join_foreign = nil)
def initialize(@name, foreign : String | Symbol?, primary : String | Symbol?, query, @join_table = nil, _join_foreign = nil, _join_primary = nil)
@association_foreign = _join_foreign.to_s if _join_foreign
@association_primary = _join_primary.to_s if _join_primary
@foreign = foreign.to_s if foreign
@primary = primary.to_s if primary
@join_query = query.tree
Expand Down Expand Up @@ -39,10 +40,11 @@ module Jennifer

def query(primary_value)
afk = association_foreign_key
apk = association_primary_key
_primary_value = primary_value
mfk = foreign_field
q = T.all.join(join_table!) do
(c(afk) == T.primary) &
(c(afk) == apk) &
(_primary_value.is_a?(Array) ? c(mfk).in(_primary_value) : c(mfk) == _primary_value)
end
if @join_query
Expand Down Expand Up @@ -72,6 +74,14 @@ module Jennifer
@association_foreign || Inflector.foreign_key(T.to_s)
end

def association_primary_key
if (association_primary = @association_primary)
Comment thread
AndiLavera marked this conversation as resolved.
Outdated
return Jennifer::QueryBuilder::Criteria.new(association_primary, T.table_name)
end

T.primary
end

def preload_relation(collection, out_collection : Array(Model::Resource), pk_repo)
return if collection.empty?
_primary = primary_field
Expand Down