milady-cima-api 0.1.0 → 0.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5539419d40c122e538f50af35e0be9230c3b9e29343ae9afaf47ecc18164cc25
4
- data.tar.gz: 175f19d66fd55269468793c5d7ae9eb2eb5b1adf6c874e35f28ca0a7cbf431e7
3
+ metadata.gz: 4cba4eea16f1a7f12d7085606bdadee4927918c7f960d2bd95ee4b9f10909f0f
4
+ data.tar.gz: e0519d5dfa0eacecf95237a65669ec5b232d23eb334bf50b9349b501887f1bbb
5
5
  SHA512:
6
- metadata.gz: 6b14b31072de9c2678cae2938c5de0dc6ba0feb1d9c2571a51db638c6bd740c04eb93d7f6972a40edd31cd07575446d74ad4fdaab401eb8d0bf28bfb70e08ccd
7
- data.tar.gz: 63c8e1ec423e9abf96e7a9b3be440e38d3a0a642eb4a76102d3440e5a5da08b3cc3ad577a721f0de455071ec5e4ab6eea71d870cb90d0a53e1a0e279eb03b666
6
+ metadata.gz: e872f0ae20e5bb564e219625426e4f853cc65ff48ac20a36c73879b7e7dcc4351c22ff6ce5fdb0aee612e11f76fce8cf38588005f54777897c2257c162c630f6
7
+ data.tar.gz: 4aedb0de4d77fa84fc8d430fb4dfc3df3ca61e6279785a7dd4750490493ee1cfec2003e8b5583d5d5f7afef19a1a5007ed8b12a0a83fb786bfcb4cf2499f9201
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.2.1] - 2025-12-04
4
+
5
+ ### Added
6
+ - Added `verify_ssl` option to `Client` initialization (defaults to `true`) to allow disabling SSL verification for testing or development.
7
+ - Added `Courses#find` method to retrieve a single course.
8
+ - Added live integration tests for `Courses` and `Assessments` filters (skipped by default).
9
+
10
+ ### Changed
11
+ - Updated `Courses#list` to use explicit keyword arguments for better documentation and usability, matching `Assessments#list`.
12
+
13
+ ## [0.2.0] - 2025-12-04
14
+
15
+ ### Added
16
+ - Added `Assessments` resource under `Courses` to support `GET /courses/{id}/assessments` and `GET /courses/{id}/assessments/{assessment_id}`.
17
+ - Standardized query parameters for `Assessments#list` with validation.
18
+
3
19
  ## [0.1.0] - 2025-10-06
4
20
 
5
21
  - Initial release
@@ -10,13 +10,15 @@ module MiLadyCimaApi
10
10
  API_PAGE_LIMIT = 100
11
11
 
12
12
  attr_reader :api_key, :base_url
13
+ attr_reader :api_key, :base_url, :verify_ssl
13
14
  attr_reader :users, :organizations, :courses
14
15
 
15
- def initialize(api_key:, base_url: DEFAULT_BASE_URL)
16
+ def initialize(api_key:, base_url: DEFAULT_BASE_URL, verify_ssl: true)
16
17
  raise ArgumentError, 'api_key is required' if api_key.nil? || api_key.strip.empty?
17
18
 
18
19
  @api_key = api_key
19
20
  @base_url = base_url.chomp('/')
21
+ @verify_ssl = verify_ssl
20
22
  @users = MiLadyCimaApi::Resources::Users.new(self)
21
23
  @organizations = MiLadyCimaApi::Resources::Organizations.new(self)
22
24
  @courses = MiLadyCimaApi::Resources::Courses.new(self)
@@ -100,6 +102,7 @@ module MiLadyCimaApi
100
102
  def perform_request(uri, request)
101
103
  http = Net::HTTP.new(uri.host, uri.port)
102
104
  http.use_ssl = uri.scheme == 'https'
105
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless verify_ssl
103
106
  response = http.request(request)
104
107
  handle_response(response)
105
108
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MiLadyCimaApi
4
+ module Resources
5
+ class Courses
6
+ # Assessments resource exposes endpoints under /courses/{id}/assessments
7
+ class Assessments
8
+ # @param client [MiLadyCimaApi::Client]
9
+ def initialize(client)
10
+ @client = client
11
+ end
12
+
13
+ # List assessments for a course
14
+ #
15
+ # GET /courses/{id}/assessments
16
+ # @param course_id [Integer, String] ID of the course
17
+ # @param filter [Hash, String] Filter using JSON structure
18
+ # @param limit [Integer] Limit the number of returned objects (default 10, max 100)
19
+ # @param offset [Integer] Used for paging through a small dataset
20
+ # @param after [Integer] Used for fast paging
21
+ # @param count [Boolean] If true, just return the number of list items
22
+ # @return [Array, Hash] Parsed JSON response from the API
23
+ def list(course_id:, filter: nil, limit: nil, offset: nil, after: nil, count: nil)
24
+ raise ArgumentError, 'course_id is required' if course_id.nil?
25
+
26
+ if limit && limit > 100
27
+ raise ArgumentError, 'limit cannot be greater than 100'
28
+ end
29
+
30
+ params = {}
31
+ params['$filter'] = normalize_filter(filter) if filter
32
+ params['$limit'] = limit if limit
33
+ params['$offset'] = offset if offset
34
+ params['$after'] = after if after
35
+ params['$count'] = count if count
36
+
37
+ @client.get("/courses/#{course_id}/assessments", params: params)
38
+ end
39
+
40
+ # Get a single assessment
41
+ #
42
+ # GET /courses/{id}/assessments/{assessment_id}
43
+ # @param course_id [Integer, String] ID of the course
44
+ # @param assessment_id [Integer, String] ID of the assessment
45
+ # @return [Hash] Parsed JSON response from the API
46
+ def find(course_id:, assessment_id:)
47
+ raise ArgumentError, 'course_id is required' if course_id.nil?
48
+ raise ArgumentError, 'assessment_id is required' if assessment_id.nil?
49
+
50
+ @client.get("/courses/#{course_id}/assessments/#{assessment_id}")
51
+ end
52
+
53
+ private
54
+
55
+ def normalize_filter(filter)
56
+ return filter if filter.is_a?(String)
57
+ return JSON.generate(filter) if filter.is_a?(Hash)
58
+
59
+ raise ArgumentError, 'filter must be a String (JSON) or a Hash'
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'json'
4
+ require_relative 'courses/assessments'
4
5
 
5
6
  module MiLadyCimaApi
6
7
  module Resources
@@ -12,22 +13,54 @@ module MiLadyCimaApi
12
13
  @client = client
13
14
  end
14
15
 
16
+ # @return [MiLadyCimaApi::Resources::Courses::Assessments]
17
+ def assessments
18
+ @assessments ||= Assessments.new(@client)
19
+ end
20
+
15
21
  # List courses
16
22
  #
17
23
  # GET /courses
18
- # @param params [Hash] Optional query params. Supports the special key
19
- # "$filter" (String or Hash). If provided as a Hash, it will be JSON-encoded
20
- # to match the API expectation (e.g., {"organization_id" => 123} or
21
- # {"and" => [{"gt" => {"metadata.created_at" => "2025-01-01T00:00:00.000Z"}}]}).
22
- # @option params [String, Hash] :$filter JSON string or Ruby Hash representing the filter
24
+ # @param filter [Hash, String] Filter using JSON structure
25
+ # @param limit [Integer] Limit the number of returned objects (default 10, max 100)
26
+ # @param offset [Integer] Used for paging through a small dataset
27
+ # @param after [Integer] Used for fast paging
28
+ # @param count [Boolean] If true, just return the number of list items
29
+ # @param order [String] Comma separated attribute names to sort by
30
+ # @param include [String] Comma separated list of relationships to include
23
31
  # @return [Array, Hash] Parsed JSON response from the API
24
- # @raise [MiLadyCimaApi::UnauthorizedError, MiLadyCimaApi::NotFoundError, MiLadyCimaApi::ClientError, MiLadyCimaApi::ServerError]
25
- def list(params = {})
26
- params = params.dup || {}
27
- normalize_filter_param!(params)
32
+ def list(filter: nil, limit: nil, offset: nil, after: nil, count: nil, order: nil, include: nil)
33
+ if limit && limit > 100
34
+ raise ArgumentError, 'limit cannot be greater than 100'
35
+ end
36
+
37
+ params = {}
38
+ params['$filter'] = normalize_filter(filter) if filter
39
+ params['$limit'] = limit if limit
40
+ params['$offset'] = offset if offset
41
+ params['$after'] = after if after
42
+ params['$count'] = count if count
43
+ params['$order'] = order if order
44
+ params['$include'] = include if include
45
+
28
46
  @client.get('/courses', params: params)
29
47
  end
30
48
 
49
+ # Get a single course
50
+ #
51
+ # GET /courses/{id}
52
+ # @param id [Integer, String] ID of the course
53
+ # @param include [String] Comma separated list of relationships to include
54
+ # @return [Hash] Parsed JSON response from the API
55
+ def find(id:, include: nil)
56
+ raise ArgumentError, 'id is required' if id.nil?
57
+
58
+ params = {}
59
+ params['$include'] = include if include
60
+
61
+ @client.get("/courses/#{id}", params: params)
62
+ end
63
+
31
64
  # Convenience: List courses by organization
32
65
  # @param organization_id [Integer, String]
33
66
  # @param extra_params [Hash] Additional query params (e.g., pagination)
@@ -35,7 +68,7 @@ module MiLadyCimaApi
35
68
  def by_organization(organization_id:, **extra_params)
36
69
  raise ArgumentError, 'organization_id is required' if organization_id.nil?
37
70
  filter = { 'organization_id' => organization_id }
38
- list({ '$filter' => filter }.merge(extra_params))
71
+ list(filter: filter, **extra_params)
39
72
  end
40
73
 
41
74
  # Convenience: List courses filtered by created_at with comparison operator
@@ -55,26 +88,16 @@ module MiLadyCimaApi
55
88
  { 'and' => [time_filter, { 'organization_id' => organization_id }] }
56
89
  end
57
90
 
58
- list({ '$filter' => filter }.merge(extra_params))
91
+ list(filter: filter, **extra_params)
59
92
  end
60
93
 
61
94
  private
62
95
 
63
- # Mutates params hash to ensure $filter is a JSON string when provided as a Hash
64
- def normalize_filter_param!(params)
65
- # support both symbol and string keys
66
- filter_key = params.key?(:$filter) ? :$filter : (params.key?("$filter") ? "$filter" : nil)
67
- return unless filter_key
68
-
69
- value = params[filter_key]
70
- case value
71
- when Hash
72
- params[filter_key] = JSON.generate(value)
73
- when String
74
- # pass through
75
- else
76
- raise ArgumentError, "$filter must be a String (JSON) or a Hash"
77
- end
96
+ def normalize_filter(filter)
97
+ return filter if filter.is_a?(String)
98
+ return JSON.generate(filter) if filter.is_a?(Hash)
99
+
100
+ raise ArgumentError, 'filter must be a String (JSON) or a Hash'
78
101
  end
79
102
  end
80
103
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module MiLadyCimaApi
4
4
  # Gem version
5
- VERSION = "0.1.0"
5
+ VERSION = "0.2.1"
6
6
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: milady-cima-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - marcus.salinas
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2025-10-22 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: milady-cima-api is a lightweight Ruby client that wraps the MiLady CIMA
14
13
  API, providing simple, idiomatic access to its endpoints.
@@ -29,10 +28,10 @@ files:
29
28
  - lib/milady_cima_api/client.rb
30
29
  - lib/milady_cima_api/errors.rb
31
30
  - lib/milady_cima_api/resources/courses.rb
31
+ - lib/milady_cima_api/resources/courses/assessments.rb
32
32
  - lib/milady_cima_api/resources/organizations.rb
33
33
  - lib/milady_cima_api/resources/users.rb
34
34
  - lib/milady_cima_api/version.rb
35
- - milady-cima-api.gemspec
36
35
  homepage: https://github.com/jippylong12/milady-cima-api
37
36
  licenses:
38
37
  - MIT
@@ -41,7 +40,6 @@ metadata:
41
40
  homepage_uri: https://github.com/jippylong12/milady-cima-api
42
41
  source_code_uri: https://github.com/jippylong12/milady-cima-api
43
42
  changelog_uri: https://github.com/jippylong12/milady-cima-api/blob/main/CHANGELOG.md
44
- post_install_message:
45
43
  rdoc_options: []
46
44
  require_paths:
47
45
  - lib
@@ -56,8 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
56
54
  - !ruby/object:Gem::Version
57
55
  version: '0'
58
56
  requirements: []
59
- rubygems_version: 3.5.22
60
- signing_key:
57
+ rubygems_version: 3.7.2
61
58
  specification_version: 4
62
59
  summary: Ruby wrapper for the MiLady CIMA API.
63
60
  test_files: []
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "lib/milady_cima_api/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "milady-cima-api"
7
- spec.version = MiLadyCimaApi::VERSION
8
- spec.authors = ["marcus.salinas"]
9
- spec.email = ["12.marcus.salinas@gmail.com"]
10
-
11
- spec.summary = "Ruby wrapper for the MiLady CIMA API."
12
- spec.description = "milady-cima-api is a lightweight Ruby client that wraps the MiLady CIMA API, providing simple, idiomatic access to its endpoints."
13
- spec.homepage = "https://github.com/jippylong12/milady-cima-api"
14
- spec.license = "MIT"
15
- spec.required_ruby_version = ">= 2.6.0"
16
-
17
- spec.metadata["allowed_push_host"] = "https://rubygems.org"
18
-
19
- spec.metadata["homepage_uri"] = spec.homepage
20
- spec.metadata["source_code_uri"] = "https://github.com/jippylong12/milady-cima-api"
21
- spec.metadata["changelog_uri"] = "https://github.com/jippylong12/milady-cima-api/blob/main/CHANGELOG.md"
22
-
23
- # Specify which files should be added to the gem when it is released.
24
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
- spec.files = Dir.chdir(__dir__) do
26
- `git ls-files -z`.split("\x0").reject do |f|
27
- (File.expand_path(f) == __FILE__) ||
28
- f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
29
- end
30
- end
31
- spec.bindir = "exe"
32
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
33
- spec.require_paths = ["lib"]
34
-
35
- # Uncomment to register a new dependency of your gem
36
- # spec.add_dependency "example-gem", "~> 1.0"
37
-
38
- # For more information and examples about making a new gem, check out our
39
- # guide at: https://bundler.io/guides/creating_gem.html
40
- end