canvas_sync 0.10.6 → 0.11.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 +5 -5
- data/lib/canvas_sync.rb +10 -0
- data/lib/canvas_sync/api_syncable.rb +8 -0
- data/lib/canvas_sync/generators/templates/migrations/create_admins.rb +7 -4
- data/lib/canvas_sync/generators/templates/migrations/create_roles.rb +3 -4
- data/lib/canvas_sync/generators/templates/models/account.rb +2 -0
- data/lib/canvas_sync/generators/templates/models/admin.rb +4 -5
- data/lib/canvas_sync/generators/templates/models/role.rb +0 -4
- data/lib/canvas_sync/generators/templates/models/term.rb +0 -2
- data/lib/canvas_sync/job.rb +10 -0
- data/lib/canvas_sync/jobs/sync_admins_job.rb +9 -5
- data/lib/canvas_sync/jobs/sync_roles_job.rb +8 -5
- data/lib/canvas_sync/jobs/sync_terms_job.rb +8 -2
- data/lib/canvas_sync/version.rb +1 -1
- data/spec/canvas_sync/jobs/sync_admins_job_spec.rb +2 -1
- data/spec/canvas_sync/jobs/sync_roles_job_spec.rb +2 -1
- data/spec/canvas_sync/models/admins_spec.rb +3 -5
- data/spec/canvas_sync/models/roles_spec.rb +5 -5
- data/spec/canvas_sync/models/term_spec.rb +3 -3
- data/spec/dummy/app/models/account.rb +2 -0
- data/spec/dummy/app/models/admin.rb +4 -5
- data/spec/dummy/app/models/role.rb +0 -4
- data/spec/dummy/app/models/term.rb +0 -2
- data/spec/dummy/db/migrate/{20190702203628_create_roles.rb → 20190927204545_create_roles.rb} +3 -4
- data/spec/dummy/db/migrate/{20190702203629_create_admins.rb → 20190927204546_create_admins.rb} +7 -4
- data/spec/dummy/db/schema.rb +11 -9
- data/spec/factories/admin_factory.rb +0 -1
- data/spec/support/fake_canvas.rb +2 -2
- data/spec/support/fixtures/canvas_responses/roles.json +6 -0
- metadata +10 -21
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +0 -4188
- data/spec/dummy/log/test.log +0 -71696
- data/spec/support/fixtures/reports/provisioning_csv_unzipped/courses.csv +0 -3
- data/spec/support/fixtures/reports/provisioning_csv_unzipped/users.csv +0 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 | 
            -
             | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 2 | 
            +
            SHA1:
         | 
| 3 | 
            +
              metadata.gz: 4445382aaee8091e3d40bc0f836bfeaef14d99d1
         | 
| 4 | 
            +
              data.tar.gz: fa0ff09fd9f2132ab29fb80a95c1353e38f2bbd8
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 3acfbb161a7c11a8d2b6c093b52b55ef5b0bf82876ff0a8e28b0092753d56ea2b28f6fa65360bb4889f5145361897e45e813acd000e45b84f9e6e9b27ab538fa
         | 
| 7 | 
            +
              data.tar.gz: be69604343fe4458a9e5cac5d26a8e307b909e3a2e2693d6aa9bdab38c5e3271cc73dab72f8d98959a92b0ef7b515d634c7f62701d61b9681e4f40b6abb17857
         | 
    
        data/lib/canvas_sync.rb
    CHANGED
    
    | @@ -138,6 +138,16 @@ module CanvasSync | |
| 138 138 | 
             
                  sub_items
         | 
| 139 139 | 
             
                end
         | 
| 140 140 |  | 
| 141 | 
            +
                # Given a Model or Relation, scope it down to items that should be synced
         | 
| 142 | 
            +
                def sync_scope(scope)
         | 
| 143 | 
            +
                  terms = %i[should_canvas_sync active_for_canvas_sync should_sync active_for_sync active]
         | 
| 144 | 
            +
                  terms.each do |t|
         | 
| 145 | 
            +
                    return scope.send(t) if scope.respond_to?(t)
         | 
| 146 | 
            +
                  end
         | 
| 147 | 
            +
                  Rails.logger.warn("Could not filter Syncable Scope for model '#{scope.try(:model)&.name || scope.name}'")
         | 
| 148 | 
            +
                  scope
         | 
| 149 | 
            +
                end
         | 
| 150 | 
            +
             | 
| 141 151 | 
             
                # Syn any report to an specific set of models
         | 
| 142 152 | 
             
                #
         | 
| 143 153 | 
             
                # @param reports_mapping [Array<Hash>] List of reports with their specific model and params
         | 
| @@ -21,6 +21,14 @@ module CanvasSync::ApiSyncable | |
| 21 21 | 
             
                  inst
         | 
| 22 22 | 
             
                end
         | 
| 23 23 |  | 
| 24 | 
            +
                def create_or_update_from_api_params(api_params)
         | 
| 25 | 
            +
                  api_params = api_params.with_indifferent_access
         | 
| 26 | 
            +
                  inst = find_or_initialize_by(canvas_id: api_params[:id])
         | 
| 27 | 
            +
                  inst.update_from_api_params(api_params)
         | 
| 28 | 
            +
                  inst.save! if inst.changed?
         | 
| 29 | 
            +
                  inst
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 24 32 | 
             
                def api_sync_options=(opts)
         | 
| 25 33 | 
             
                  @api_sync_options = opts
         | 
| 26 34 | 
             
                end
         | 
| @@ -5,13 +5,16 @@ class CreateAdmins < ActiveRecord::Migration[5.1] | |
| 5 5 | 
             
                create_table :admins do |t|
         | 
| 6 6 | 
             
                  t.bigint :canvas_id, null: false
         | 
| 7 7 | 
             
                  t.string :role_name
         | 
| 8 | 
            -
                  t.bigint : | 
| 9 | 
            -
                  t. | 
| 10 | 
            -
                  t.bigint :canvas_user_id | 
| 11 | 
            -
                  t.string :workflow_state | 
| 8 | 
            +
                  t.bigint :canvas_account_id
         | 
| 9 | 
            +
                  t.bigint :canvas_role_id
         | 
| 10 | 
            +
                  t.bigint :canvas_user_id
         | 
| 11 | 
            +
                  t.string :workflow_state
         | 
| 12 12 |  | 
| 13 13 | 
             
                  t.timestamps
         | 
| 14 14 | 
             
                end
         | 
| 15 15 | 
             
                add_index :admins, :canvas_id, unique: true
         | 
| 16 | 
            +
                add_index :admins, :canvas_role_id
         | 
| 17 | 
            +
                add_index :admins, :canvas_user_id
         | 
| 18 | 
            +
                add_index :admins, :canvas_account_id
         | 
| 16 19 | 
             
              end
         | 
| 17 20 | 
             
            end
         | 
| @@ -4,11 +4,10 @@ class CreateRoles < ActiveRecord::Migration[5.1] | |
| 4 4 | 
             
              def change
         | 
| 5 5 | 
             
                create_table :roles do |t|
         | 
| 6 6 | 
             
                  t.integer :canvas_id, null: false
         | 
| 7 | 
            -
                  t.string :label | 
| 8 | 
            -
                  t.string :base_role_type | 
| 9 | 
            -
                  t.json :account
         | 
| 7 | 
            +
                  t.string :label
         | 
| 8 | 
            +
                  t.string :base_role_type
         | 
| 10 9 | 
             
                  t.integer :canvas_account_id
         | 
| 11 | 
            -
                  t.string :workflow_state | 
| 10 | 
            +
                  t.string :workflow_state
         | 
| 12 11 | 
             
                  t.json :permissions
         | 
| 13 12 |  | 
| 14 13 | 
             
                  t.timestamps
         | 
| @@ -4,6 +4,7 @@ class Admin < ApplicationRecord | |
| 4 4 | 
             
              include CanvasSync::ApiSyncable
         | 
| 5 5 |  | 
| 6 6 | 
             
              validates :canvas_id, uniqueness: true, presence: true
         | 
| 7 | 
            +
              belongs_to :account, primary_key: :canvas_id, foreign_key: :canvas_account_id, optional: true
         | 
| 7 8 | 
             
              belongs_to :user, primary_key: :canvas_id, foreign_key: :canvas_user_id, optional: true
         | 
| 8 9 | 
             
              belongs_to :role, primary_key: :canvas_id, foreign_key: :canvas_role_id, optional: true
         | 
| 9 10 |  | 
| @@ -11,16 +12,14 @@ class Admin < ApplicationRecord | |
| 11 12 | 
             
                canvas_id: :id,
         | 
| 12 13 | 
             
                role_name: :role,
         | 
| 13 14 | 
             
                canvas_role_id: :role_id,
         | 
| 14 | 
            -
                user_data: :user,
         | 
| 15 15 | 
             
                canvas_user_id: ->(r) { r['user']['id'] },
         | 
| 16 | 
            +
                # NOTICE: The :account_id field is added by CanvasSync - it is not included in the Canvas API response
         | 
| 17 | 
            +
                canvas_account_id: :account_id,
         | 
| 16 18 | 
             
                workflow_state: :workflow_state,
         | 
| 17 19 | 
             
              }, -> (api) {
         | 
| 18 | 
            -
                admins = api.account_admins( | 
| 20 | 
            +
                admins = api.account_admins(canvas_account_id).all_pages!
         | 
| 19 21 | 
             
                admin_data = admins.find{|admin| admin['id'] == canvas_id }
         | 
| 20 22 | 
             
                raise Footrest::HttpError::NotFound unless admin_data.present?
         | 
| 21 23 | 
             
                admin_data
         | 
| 22 24 | 
             
              })
         | 
| 23 | 
            -
             | 
| 24 | 
            -
              def self.create_or_update(params); find_or_initialize_by(canvas_id: params['id']).update_from_api_params!(params); end
         | 
| 25 | 
            -
             | 
| 26 25 | 
             
            end
         | 
| @@ -10,12 +10,8 @@ class Role < ApplicationRecord | |
| 10 10 | 
             
                canvas_id: :id,
         | 
| 11 11 | 
             
                label: :label,
         | 
| 12 12 | 
             
                base_role_type: :base_role_type,
         | 
| 13 | 
            -
                account: :account,
         | 
| 14 13 | 
             
                canvas_account_id: ->(r) { r.dig('account', 'id') },
         | 
| 15 14 | 
             
                permissions: :permissions,
         | 
| 16 15 | 
             
                workflow_state: :workflow_state,
         | 
| 17 16 | 
             
              }, -> (api) { api.get("/api/v1/accounts/#{canvas_account_id}/roles/#{canvas_id}") })
         | 
| 18 | 
            -
             | 
| 19 | 
            -
              def self.create_or_update(params); find_or_initialize_by(canvas_id: params['id']).update_from_api_params!(params); end
         | 
| 20 | 
            -
             | 
| 21 17 | 
             
            end
         | 
| @@ -21,8 +21,6 @@ class Term < ApplicationRecord | |
| 21 21 | 
             
                term_data
         | 
| 22 22 | 
             
              })
         | 
| 23 23 |  | 
| 24 | 
            -
              def self.create_or_update(params); find_or_initialize_by(canvas_id: params['id']).update_from_api_params!(params); end
         | 
| 25 | 
            -
             | 
| 26 24 | 
             
              # This is a sample scope created by the CanvasSync gem; feel
         | 
| 27 25 | 
             
              # free to customize it for your tool's requirements.
         | 
| 28 26 | 
             
              scope :active, -> {
         | 
    
        data/lib/canvas_sync/job.rb
    CHANGED
    
    | @@ -56,5 +56,15 @@ module CanvasSync | |
| 56 56 | 
             
                    status: JobLog::ENQUEUED_STATUS,
         | 
| 57 57 | 
             
                  )
         | 
| 58 58 | 
             
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                def update_or_create_model(model, params)
         | 
| 61 | 
            +
                  if model.respond_to? :create_or_update
         | 
| 62 | 
            +
                    model.create_or_update(params)
         | 
| 63 | 
            +
                  elsif model.method_defined? :update_from_api_params!
         | 
| 64 | 
            +
                    model.find_or_initialize_by(canvas_id: params['id']).update_from_api_params!(params)
         | 
| 65 | 
            +
                  else
         | 
| 66 | 
            +
                    raise "Could not create/update #{model.name}. It must have a create_or_update(params) ClassMethod or implement ApiSyncable."
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
                end
         | 
| 59 69 | 
             
              end
         | 
| 60 70 | 
             
            end
         | 
| @@ -7,12 +7,16 @@ module CanvasSync | |
| 7 7 | 
             
                  # @param job_chain [Hash]
         | 
| 8 8 | 
             
                  # @param options [Hash]
         | 
| 9 9 | 
             
                  def perform(job_chain, _options)
         | 
| 10 | 
            -
                     | 
| 11 | 
            -
                    CanvasSync.get_canvas_sync_client(job_chain[:global_options]) | 
| 12 | 
            -
             | 
| 13 | 
            -
                       | 
| 10 | 
            +
                    updated_admin_ids = []
         | 
| 11 | 
            +
                    api_client = CanvasSync.get_canvas_sync_client(job_chain[:global_options])
         | 
| 12 | 
            +
                    CanvasSync.sync_scope(Account).find_each do |acc|
         | 
| 13 | 
            +
                      api_client.account_admins(acc.canvas_id).all_pages_each do |admin_params|
         | 
| 14 | 
            +
                        admin_params[:account_id] = acc.canvas_id
         | 
| 15 | 
            +
                        admin = update_or_create_model(Admin, admin_params)
         | 
| 16 | 
            +
                        updated_admin_ids.push(admin.id)
         | 
| 17 | 
            +
                      end
         | 
| 14 18 | 
             
                    end
         | 
| 15 | 
            -
                    Admin.where.not(id:  | 
| 19 | 
            +
                    Admin.where.not(id: updated_admin_ids).update_all(workflow_state: 'inactive')
         | 
| 16 20 | 
             
                    CanvasSync.invoke_next(job_chain)
         | 
| 17 21 | 
             
                  end
         | 
| 18 22 | 
             
                end
         | 
| @@ -7,12 +7,15 @@ module CanvasSync | |
| 7 7 | 
             
                  # @param job_chain [Hash]
         | 
| 8 8 | 
             
                  # @param options [Hash]
         | 
| 9 9 | 
             
                  def perform(job_chain, _options)
         | 
| 10 | 
            -
                     | 
| 11 | 
            -
                    CanvasSync.get_canvas_sync_client(job_chain[:global_options]) | 
| 12 | 
            -
             | 
| 13 | 
            -
                       | 
| 10 | 
            +
                    updated_role_ids = []
         | 
| 11 | 
            +
                    api_client = CanvasSync.get_canvas_sync_client(job_chain[:global_options])
         | 
| 12 | 
            +
                    CanvasSync.sync_scope(Account).find_each do |acc|
         | 
| 13 | 
            +
                      api_client.list_roles(acc.canvas_id, state: %w[active inactive]).all_pages_each do |role_params|
         | 
| 14 | 
            +
                        role = update_or_create_model(Role, role_params)
         | 
| 15 | 
            +
                        updated_role_ids.push(role.id)
         | 
| 16 | 
            +
                      end
         | 
| 14 17 | 
             
                    end
         | 
| 15 | 
            -
                    Role.where.not(id:  | 
| 18 | 
            +
                    Role.where.not(id: updated_role_ids).update_all(workflow_state: 'inactive')
         | 
| 16 19 | 
             
                    CanvasSync.invoke_next(job_chain)
         | 
| 17 20 | 
             
                  end
         | 
| 18 21 | 
             
                end
         | 
| @@ -10,9 +10,15 @@ module CanvasSync | |
| 10 10 | 
             
                  def perform(job_chain, _options)
         | 
| 11 11 | 
             
                    CanvasSync.get_canvas_sync_client(job_chain[:global_options]).terms("self").all_pages!.each do |term_params|
         | 
| 12 12 | 
             
                      if job_chain[:global_options][:account_id]
         | 
| 13 | 
            -
                         | 
| 13 | 
            +
                        # These branches are primarily to support Legacy apps
         | 
| 14 | 
            +
                        if Term.respond_to?(:create_or_update) && Term.method(:create_or_update).arity.abs == 2
         | 
| 15 | 
            +
                          Term.create_or_update(term_params, job_chain[:global_options][:account_id])
         | 
| 16 | 
            +
                        else
         | 
| 17 | 
            +
                          term_params[:account_id] |= job_chain[:global_options][:account_id]
         | 
| 18 | 
            +
                          update_or_create_model(Term, term_params)
         | 
| 19 | 
            +
                        end
         | 
| 14 20 | 
             
                      else
         | 
| 15 | 
            -
                        Term | 
| 21 | 
            +
                        update_or_create_model(Term, term_params)
         | 
| 16 22 | 
             
                      end
         | 
| 17 23 | 
             
                    end
         | 
| 18 24 |  | 
    
        data/lib/canvas_sync/version.rb
    CHANGED
    
    
| @@ -2,10 +2,11 @@ require 'spec_helper' | |
| 2 2 |  | 
| 3 3 | 
             
            RSpec.describe CanvasSync::Jobs::SyncAdminsJob do
         | 
| 4 4 | 
             
              describe '#perform' do
         | 
| 5 | 
            +
                let!(:account) { FactoryGirl.create(:account, canvas_id: 1) }
         | 
| 5 6 | 
             
                let(:admin_params) { open_canvas_fixture('admins') }
         | 
| 6 7 | 
             
                let(:job_chain) { { jobs: [], global_options: {}} }
         | 
| 7 8 |  | 
| 8 | 
            -
                it 'retrieves all  | 
| 9 | 
            +
                it 'retrieves all admins from the Canvas API and then invokes the next job' do
         | 
| 9 10 | 
             
                  expect(CanvasSync).to receive(:invoke_next).with(job_chain)
         | 
| 10 11 |  | 
| 11 12 | 
             
                  expect {
         | 
| @@ -2,10 +2,11 @@ require 'spec_helper' | |
| 2 2 |  | 
| 3 3 | 
             
            RSpec.describe CanvasSync::Jobs::SyncRolesJob do
         | 
| 4 4 | 
             
              describe '#perform' do
         | 
| 5 | 
            +
                let!(:account) { FactoryGirl.create(:account, canvas_id: 1) }
         | 
| 5 6 | 
             
                let(:role_params) { open_canvas_fixture('roles') }
         | 
| 6 7 | 
             
                let(:job_chain) { { jobs: [], global_options: {}} }
         | 
| 7 8 |  | 
| 8 | 
            -
                it 'retrieves all  | 
| 9 | 
            +
                it 'retrieves all roles from the Canvas API and then invokes the next job' do
         | 
| 9 10 | 
             
                  expect(CanvasSync).to receive(:invoke_next).with(job_chain)
         | 
| 10 11 |  | 
| 11 12 | 
             
                  expect {
         | 
| @@ -8,19 +8,18 @@ RSpec.describe Admin, type: :model do | |
| 8 8 | 
             
                it { should validate_uniqueness_of(:canvas_id) }
         | 
| 9 9 | 
             
              end
         | 
| 10 10 |  | 
| 11 | 
            -
              describe '. | 
| 11 | 
            +
              describe '.create_or_update_from_api_params' do
         | 
| 12 12 | 
             
                let(:admin_params) { open_canvas_fixture('admins')[0] }
         | 
| 13 13 |  | 
| 14 14 | 
             
                context 'the admin does not already exist' do
         | 
| 15 15 | 
             
                  it 'creates it' do
         | 
| 16 16 | 
             
                    expect {
         | 
| 17 | 
            -
                      Admin. | 
| 17 | 
            +
                      Admin.create_or_update_from_api_params(admin_params)
         | 
| 18 18 | 
             
                    }.to change { Admin.count }.by(1)
         | 
| 19 19 |  | 
| 20 20 | 
             
                    admin = Admin.last
         | 
| 21 21 | 
             
                    expect(admin.role_name).to eq(admin_params['role'])
         | 
| 22 22 | 
             
                    expect(admin.canvas_role_id).to eq(admin_params['role_id'])
         | 
| 23 | 
            -
                    expect(admin.user_data).to eq(admin_params['user'])
         | 
| 24 23 | 
             
                    expect(admin.canvas_user_id).to eq(admin_params['user']['id'])
         | 
| 25 24 | 
             
                    expect(admin.workflow_state).to eq(admin_params['workflow_state'])
         | 
| 26 25 | 
             
                  end
         | 
| @@ -31,13 +30,12 @@ RSpec.describe Admin, type: :model do | |
| 31 30 |  | 
| 32 31 | 
             
                  it 'updates it' do
         | 
| 33 32 | 
             
                    expect {
         | 
| 34 | 
            -
                      Admin. | 
| 33 | 
            +
                      Admin.create_or_update_from_api_params(admin_params)
         | 
| 35 34 | 
             
                    }.to_not change { Admin.count }
         | 
| 36 35 |  | 
| 37 36 | 
             
                    existing_admin.reload
         | 
| 38 37 | 
             
                    expect(existing_admin.role_name).to eq(admin_params['role'])
         | 
| 39 38 | 
             
                    expect(existing_admin.canvas_role_id).to eq(admin_params['role_id'])
         | 
| 40 | 
            -
                    expect(existing_admin.user_data).to eq(admin_params['user'])
         | 
| 41 39 | 
             
                    expect(existing_admin.canvas_user_id).to eq(admin_params['user']['id'])
         | 
| 42 40 | 
             
                    expect(existing_admin.workflow_state).to eq(admin_params['workflow_state'])
         | 
| 43 41 | 
             
                  end
         | 
| @@ -8,19 +8,19 @@ RSpec.describe Role, type: :model do | |
| 8 8 | 
             
                it { should validate_uniqueness_of(:canvas_id) }
         | 
| 9 9 | 
             
              end
         | 
| 10 10 |  | 
| 11 | 
            -
              describe '. | 
| 11 | 
            +
              describe '.create_or_update_from_api_params' do
         | 
| 12 12 | 
             
                let(:role_params) { open_canvas_fixture('roles')[0] }
         | 
| 13 13 |  | 
| 14 14 | 
             
                context 'the role does not already exist' do
         | 
| 15 15 | 
             
                  it 'creates it' do
         | 
| 16 16 | 
             
                    expect {
         | 
| 17 | 
            -
                      Role. | 
| 17 | 
            +
                      Role.create_or_update_from_api_params(role_params)
         | 
| 18 18 | 
             
                    }.to change { Role.count }.by(1)
         | 
| 19 19 |  | 
| 20 20 | 
             
                    role = Role.last
         | 
| 21 21 | 
             
                    expect(role.label).to eq(role_params['label'])
         | 
| 22 22 | 
             
                    expect(role.base_role_type).to eq(role_params['base_role_type'])
         | 
| 23 | 
            -
                    expect(role. | 
| 23 | 
            +
                    expect(role.canvas_account_id).to eq(role_params['account']['id'])
         | 
| 24 24 | 
             
                    expect(role.permissions).to eq(role_params['permissions'])
         | 
| 25 25 | 
             
                    expect(role.workflow_state).to eq(role_params['workflow_state'])
         | 
| 26 26 | 
             
                  end
         | 
| @@ -31,13 +31,13 @@ RSpec.describe Role, type: :model do | |
| 31 31 |  | 
| 32 32 | 
             
                  it 'updates it' do
         | 
| 33 33 | 
             
                    expect {
         | 
| 34 | 
            -
                      Role. | 
| 34 | 
            +
                      Role.create_or_update_from_api_params(role_params)
         | 
| 35 35 | 
             
                    }.to_not change { Role.count }
         | 
| 36 36 |  | 
| 37 37 | 
             
                    existing_role.reload
         | 
| 38 38 | 
             
                    expect(existing_role.label).to eq(role_params['label'])
         | 
| 39 39 | 
             
                    expect(existing_role.base_role_type).to eq(role_params['base_role_type'])
         | 
| 40 | 
            -
                    expect(existing_role. | 
| 40 | 
            +
                    expect(existing_role.canvas_account_id).to eq(role_params['account']['id'])
         | 
| 41 41 | 
             
                    expect(existing_role.permissions).to eq(role_params['permissions'])
         | 
| 42 42 | 
             
                    expect(existing_role.workflow_state).to eq(role_params['workflow_state'])
         | 
| 43 43 | 
             
                  end
         | 
| @@ -29,13 +29,13 @@ RSpec.describe Term, type: :model do | |
| 29 29 | 
             
                end
         | 
| 30 30 | 
             
              end
         | 
| 31 31 |  | 
| 32 | 
            -
              describe '. | 
| 32 | 
            +
              describe '.create_or_update_from_api_params' do
         | 
| 33 33 | 
             
                let(:term_params) { open_canvas_fixture('terms')['enrollment_terms'][0] }
         | 
| 34 34 |  | 
| 35 35 | 
             
                context 'the term does not already exist' do
         | 
| 36 36 | 
             
                  it 'creates it' do
         | 
| 37 37 | 
             
                    expect {
         | 
| 38 | 
            -
                      Term. | 
| 38 | 
            +
                      Term.create_or_update_from_api_params(term_params)
         | 
| 39 39 | 
             
                    }.to change { Term.count }.by(1)
         | 
| 40 40 |  | 
| 41 41 | 
             
                    term = Term.last
         | 
| @@ -54,7 +54,7 @@ RSpec.describe Term, type: :model do | |
| 54 54 |  | 
| 55 55 | 
             
                  it 'updates it' do
         | 
| 56 56 | 
             
                    expect {
         | 
| 57 | 
            -
                      Term. | 
| 57 | 
            +
                      Term.create_or_update_from_api_params(term_params)
         | 
| 58 58 | 
             
                    }.to_not change { Term.count }
         | 
| 59 59 |  | 
| 60 60 | 
             
                    existing_term.reload
         | 
| @@ -10,6 +10,7 @@ class Admin < ApplicationRecord | |
| 10 10 | 
             
              include CanvasSync::ApiSyncable
         | 
| 11 11 |  | 
| 12 12 | 
             
              validates :canvas_id, uniqueness: true, presence: true
         | 
| 13 | 
            +
              belongs_to :account, primary_key: :canvas_id, foreign_key: :canvas_account_id, optional: true
         | 
| 13 14 | 
             
              belongs_to :user, primary_key: :canvas_id, foreign_key: :canvas_user_id, optional: true
         | 
| 14 15 | 
             
              belongs_to :role, primary_key: :canvas_id, foreign_key: :canvas_role_id, optional: true
         | 
| 15 16 |  | 
| @@ -17,16 +18,14 @@ class Admin < ApplicationRecord | |
| 17 18 | 
             
                canvas_id: :id,
         | 
| 18 19 | 
             
                role_name: :role,
         | 
| 19 20 | 
             
                canvas_role_id: :role_id,
         | 
| 20 | 
            -
                user_data: :user,
         | 
| 21 21 | 
             
                canvas_user_id: ->(r) { r['user']['id'] },
         | 
| 22 | 
            +
                # NOTICE: The :account_id field is added by CanvasSync - it is not included in the Canvas API response
         | 
| 23 | 
            +
                canvas_account_id: :account_id,
         | 
| 22 24 | 
             
                workflow_state: :workflow_state,
         | 
| 23 25 | 
             
              }, -> (api) {
         | 
| 24 | 
            -
                admins = api.account_admins( | 
| 26 | 
            +
                admins = api.account_admins(canvas_account_id).all_pages!
         | 
| 25 27 | 
             
                admin_data = admins.find{|admin| admin['id'] == canvas_id }
         | 
| 26 28 | 
             
                raise Footrest::HttpError::NotFound unless admin_data.present?
         | 
| 27 29 | 
             
                admin_data
         | 
| 28 30 | 
             
              })
         | 
| 29 | 
            -
             | 
| 30 | 
            -
              def self.create_or_update(params); find_or_initialize_by(canvas_id: params['id']).update_from_api_params!(params); end
         | 
| 31 | 
            -
             | 
| 32 31 | 
             
            end
         | 
| @@ -16,12 +16,8 @@ class Role < ApplicationRecord | |
| 16 16 | 
             
                canvas_id: :id,
         | 
| 17 17 | 
             
                label: :label,
         | 
| 18 18 | 
             
                base_role_type: :base_role_type,
         | 
| 19 | 
            -
                account: :account,
         | 
| 20 19 | 
             
                canvas_account_id: ->(r) { r.dig('account', 'id') },
         | 
| 21 20 | 
             
                permissions: :permissions,
         | 
| 22 21 | 
             
                workflow_state: :workflow_state,
         | 
| 23 22 | 
             
              }, -> (api) { api.get("/api/v1/accounts/#{canvas_account_id}/roles/#{canvas_id}") })
         | 
| 24 | 
            -
             | 
| 25 | 
            -
              def self.create_or_update(params); find_or_initialize_by(canvas_id: params['id']).update_from_api_params!(params); end
         | 
| 26 | 
            -
             | 
| 27 23 | 
             
            end
         | 
| @@ -27,8 +27,6 @@ class Term < ApplicationRecord | |
| 27 27 | 
             
                term_data
         | 
| 28 28 | 
             
              })
         | 
| 29 29 |  | 
| 30 | 
            -
              def self.create_or_update(params); find_or_initialize_by(canvas_id: params['id']).update_from_api_params!(params); end
         | 
| 31 | 
            -
             | 
| 32 30 | 
             
              # This is a sample scope created by the CanvasSync gem; feel
         | 
| 33 31 | 
             
              # free to customize it for your tool's requirements.
         | 
| 34 32 | 
             
              scope :active, -> {
         | 
    
        data/spec/dummy/db/migrate/{20190702203628_create_roles.rb → 20190927204545_create_roles.rb}
    RENAMED
    
    | @@ -10,11 +10,10 @@ class CreateRoles < ActiveRecord::Migration[5.1] | |
| 10 10 | 
             
              def change
         | 
| 11 11 | 
             
                create_table :roles do |t|
         | 
| 12 12 | 
             
                  t.integer :canvas_id, null: false
         | 
| 13 | 
            -
                  t.string :label | 
| 14 | 
            -
                  t.string :base_role_type | 
| 15 | 
            -
                  t.json :account
         | 
| 13 | 
            +
                  t.string :label
         | 
| 14 | 
            +
                  t.string :base_role_type
         | 
| 16 15 | 
             
                  t.integer :canvas_account_id
         | 
| 17 | 
            -
                  t.string :workflow_state | 
| 16 | 
            +
                  t.string :workflow_state
         | 
| 18 17 | 
             
                  t.json :permissions
         | 
| 19 18 |  | 
| 20 19 | 
             
                  t.timestamps
         | 
    
        data/spec/dummy/db/migrate/{20190702203629_create_admins.rb → 20190927204546_create_admins.rb}
    RENAMED
    
    | @@ -11,13 +11,16 @@ class CreateAdmins < ActiveRecord::Migration[5.1] | |
| 11 11 | 
             
                create_table :admins do |t|
         | 
| 12 12 | 
             
                  t.bigint :canvas_id, null: false
         | 
| 13 13 | 
             
                  t.string :role_name
         | 
| 14 | 
            -
                  t.bigint : | 
| 15 | 
            -
                  t. | 
| 16 | 
            -
                  t.bigint :canvas_user_id | 
| 17 | 
            -
                  t.string :workflow_state | 
| 14 | 
            +
                  t.bigint :canvas_account_id
         | 
| 15 | 
            +
                  t.bigint :canvas_role_id
         | 
| 16 | 
            +
                  t.bigint :canvas_user_id
         | 
| 17 | 
            +
                  t.string :workflow_state
         | 
| 18 18 |  | 
| 19 19 | 
             
                  t.timestamps
         | 
| 20 20 | 
             
                end
         | 
| 21 21 | 
             
                add_index :admins, :canvas_id, unique: true
         | 
| 22 | 
            +
                add_index :admins, :canvas_role_id
         | 
| 23 | 
            +
                add_index :admins, :canvas_user_id
         | 
| 24 | 
            +
                add_index :admins, :canvas_account_id
         | 
| 22 25 | 
             
              end
         | 
| 23 26 | 
             
            end
         |