meibo 0.1.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.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +13 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +84 -0
- data/LICENSE.txt +21 -0
- data/README.md +41 -0
- data/Rakefile +12 -0
- data/lib/meibo/academic_session.rb +48 -0
- data/lib/meibo/academic_session_set.rb +15 -0
- data/lib/meibo/base_profile.rb +37 -0
- data/lib/meibo/builder/academic_session_builder.rb +26 -0
- data/lib/meibo/builder/base_builder.rb +13 -0
- data/lib/meibo/builder/classroom_builder.rb +38 -0
- data/lib/meibo/builder/course_builder.rb +32 -0
- data/lib/meibo/builder/demographic_builder.rb +22 -0
- data/lib/meibo/builder/enrollment_builder.rb +30 -0
- data/lib/meibo/builder/organization_builder.rb +34 -0
- data/lib/meibo/builder/role_builder.rb +30 -0
- data/lib/meibo/builder/user_builder.rb +36 -0
- data/lib/meibo/builder/user_profile_builder.rb +22 -0
- data/lib/meibo/builder.rb +60 -0
- data/lib/meibo/classroom.rb +67 -0
- data/lib/meibo/classroom_set.rb +29 -0
- data/lib/meibo/converter.rb +259 -0
- data/lib/meibo/course.rb +45 -0
- data/lib/meibo/course_set.rb +23 -0
- data/lib/meibo/data_model.rb +84 -0
- data/lib/meibo/data_set.rb +44 -0
- data/lib/meibo/demographic.rb +70 -0
- data/lib/meibo/demographic_set.rb +18 -0
- data/lib/meibo/enrollment.rb +51 -0
- data/lib/meibo/enrollment_set.rb +22 -0
- data/lib/meibo/errors.rb +13 -0
- data/lib/meibo/factory_bot/academic_session.rb +23 -0
- data/lib/meibo/factory_bot/all.rb +13 -0
- data/lib/meibo/factory_bot/classroom.rb +28 -0
- data/lib/meibo/factory_bot/course.rb +21 -0
- data/lib/meibo/factory_bot/demographic.rb +16 -0
- data/lib/meibo/factory_bot/enrollment.rb +37 -0
- data/lib/meibo/factory_bot/manifest.rb +33 -0
- data/lib/meibo/factory_bot/memory_package.rb +11 -0
- data/lib/meibo/factory_bot/organization.rb +47 -0
- data/lib/meibo/factory_bot/role.rb +41 -0
- data/lib/meibo/factory_bot/user.rb +22 -0
- data/lib/meibo/factory_bot/user_profile.rb +21 -0
- data/lib/meibo/japan_profile/academic_session.rb +26 -0
- data/lib/meibo/japan_profile/classroom.rb +21 -0
- data/lib/meibo/japan_profile/course.rb +18 -0
- data/lib/meibo/japan_profile/demographic.rb +15 -0
- data/lib/meibo/japan_profile/enrollment.rb +35 -0
- data/lib/meibo/japan_profile/organization.rb +20 -0
- data/lib/meibo/japan_profile/role.rb +26 -0
- data/lib/meibo/japan_profile/user.rb +27 -0
- data/lib/meibo/japan_profile/user_profile.rb +7 -0
- data/lib/meibo/japan_profile.rb +39 -0
- data/lib/meibo/manifest/processing_mode.rb +40 -0
- data/lib/meibo/manifest.rb +163 -0
- data/lib/meibo/organization.rb +44 -0
- data/lib/meibo/organization_set.rb +15 -0
- data/lib/meibo/reader.rb +138 -0
- data/lib/meibo/role.rb +65 -0
- data/lib/meibo/role_set.rb +25 -0
- data/lib/meibo/roster.rb +166 -0
- data/lib/meibo/user.rb +71 -0
- data/lib/meibo/user_profile.rb +42 -0
- data/lib/meibo/user_profile_set.rb +18 -0
- data/lib/meibo/user_set.rb +24 -0
- data/lib/meibo/version.rb +5 -0
- data/lib/meibo.rb +17 -0
- data/meibo.gemspec +38 -0
- data/sig/meibo.rbs +4 -0
- metadata +148 -0
    
        data/lib/meibo/roster.rb
    ADDED
    
    | @@ -0,0 +1,166 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'zip'
         | 
| 4 | 
            +
            require 'csv'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module Meibo
         | 
| 7 | 
            +
              class Roster
         | 
| 8 | 
            +
                class << self
         | 
| 9 | 
            +
                  def from_file(file_path, profile: BaseProfile)
         | 
| 10 | 
            +
                    Reader.open(file_path, profile: profile) do |reader|
         | 
| 11 | 
            +
                      begin
         | 
| 12 | 
            +
                        manifest = reader.manifest
         | 
| 13 | 
            +
                      rescue CsvFileNotFoundError
         | 
| 14 | 
            +
                        raise NotSupportedError, 'OneRoster 1.0はサポートしていません'
         | 
| 15 | 
            +
                      rescue
         | 
| 16 | 
            +
                        raise NotSupportedError, "#{Meibo::Manifest.filename}の読み込みに失敗しました"
         | 
| 17 | 
            +
                      end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                      validate_manifest_version(manifest.manifest_version)
         | 
| 20 | 
            +
                      validate_oneroster_version(manifest.oneroster_version)
         | 
| 21 | 
            +
                      validate_supported_processing_mode(manifest)
         | 
| 22 | 
            +
                      processing_modes = Meibo::Manifest::PROCESSING_MODES
         | 
| 23 | 
            +
                      validate_absent_files(reader, manifest.filenames(processing_mode: processing_modes[:absent]))
         | 
| 24 | 
            +
                      validate_bulk_files(reader, manifest.filenames(processing_mode: processing_modes[:bulk]))
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                      new(manifest_properties: manifest.to_h, profile: profile, **reader.load_bulk_files).tap(&:check_semantically_consistent)
         | 
| 27 | 
            +
                    end
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  private
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  def validate_absent_files(reader, absent_filenames)
         | 
| 33 | 
            +
                    absent_filenames.each do |absent_filename|
         | 
| 34 | 
            +
                      next unless reader.file_entry?(absent_filename)
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                      raise NotSupportedError, "#{absent_filename}が存在します"
         | 
| 37 | 
            +
                    end
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def validate_bulk_files(reader, bulk_filenames)
         | 
| 41 | 
            +
                    bulk_filenames.each do |bulk_filename|
         | 
| 42 | 
            +
                      next if reader.file_entry?(bulk_filename)
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                      raise NotSupportedError, "#{bulk_filename}が存在しません"
         | 
| 45 | 
            +
                    end
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  def validate_manifest_version(manifest_version)
         | 
| 49 | 
            +
                    return if manifest_version == Meibo::Manifest::MANIFEST_VERSION
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                    raise NotSupportedError, "manifest.version: #{manifest_version}はサポートしていません"
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  def validate_oneroster_version(oneroster_version)
         | 
| 55 | 
            +
                    return if oneroster_version == Meibo::Manifest::ONEROSTER_VERSION
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                    raise NotSupportedError, "oneroster.version: #{oneroster_version}はサポートしていません"
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                  def validate_supported_processing_mode(manifest)
         | 
| 61 | 
            +
                    return if manifest.file_attributes(processing_mode: Meibo::Manifest::PROCESSING_MODES[:delta]).empty?
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                    raise NotSupportedError, 'DELTAはサポートしていません'
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                attr_reader :profile, :manifest_properties, :academic_sessions, :classes, :courses, :demographics, :enrollments, :organizations, :roles, :user_profiles, :users
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                def initialize(profile: BaseProfile, manifest_properties: {}, academic_sessions: [], classes: [], courses: [], demographics: [], enrollments: [], organizations: [], roles: [], user_profiles: [], users: [])
         | 
| 70 | 
            +
                  @profile = profile
         | 
| 71 | 
            +
                  @manifest_properties = manifest_properties
         | 
| 72 | 
            +
                  @academic_sessions = AcademicSessionSet.new(academic_sessions)
         | 
| 73 | 
            +
                  @organizations = OrganizationSet.new(organizations)
         | 
| 74 | 
            +
                  @courses = CourseSet.new(courses, academic_session_set: @academic_sessions, organization_set: @organizations)
         | 
| 75 | 
            +
                  @classes = ClassroomSet.new(classes, academic_session_set: @academic_sessions, course_set: @courses, organization_set: @organizations)
         | 
| 76 | 
            +
                  @users = UserSet.new(users, organization_set: @organizations)
         | 
| 77 | 
            +
                  @demographics = DemographicSet.new(demographics, user_set: @users)
         | 
| 78 | 
            +
                  @user_profiles = UserProfileSet.new(user_profiles, user_set: @users)
         | 
| 79 | 
            +
                  @roles = RoleSet.new(roles, organization_set: @organizations, user_set: @users, user_profile_set: @user_profiles)
         | 
| 80 | 
            +
                  @enrollments = EnrollmentSet.new(enrollments, classroom_set: @classes, organization_set: @organizations, user_set: @users)
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                def check_semantically_consistent
         | 
| 84 | 
            +
                  [
         | 
| 85 | 
            +
                    academic_sessions,
         | 
| 86 | 
            +
                    classes,
         | 
| 87 | 
            +
                    courses,
         | 
| 88 | 
            +
                    demographics,
         | 
| 89 | 
            +
                    enrollments,
         | 
| 90 | 
            +
                    organizations,
         | 
| 91 | 
            +
                    roles,
         | 
| 92 | 
            +
                    user_profiles,
         | 
| 93 | 
            +
                    users
         | 
| 94 | 
            +
                  ].each(&:check_semantically_consistent)
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                def write(path)
         | 
| 98 | 
            +
                  Zip::File.open(path, ::Zip::File::CREATE) do |zipfile|
         | 
| 99 | 
            +
                    manifest = build_manifest
         | 
| 100 | 
            +
                    zipfile.get_output_stream(::Meibo::Manifest.filename) do |f|
         | 
| 101 | 
            +
                      f.puts ::Meibo::Manifest.header_fields.to_csv
         | 
| 102 | 
            +
                      manifest.to_a.each do |row|
         | 
| 103 | 
            +
                        f.puts row.to_csv
         | 
| 104 | 
            +
                      end
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
                    file_properties.each do |file_attribute, processing_mode|
         | 
| 107 | 
            +
                      next if processing_mode.absent?
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                      klass = profile.data_model_for(file_attribute)
         | 
| 110 | 
            +
                      filename = Manifest.filename_for(file_attribute)
         | 
| 111 | 
            +
                      data = data_for(file_attribute)
         | 
| 112 | 
            +
                      zipfile.get_output_stream(filename) do |f|
         | 
| 113 | 
            +
                        f.puts klass.header_fields.to_csv
         | 
| 114 | 
            +
                        data.each do |row|
         | 
| 115 | 
            +
                          f.puts row.to_csv(write_converters: klass.write_converters)
         | 
| 116 | 
            +
                        end
         | 
| 117 | 
            +
                      end
         | 
| 118 | 
            +
                    end
         | 
| 119 | 
            +
                  end
         | 
| 120 | 
            +
                end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                private
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                def build_manifest
         | 
| 125 | 
            +
                  new_manifest_properties = file_properties.merge(manifest_properties)
         | 
| 126 | 
            +
                  Meibo::Manifest.build_from_default(**new_manifest_properties)
         | 
| 127 | 
            +
                end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                def data_for(file_attribute)
         | 
| 130 | 
            +
                  data_method = {
         | 
| 131 | 
            +
                    file_academic_sessions: :academic_sessions,
         | 
| 132 | 
            +
                    file_classes: :classes,
         | 
| 133 | 
            +
                    file_courses: :courses,
         | 
| 134 | 
            +
                    file_demographics: :demographics,
         | 
| 135 | 
            +
                    file_enrollments: :enrollments,
         | 
| 136 | 
            +
                    file_orgs: :organizations,
         | 
| 137 | 
            +
                    file_roles: :roles,
         | 
| 138 | 
            +
                    file_user_profiles: :user_profiles,
         | 
| 139 | 
            +
                    file_users: :users
         | 
| 140 | 
            +
                  }[file_attribute]
         | 
| 141 | 
            +
                  public_send(data_method)
         | 
| 142 | 
            +
                end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                def file_properties
         | 
| 145 | 
            +
                  {
         | 
| 146 | 
            +
                    file_academic_sessions: procesing_mode(academic_sessions),
         | 
| 147 | 
            +
                    file_classes: procesing_mode(classes),
         | 
| 148 | 
            +
                    file_courses: procesing_mode(courses),
         | 
| 149 | 
            +
                    file_demographics: procesing_mode(demographics),
         | 
| 150 | 
            +
                    file_enrollments: procesing_mode(enrollments),
         | 
| 151 | 
            +
                    file_orgs: procesing_mode(organizations),
         | 
| 152 | 
            +
                    file_roles: procesing_mode(roles),
         | 
| 153 | 
            +
                    file_user_profiles: procesing_mode(user_profiles),
         | 
| 154 | 
            +
                    file_users: procesing_mode(users)
         | 
| 155 | 
            +
                  }
         | 
| 156 | 
            +
                end
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                def procesing_mode(data)
         | 
| 159 | 
            +
                  if data.empty?
         | 
| 160 | 
            +
                    Meibo::Manifest::PROCESSING_MODES[:absent]
         | 
| 161 | 
            +
                  else
         | 
| 162 | 
            +
                    Meibo::Manifest::PROCESSING_MODES[:bulk]
         | 
| 163 | 
            +
                  end
         | 
| 164 | 
            +
                end
         | 
| 165 | 
            +
              end
         | 
| 166 | 
            +
            end
         | 
    
        data/lib/meibo/user.rb
    ADDED
    
    | @@ -0,0 +1,71 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Meibo
         | 
| 4 | 
            +
              class User
         | 
| 5 | 
            +
                USER_ID_FORMAT_REGEXP = /\A\{[^:\}]+:[^\}]+\}\z/
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                DataModel.define(
         | 
| 8 | 
            +
                  self,
         | 
| 9 | 
            +
                  attribute_name_to_header_field_map: {
         | 
| 10 | 
            +
                    sourced_id: 'sourcedId',
         | 
| 11 | 
            +
                    status: 'status',
         | 
| 12 | 
            +
                    date_last_modified: 'dateLastModified',
         | 
| 13 | 
            +
                    enabled_user: 'enabledUser',
         | 
| 14 | 
            +
                    username: 'username',
         | 
| 15 | 
            +
                    user_ids: 'userIds',
         | 
| 16 | 
            +
                    given_name: 'givenName',
         | 
| 17 | 
            +
                    family_name: 'familyName',
         | 
| 18 | 
            +
                    middle_name: 'middleName',
         | 
| 19 | 
            +
                    identifier: 'identifier',
         | 
| 20 | 
            +
                    email: 'email',
         | 
| 21 | 
            +
                    sms: 'sms',
         | 
| 22 | 
            +
                    phone: 'phone',
         | 
| 23 | 
            +
                    agent_sourced_ids: 'agentSourcedIds',
         | 
| 24 | 
            +
                    grades: 'grades',
         | 
| 25 | 
            +
                    password: 'password',
         | 
| 26 | 
            +
                    user_master_identifier: 'userMasterIdentifier',
         | 
| 27 | 
            +
                    resource_sourced_ids: 'resourceSourcedIds',
         | 
| 28 | 
            +
                    preferred_given_name: 'preferredGivenName',
         | 
| 29 | 
            +
                    preferred_middle_name: 'preferredMiddleName',
         | 
| 30 | 
            +
                    preferred_family_name: 'preferredFamilyName',
         | 
| 31 | 
            +
                    primary_org_sourced_id: 'primaryOrgSourcedId',
         | 
| 32 | 
            +
                    pronouns: 'pronouns'
         | 
| 33 | 
            +
                  }.freeze,
         | 
| 34 | 
            +
                  converters: {
         | 
| 35 | 
            +
                    boolean: [:enabled_user].freeze,
         | 
| 36 | 
            +
                    datetime: [:date_last_modified].freeze,
         | 
| 37 | 
            +
                    list: [:user_ids, :agent_sourced_ids, :grades, :resource_sourced_ids].freeze,
         | 
| 38 | 
            +
                    required: [:sourced_id, :enabled_user, :username, :given_name, :family_name].freeze,
         | 
| 39 | 
            +
                    status: [:status].freeze,
         | 
| 40 | 
            +
                    user_ids: [:user_ids].freeze
         | 
| 41 | 
            +
                  }.freeze
         | 
| 42 | 
            +
                )
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                def initialize(sourced_id:, status: nil, date_last_modified: nil, enabled_user: nil, username:, user_ids: nil, given_name:, family_name:, middle_name: nil, identifier: nil, email: nil, sms: nil, phone: nil, agent_sourced_ids: [], grades: nil, password: nil, user_master_identifier: nil, resource_sourced_ids: nil, preferred_given_name: nil, preferred_middle_name: nil, preferred_family_name: nil, primary_org_sourced_id: nil, pronouns: nil, kana_given_name: nil, kana_family_name: nil, kana_middle_name: nil, home_class: nil, **extension_fields)
         | 
| 45 | 
            +
                  @sourced_id = sourced_id
         | 
| 46 | 
            +
                  @status = status
         | 
| 47 | 
            +
                  @date_last_modified = date_last_modified
         | 
| 48 | 
            +
                  @enabled_user = enabled_user
         | 
| 49 | 
            +
                  @username = username
         | 
| 50 | 
            +
                  @user_ids = user_ids
         | 
| 51 | 
            +
                  @given_name = given_name
         | 
| 52 | 
            +
                  @family_name = family_name
         | 
| 53 | 
            +
                  @middle_name = middle_name
         | 
| 54 | 
            +
                  @identifier = identifier
         | 
| 55 | 
            +
                  @email = email
         | 
| 56 | 
            +
                  @sms = sms
         | 
| 57 | 
            +
                  @phone = phone
         | 
| 58 | 
            +
                  @agent_sourced_ids = agent_sourced_ids
         | 
| 59 | 
            +
                  @grades = grades
         | 
| 60 | 
            +
                  @password = password
         | 
| 61 | 
            +
                  @user_master_identifier = user_master_identifier
         | 
| 62 | 
            +
                  @resource_sourced_ids = resource_sourced_ids
         | 
| 63 | 
            +
                  @preferred_given_name = preferred_given_name
         | 
| 64 | 
            +
                  @preferred_middle_name = preferred_middle_name
         | 
| 65 | 
            +
                  @preferred_family_name = preferred_family_name
         | 
| 66 | 
            +
                  @primary_org_sourced_id = primary_org_sourced_id
         | 
| 67 | 
            +
                  @pronouns = pronouns
         | 
| 68 | 
            +
                  @extension_fields = extension_fields
         | 
| 69 | 
            +
                end
         | 
| 70 | 
            +
              end
         | 
| 71 | 
            +
            end
         | 
| @@ -0,0 +1,42 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Meibo
         | 
| 4 | 
            +
              class UserProfile
         | 
| 5 | 
            +
                DataModel.define(
         | 
| 6 | 
            +
                  self,
         | 
| 7 | 
            +
                  attribute_name_to_header_field_map: {
         | 
| 8 | 
            +
                    sourced_id: 'sourcedId',
         | 
| 9 | 
            +
                    status: 'status',
         | 
| 10 | 
            +
                    date_last_modified: 'dateLastModified',
         | 
| 11 | 
            +
                    user_sourced_id: 'userSourcedId',
         | 
| 12 | 
            +
                    profile_type: 'profileType',
         | 
| 13 | 
            +
                    vendor_id: 'vendorId',
         | 
| 14 | 
            +
                    application_id: 'applicationId',
         | 
| 15 | 
            +
                    description: 'description',
         | 
| 16 | 
            +
                    credential_type: 'credentialType',
         | 
| 17 | 
            +
                    username: 'username',
         | 
| 18 | 
            +
                    password: 'password'
         | 
| 19 | 
            +
                  },
         | 
| 20 | 
            +
                  converters: {
         | 
| 21 | 
            +
                    datetime: [:date_last_modified],
         | 
| 22 | 
            +
                    required: [:sourced_id, :user_sourced_id, :profile_type, :vendor_id, :credential_type, :username],
         | 
| 23 | 
            +
                    status: [:status]
         | 
| 24 | 
            +
                  }
         | 
| 25 | 
            +
                )
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def initialize(sourced_id:, status: nil, date_last_modified: nil, user_sourced_id:, profile_type:, vendor_id:, application_id: nil, description: nil, credential_type:, username:, password: nil, **extension_fields)
         | 
| 28 | 
            +
                  @sourced_id = sourced_id
         | 
| 29 | 
            +
                  @status = status
         | 
| 30 | 
            +
                  @date_last_modified = date_last_modified
         | 
| 31 | 
            +
                  @user_sourced_id = user_sourced_id
         | 
| 32 | 
            +
                  @profile_type = profile_type
         | 
| 33 | 
            +
                  @vendor_id = vendor_id
         | 
| 34 | 
            +
                  @application_id = application_id
         | 
| 35 | 
            +
                  @description = description
         | 
| 36 | 
            +
                  @credential_type = credential_type
         | 
| 37 | 
            +
                  @username = username
         | 
| 38 | 
            +
                  @password = password
         | 
| 39 | 
            +
                  @extension_fields = extension_fields
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
            end
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Meibo
         | 
| 4 | 
            +
              class UserProfileSet < DataSet
         | 
| 5 | 
            +
                def initialize(data, user_set:)
         | 
| 6 | 
            +
                  super(data)
         | 
| 7 | 
            +
                  @user_set = user_set
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def check_semantically_consistent
         | 
| 11 | 
            +
                  super
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  each do |user_profile|
         | 
| 14 | 
            +
                    @user_set.find_by_sourced_id(user_profile.user_sourced_id)
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Meibo
         | 
| 4 | 
            +
              class UserSet < DataSet
         | 
| 5 | 
            +
                def initialize(data, organization_set:)
         | 
| 6 | 
            +
                  super(data)
         | 
| 7 | 
            +
                  @organization_set = organization_set
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def check_semantically_consistent
         | 
| 11 | 
            +
                  super
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  each do |user|
         | 
| 14 | 
            +
                    if user.primary_org_sourced_id
         | 
| 15 | 
            +
                      @organization_set.find_by_sourced_id(user.primary_org_sourced_id)
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    user.agent_sourced_ids.each do |agent_sourced_id|
         | 
| 19 | 
            +
                      find_by_sourced_id(agent_sourced_id)
         | 
| 20 | 
            +
                    end
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
            end
         | 
    
        data/lib/meibo.rb
    ADDED
    
    | @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require "zeitwerk"
         | 
| 4 | 
            +
            loader = Zeitwerk::Loader.for_gem
         | 
| 5 | 
            +
            loader.ignore("#{__dir__}/meibo/errors.rb")
         | 
| 6 | 
            +
            loader.ignore("#{__dir__}/meibo/factory_bot")
         | 
| 7 | 
            +
            loader.setup
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            require_relative "meibo/version"
         | 
| 10 | 
            +
            require_relative "meibo/errors"
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            module Meibo
         | 
| 13 | 
            +
              CSV_ENCODING = 'UTF-8'
         | 
| 14 | 
            +
              ENUM_EXT_PATTERN = /\Aext:[a-zA-Z0-9\.\-_]+\z/
         | 
| 15 | 
            +
            end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            loader.eager_load
         | 
    
        data/meibo.gemspec
    ADDED
    
    | @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require_relative "lib/meibo/version"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Gem::Specification.new do |spec|
         | 
| 6 | 
            +
              spec.name = "meibo"
         | 
| 7 | 
            +
              spec.version = Meibo::VERSION
         | 
| 8 | 
            +
              spec.authors = ["Seiei Miyagi"]
         | 
| 9 | 
            +
              spec.email = ["hanachin@gmail.com"]
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              spec.summary = "Meibo is a ruby library for OneRoster CSV Binding Japan Profile."
         | 
| 12 | 
            +
              spec.homepage = "https://github.com/hanachin/meibo"
         | 
| 13 | 
            +
              spec.license = "MIT"
         | 
| 14 | 
            +
              spec.required_ruby_version = ">= 2.7.0"
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              spec.metadata["allowed_push_host"] = "https://rubygems.org/"
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              spec.metadata["homepage_uri"] = spec.homepage
         | 
| 19 | 
            +
              spec.metadata["source_code_uri"] = "https://github.com/hanachin/meibo"
         | 
| 20 | 
            +
              spec.metadata["changelog_uri"] = "https://github.com/hanachin/meibo/blob/meibo/v#{Meibo::VERSION}/CHANGELOG.md"
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              # Specify which files should be added to the gem when it is released.
         | 
| 23 | 
            +
              # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
         | 
| 24 | 
            +
              spec.files = Dir.chdir(File.expand_path(__dir__)) do
         | 
| 25 | 
            +
                `git ls-files -z`.split("\x0").reject do |f|
         | 
| 26 | 
            +
                  (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
              spec.bindir = "exe"
         | 
| 30 | 
            +
              spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
         | 
| 31 | 
            +
              spec.require_paths = ["lib"]
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              spec.add_dependency "rubyzip"
         | 
| 34 | 
            +
              spec.add_dependency "zeitwerk"
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              # For more information and examples about making a new gem, check out our
         | 
| 37 | 
            +
              # guide at: https://bundler.io/guides/creating_gem.html
         | 
| 38 | 
            +
            end
         | 
    
        data/sig/meibo.rbs
    ADDED
    
    
    
        metadata
    ADDED
    
    | @@ -0,0 +1,148 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: meibo
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.1.0
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors:
         | 
| 7 | 
            +
            - Seiei Miyagi
         | 
| 8 | 
            +
            autorequire:
         | 
| 9 | 
            +
            bindir: exe
         | 
| 10 | 
            +
            cert_chain: []
         | 
| 11 | 
            +
            date: 2022-11-04 00:00:00.000000000 Z
         | 
| 12 | 
            +
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: rubyzip
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - ">="
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: '0'
         | 
| 20 | 
            +
              type: :runtime
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - ">="
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: '0'
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: zeitwerk
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - ">="
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: '0'
         | 
| 34 | 
            +
              type: :runtime
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - ">="
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: '0'
         | 
| 41 | 
            +
            description:
         | 
| 42 | 
            +
            email:
         | 
| 43 | 
            +
            - hanachin@gmail.com
         | 
| 44 | 
            +
            executables: []
         | 
| 45 | 
            +
            extensions: []
         | 
| 46 | 
            +
            extra_rdoc_files: []
         | 
| 47 | 
            +
            files:
         | 
| 48 | 
            +
            - ".rspec"
         | 
| 49 | 
            +
            - ".rubocop.yml"
         | 
| 50 | 
            +
            - CHANGELOG.md
         | 
| 51 | 
            +
            - CODE_OF_CONDUCT.md
         | 
| 52 | 
            +
            - Gemfile
         | 
| 53 | 
            +
            - Gemfile.lock
         | 
| 54 | 
            +
            - LICENSE.txt
         | 
| 55 | 
            +
            - README.md
         | 
| 56 | 
            +
            - Rakefile
         | 
| 57 | 
            +
            - lib/meibo.rb
         | 
| 58 | 
            +
            - lib/meibo/academic_session.rb
         | 
| 59 | 
            +
            - lib/meibo/academic_session_set.rb
         | 
| 60 | 
            +
            - lib/meibo/base_profile.rb
         | 
| 61 | 
            +
            - lib/meibo/builder.rb
         | 
| 62 | 
            +
            - lib/meibo/builder/academic_session_builder.rb
         | 
| 63 | 
            +
            - lib/meibo/builder/base_builder.rb
         | 
| 64 | 
            +
            - lib/meibo/builder/classroom_builder.rb
         | 
| 65 | 
            +
            - lib/meibo/builder/course_builder.rb
         | 
| 66 | 
            +
            - lib/meibo/builder/demographic_builder.rb
         | 
| 67 | 
            +
            - lib/meibo/builder/enrollment_builder.rb
         | 
| 68 | 
            +
            - lib/meibo/builder/organization_builder.rb
         | 
| 69 | 
            +
            - lib/meibo/builder/role_builder.rb
         | 
| 70 | 
            +
            - lib/meibo/builder/user_builder.rb
         | 
| 71 | 
            +
            - lib/meibo/builder/user_profile_builder.rb
         | 
| 72 | 
            +
            - lib/meibo/classroom.rb
         | 
| 73 | 
            +
            - lib/meibo/classroom_set.rb
         | 
| 74 | 
            +
            - lib/meibo/converter.rb
         | 
| 75 | 
            +
            - lib/meibo/course.rb
         | 
| 76 | 
            +
            - lib/meibo/course_set.rb
         | 
| 77 | 
            +
            - lib/meibo/data_model.rb
         | 
| 78 | 
            +
            - lib/meibo/data_set.rb
         | 
| 79 | 
            +
            - lib/meibo/demographic.rb
         | 
| 80 | 
            +
            - lib/meibo/demographic_set.rb
         | 
| 81 | 
            +
            - lib/meibo/enrollment.rb
         | 
| 82 | 
            +
            - lib/meibo/enrollment_set.rb
         | 
| 83 | 
            +
            - lib/meibo/errors.rb
         | 
| 84 | 
            +
            - lib/meibo/factory_bot/academic_session.rb
         | 
| 85 | 
            +
            - lib/meibo/factory_bot/all.rb
         | 
| 86 | 
            +
            - lib/meibo/factory_bot/classroom.rb
         | 
| 87 | 
            +
            - lib/meibo/factory_bot/course.rb
         | 
| 88 | 
            +
            - lib/meibo/factory_bot/demographic.rb
         | 
| 89 | 
            +
            - lib/meibo/factory_bot/enrollment.rb
         | 
| 90 | 
            +
            - lib/meibo/factory_bot/manifest.rb
         | 
| 91 | 
            +
            - lib/meibo/factory_bot/memory_package.rb
         | 
| 92 | 
            +
            - lib/meibo/factory_bot/organization.rb
         | 
| 93 | 
            +
            - lib/meibo/factory_bot/role.rb
         | 
| 94 | 
            +
            - lib/meibo/factory_bot/user.rb
         | 
| 95 | 
            +
            - lib/meibo/factory_bot/user_profile.rb
         | 
| 96 | 
            +
            - lib/meibo/japan_profile.rb
         | 
| 97 | 
            +
            - lib/meibo/japan_profile/academic_session.rb
         | 
| 98 | 
            +
            - lib/meibo/japan_profile/classroom.rb
         | 
| 99 | 
            +
            - lib/meibo/japan_profile/course.rb
         | 
| 100 | 
            +
            - lib/meibo/japan_profile/demographic.rb
         | 
| 101 | 
            +
            - lib/meibo/japan_profile/enrollment.rb
         | 
| 102 | 
            +
            - lib/meibo/japan_profile/organization.rb
         | 
| 103 | 
            +
            - lib/meibo/japan_profile/role.rb
         | 
| 104 | 
            +
            - lib/meibo/japan_profile/user.rb
         | 
| 105 | 
            +
            - lib/meibo/japan_profile/user_profile.rb
         | 
| 106 | 
            +
            - lib/meibo/manifest.rb
         | 
| 107 | 
            +
            - lib/meibo/manifest/processing_mode.rb
         | 
| 108 | 
            +
            - lib/meibo/organization.rb
         | 
| 109 | 
            +
            - lib/meibo/organization_set.rb
         | 
| 110 | 
            +
            - lib/meibo/reader.rb
         | 
| 111 | 
            +
            - lib/meibo/role.rb
         | 
| 112 | 
            +
            - lib/meibo/role_set.rb
         | 
| 113 | 
            +
            - lib/meibo/roster.rb
         | 
| 114 | 
            +
            - lib/meibo/user.rb
         | 
| 115 | 
            +
            - lib/meibo/user_profile.rb
         | 
| 116 | 
            +
            - lib/meibo/user_profile_set.rb
         | 
| 117 | 
            +
            - lib/meibo/user_set.rb
         | 
| 118 | 
            +
            - lib/meibo/version.rb
         | 
| 119 | 
            +
            - meibo.gemspec
         | 
| 120 | 
            +
            - sig/meibo.rbs
         | 
| 121 | 
            +
            homepage: https://github.com/hanachin/meibo
         | 
| 122 | 
            +
            licenses:
         | 
| 123 | 
            +
            - MIT
         | 
| 124 | 
            +
            metadata:
         | 
| 125 | 
            +
              allowed_push_host: https://rubygems.org/
         | 
| 126 | 
            +
              homepage_uri: https://github.com/hanachin/meibo
         | 
| 127 | 
            +
              source_code_uri: https://github.com/hanachin/meibo
         | 
| 128 | 
            +
              changelog_uri: https://github.com/hanachin/meibo/blob/meibo/v0.1.0/CHANGELOG.md
         | 
| 129 | 
            +
            post_install_message:
         | 
| 130 | 
            +
            rdoc_options: []
         | 
| 131 | 
            +
            require_paths:
         | 
| 132 | 
            +
            - lib
         | 
| 133 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 134 | 
            +
              requirements:
         | 
| 135 | 
            +
              - - ">="
         | 
| 136 | 
            +
                - !ruby/object:Gem::Version
         | 
| 137 | 
            +
                  version: 2.7.0
         | 
| 138 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 139 | 
            +
              requirements:
         | 
| 140 | 
            +
              - - ">="
         | 
| 141 | 
            +
                - !ruby/object:Gem::Version
         | 
| 142 | 
            +
                  version: '0'
         | 
| 143 | 
            +
            requirements: []
         | 
| 144 | 
            +
            rubygems_version: 3.2.26
         | 
| 145 | 
            +
            signing_key:
         | 
| 146 | 
            +
            specification_version: 4
         | 
| 147 | 
            +
            summary: Meibo is a ruby library for OneRoster CSV Binding Japan Profile.
         | 
| 148 | 
            +
            test_files: []
         |