Class: ActiveProject::AssociationProxy

Inherits:
Object
  • Object
show all
Defined in:
lib/active_project/association_proxy.rb

Overview

Represents an association between resources (e.g., project.issues). Delegates finding/creating methods to the adapter, providing owner context.

Instance Method Summary collapse

Constructor Details

#initialize(owner:, adapter:, association_name:) ⇒ AssociationProxy

Returns a new instance of AssociationProxy.

Parameters:

  • owner (Resources::BaseResource)

    The resource instance owning the association.

  • adapter (Adapters::Base)

    The adapter instance.

  • association_name (Symbol)

    The name of the association (e.g., :issues, :comments).



10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/active_project/association_proxy.rb', line 10

def initialize(owner:, adapter:, association_name:)
  @owner = owner
  @adapter = adapter
  @association_name = association_name
  # Determine target resource class based on association name (simple heuristic for now)
  @target_resource_class = case association_name
  when :issues then Resources::Issue
  when :comments then Resources::Comment
  # Add other associations like :project for an issue?
  else raise "Unknown association: #{association_name}"
  end
end

Instance Method Details

#all(options = {}) ⇒ Array<BaseResource>

Fetches all associated resources. Example: project.issues.all -> adapter.list_issues(project.id)

Parameters:

  • options (Hash) (defaults to: {})

    Additional options for the list method.

Returns:

  • (Array<BaseResource>)


29
30
31
32
33
34
35
36
37
# File 'lib/active_project/association_proxy.rb', line 29

def all(options = {})
  list_method = determine_list_method
  # Pass owner's ID as the primary context, then options
  # Ensure owner.id is accessed correctly
  owner_id = @owner.respond_to?(:id) ? @owner.id : nil
  raise "Owner object #{@owner.inspect} does not have an ID for association call." unless owner_id

  @adapter.send(list_method, owner_id, options)
end

#build(attributes = {}) ⇒ BaseResource Also known as: new

Builds a new, unsaved associated resource instance. Example: project.issues.build(title: ‘New’)

Parameters:

  • attributes (Hash) (defaults to: {})

    Attributes for the new resource.

Returns:

  • (BaseResource)


71
72
73
74
75
76
77
78
79
80
81
# File 'lib/active_project/association_proxy.rb', line 71

def build(attributes = {})
  # Automatically add owner context (e.g., project_id)
  owner_key = :"#{@owner.class.name.split('::').last.downcase}_id"
  merged_attrs = attributes.merge(
    owner_key => @owner.id,
    adapter_source: @adapter.class.name.split("::").last.sub("Adapter", "").downcase.to_sym,
    raw_data: attributes
  )
  # Ensure target resource class is correctly determined and used
  @target_resource_class.new(@adapter, merged_attrs)
end

#create(attributes = {}) ⇒ BaseResource

Creates and saves a new associated resource. Example: project.issues.create(title: ‘New’, list_id: ‘…’)

Parameters:

  • attributes (Hash) (defaults to: {})

    Attributes for the new resource.

Returns:

  • (BaseResource)

Raises:

  • (NotImplementedError)

    Currently raises because #save is not fully implemented on resource.



90
91
92
93
94
95
96
97
98
99
100
# File 'lib/active_project/association_proxy.rb', line 90

def create(attributes = {})
  create_method = determine_create_method
  determine_context # Get owner context
  # Pass owner ID/context first, then attributes
  owner_id = @owner.respond_to?(:id) ? @owner.id : nil
  raise "Owner object #{@owner.inspect} does not have an ID for association call." unless owner_id

  @adapter.send(create_method, owner_id, attributes)
  # NOTE: This currently returns the result from the adapter directly.
  # A full implementation would likely build and then save, or re-fetch.
end

#find(id) ⇒ BaseResource?

Finds a specific associated resource by ID. Example: project.issues.find(issue_id) -> adapter.find_issue(issue_id, { project_id: project.id })

Parameters:

  • id (String, Integer)

    The ID of the resource to find.

Returns:

  • (BaseResource, nil)


43
44
45
46
47
48
49
50
# File 'lib/active_project/association_proxy.rb', line 43

def find(id)
  find_method = determine_find_method
  # Pass owner context needed by the find method
  context = determine_context
  @adapter.send(find_method, id, context)
rescue ActiveProject::NotFoundError
  nil
end

#where(conditions) ⇒ Array<BaseResource>

Filters associated resources based on conditions. Example: project.issues.where(status: :open) Currently performs client-side filtering on #all results.

Parameters:

  • conditions (Hash)

    Conditions to filter by.

Returns:

  • (Array<BaseResource>)


57
58
59
60
61
62
63
64
65
# File 'lib/active_project/association_proxy.rb', line 57

def where(conditions)
  # Basic client-side filtering for now
  # Note: This calls the proxy's #all method, which passes owner context
  all.select do |resource|
    conditions.all? do |key, value|
      resource.respond_to?(key) && resource.send(key) == value
    end
  end
end