moco-ruby 0.1.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MOCO
4
+ # Represents a MOCO webhook
5
+ # Provides methods for webhook-specific operations
6
+ class WebHook < BaseEntity
7
+ # Override entity_path to match API path
8
+ def self.entity_path
9
+ "account/web_hooks"
10
+ end
11
+
12
+ # Instance methods for webhook-specific operations
13
+ def enable
14
+ client.put("account/web_hooks/#{id}/enable")
15
+ self
16
+ end
17
+
18
+ def disable
19
+ client.put("account/web_hooks/#{id}/disable")
20
+ self
21
+ end
22
+
23
+ def to_s
24
+ "#{target} - #{url}"
25
+ end
26
+ end
27
+ end
data/lib/moco/entities.rb CHANGED
@@ -4,6 +4,7 @@ require_relative "helpers"
4
4
 
5
5
  module MOCO
6
6
  # Base entity class others inherit from, providing comparison, to_h, to_json
7
+ # @deprecated Use MOCO::BaseEntity from entities/base_entity.rb instead
7
8
  class BaseEntity
8
9
  def eql?(other)
9
10
  return false unless other.is_a? self.class
@@ -28,7 +29,6 @@ module MOCO
28
29
  hash
29
30
  end
30
31
 
31
- # rubocop:disable Metrics/MethodLength
32
32
  def to_json(*arg)
33
33
  to_h do |k, v|
34
34
  if v.is_a? Hash
@@ -43,9 +43,9 @@ module MOCO
43
43
  end.to_h.to_json(arg)
44
44
  end
45
45
  end
46
- # rubocop:enable Metrics/MethodLength
47
46
 
48
47
  # https://hundertzehn.github.io/mocoapp-api-docs/sections/projects.html
48
+ # @deprecated Use MOCO::Project from entities/project.rb instead
49
49
  class Project < BaseEntity
50
50
  attr_accessor :id, :active, :name, :customer, :tasks
51
51
 
@@ -55,6 +55,7 @@ module MOCO
55
55
  end
56
56
 
57
57
  # https://hundertzehn.github.io/mocoapp-api-docs/sections/project_tasks.html
58
+ # @deprecated Use MOCO::Task from entities/task.rb instead
58
59
  class Task < BaseEntity
59
60
  attr_accessor :id, :active, :name, :project_id, :billable
60
61
 
@@ -64,22 +65,28 @@ module MOCO
64
65
  end
65
66
 
66
67
  # https://hundertzehn.github.io/mocoapp-api-docs/sections/activities.html
68
+ # @deprecated Use MOCO::Activity from entities/activity.rb instead
67
69
  class Activity < BaseEntity
68
70
  attr_accessor :id, :active, :date, :description, :project, :task, :seconds, :hours, :billable, :billed, :user,
69
71
  :customer, :tag
70
72
 
71
73
  def to_s
72
- "#{date} - #{Helpers.decimal_hours_to_civil(hours)}h (#{seconds}s) - #{project&.name} - #{task&.name}#{description.empty? ? "" : " (#{description})"} " \
73
- "(#{%i[billable billed].map { |x| (send(x) ? "" : "not ") + x.to_s }.join(", ")})"
74
+ description_part = description.empty? ? "" : " (#{description})"
75
+ status_part = "(#{%i[billable billed].map { |x| (send(x) ? "" : "not ") + x.to_s }.join(", ")})"
76
+
77
+ "#{date} - #{Helpers.decimal_hours_to_civil(hours)}h (#{seconds}s) - " \
78
+ "#{project&.name} - #{task&.name}#{description_part} #{status_part}"
74
79
  end
75
80
  end
76
81
 
77
82
  # https://hundertzehn.github.io/mocoapp-api-docs/sections/companies.html
83
+ # @deprecated Use MOCO::Company from entities/company.rb instead
78
84
  class Customer < BaseEntity
79
85
  attr_accessor :id, :name
80
86
  end
81
87
 
82
88
  # https://hundertzehn.github.io/mocoapp-api-docs/sections/users.html
89
+ # @deprecated Use MOCO::User from entities/user.rb instead
83
90
  class User < BaseEntity
84
91
  attr_accessor :id, :firstname, :lastname
85
92
  end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "collection_proxy"
4
+
5
+ module MOCO
6
+ # Provides high-level collection operations for MOCO entities
7
+ class EntityCollection
8
+ include Enumerable
9
+ attr_reader :client, :path, :entity_class_name
10
+
11
+ def initialize(client, path, entity_class_name)
12
+ @client = client
13
+ @path = path
14
+ @entity_class_name = entity_class_name
15
+ end
16
+
17
+ def all
18
+ collection.all
19
+ end
20
+
21
+ def find(id)
22
+ collection.find(id)
23
+ end
24
+
25
+ def where(filters = {})
26
+ collection.where(filters)
27
+ end
28
+
29
+ def create(attributes)
30
+ collection.create(attributes)
31
+ end
32
+
33
+ def each(&)
34
+ collection.each(&)
35
+ end
36
+
37
+ def first
38
+ all.first
39
+ end
40
+
41
+ def count
42
+ all.count
43
+ end
44
+
45
+ def update(id, attributes)
46
+ collection.update(id, attributes)
47
+ end
48
+
49
+ def delete(id)
50
+ collection.delete(id)
51
+ end
52
+
53
+ private
54
+
55
+ def collection
56
+ @collection ||= CollectionProxy.new(client, path, entity_class_name)
57
+ end
58
+ end
59
+ end
data/lib/moco/helpers.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MOCO
4
+ # Utility class with helper methods for the MOCO API
4
5
  class Helpers
5
6
  def self.decimal_hours_to_civil(decimal_hours)
6
7
  hours = decimal_hours.floor
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MOCO
4
+ # Provides ActiveRecord-style query interface for nested MOCO entities
5
+ # For example, project.tasks is a nested collection of tasks under a project
6
+ class NestedCollectionProxy < CollectionProxy
7
+ attr_reader :parent, :records
8
+
9
+ def initialize(client, parent, path_or_entity_name, entity_class_name)
10
+ @parent = parent
11
+ super(client, path_or_entity_name, entity_class_name)
12
+ end
13
+
14
+ # Override determine_base_path to include the parent's path
15
+ # For nested resources, we ignore any custom entity_path and just use simple pluralization
16
+ def determine_base_path(path_or_entity_name)
17
+ parent_type = ActiveSupport::Inflector.underscore(parent.class.name.split("::").last)
18
+ # Use simple tableized name, not entity_path (which might include 'projects/' prefix)
19
+ nested_path = ActiveSupport::Inflector.tableize(path_or_entity_name.to_s)
20
+ "#{parent_type.pluralize}/#{parent.id}/#{nested_path}"
21
+ end
22
+
23
+ # Create a new entity in this nested collection
24
+ def create(attributes)
25
+ klass = entity_class
26
+ return nil unless klass && klass <= MOCO::BaseEntity
27
+
28
+ klass.new(client, client.post(@base_path, attributes))
29
+ end
30
+
31
+ # Delete all entities in this nested collection
32
+ def destroy_all
33
+ client.delete("#{@base_path}/destroy_all")
34
+ true
35
+ rescue StandardError => e
36
+ warn "Warning: Failed to destroy all entities in #{@base_path}: #{e.message}"
37
+ false
38
+ end
39
+
40
+ # Make these methods public so they can be accessed by Project#tasks
41
+ public :load_records, :loaded?
42
+ end
43
+ end