canvas_sync 0.24.0 → 0.26.0.beta1
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 +4 -4
- data/lib/canvas_sync/concerns/ability_helper.rb +6 -2
- data/lib/canvas_sync/concerns/canvas_id_as_primary.rb +11 -0
- data/lib/canvas_sync/concerns/user/through_pseudonyms.rb +47 -0
- data/lib/canvas_sync/concerns/user_via_pseudonym.rb +141 -0
- data/lib/canvas_sync/generators/templates/migrations/create_accounts.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_admins.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_assignment_groups.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_assignment_overrides.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_assignments.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_content_migrations.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_context_module_items.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_context_modules.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_course_nicknames.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_course_progresses.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_courses.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_enrollments.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_grading_period_groups.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_grading_periods.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_group_memberships.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_groups.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_learning_outcome_results.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_learning_outcomes.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_pseudonyms.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_roles.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_rubric_assessments.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_rubric_associations.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_rubrics.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_scores.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_sections.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_submissions.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_terms.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_user_observers.rb +1 -1
- data/lib/canvas_sync/generators/templates/migrations/create_users.rb +1 -1
- data/lib/canvas_sync/generators/templates/models/course_nickname.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/course_progress.rb +1 -0
- data/lib/canvas_sync/generators/templates/models/pseudonym.rb +2 -0
- data/lib/canvas_sync/generators/templates/models/user.rb +2 -0
- data/lib/canvas_sync/generators/templates/models/user_observer.rb +2 -0
- data/lib/canvas_sync/importers/bulk_importer.rb +1 -1
- data/lib/canvas_sync/jobs/sync_admins_job.rb +2 -2
- data/lib/canvas_sync/jobs/sync_roles_job.rb +2 -2
- data/lib/canvas_sync/misc_helper.rb +1 -1
- data/lib/canvas_sync/version.rb +1 -1
- data/lib/canvas_sync.rb +6 -0
- data/spec/canvas_sync/processors/context_modules_processor_spec.rb +2 -2
- data/spec/canvas_sync/processors/provisioning_report_processor_spec.rb +0 -2
- data/spec/internal/app/models/course_nickname.rb +1 -0
- data/spec/internal/app/models/course_progress.rb +1 -0
- data/spec/internal/app/models/pseudonym.rb +2 -0
- data/spec/internal/app/models/user.rb +2 -0
- data/spec/internal/app/models/user_observer.rb +2 -0
- data/spec/internal/db/migrate/{20250912205136_create_users.rb → 20251029222307_create_users.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205137_create_pseudonyms.rb → 20251029222308_create_pseudonyms.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205138_create_courses.rb → 20251029222309_create_courses.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205139_create_groups.rb → 20251029222310_create_groups.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205140_create_group_memberships.rb → 20251029222311_create_group_memberships.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205141_create_accounts.rb → 20251029222312_create_accounts.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205142_create_terms.rb → 20251029222313_create_terms.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205143_create_enrollments.rb → 20251029222314_create_enrollments.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205144_create_sections.rb → 20251029222315_create_sections.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205145_create_assignments.rb → 20251029222316_create_assignments.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205146_create_submissions.rb → 20251029222317_create_submissions.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205147_create_roles.rb → 20251029222318_create_roles.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205148_create_admins.rb → 20251029222319_create_admins.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205149_create_assignment_groups.rb → 20251029222320_create_assignment_groups.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205150_create_context_modules.rb → 20251029222321_create_context_modules.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205151_create_context_module_items.rb → 20251029222322_create_context_module_items.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205153_create_grading_periods.rb → 20251029222324_create_grading_periods.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205154_create_grading_period_groups.rb → 20251029222325_create_grading_period_groups.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205155_create_content_migrations.rb → 20251029222326_create_content_migrations.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205156_create_learning_outcomes.rb → 20251029222327_create_learning_outcomes.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205157_create_learning_outcome_results.rb → 20251029222328_create_learning_outcome_results.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205159_create_rubrics.rb → 20251029222330_create_rubrics.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205160_create_rubric_associations.rb → 20251029222331_create_rubric_associations.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205161_create_rubric_assessments.rb → 20251029222332_create_rubric_assessments.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205163_create_assignment_overrides.rb → 20251029222334_create_assignment_overrides.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205164_create_scores.rb → 20251029222335_create_scores.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205152_create_user_observers.rb → 20251029223411_create_user_observers.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205158_create_course_nicknames.rb → 20251029224009_create_course_nicknames.rb} +1 -1
- data/spec/internal/db/migrate/{20250912205162_create_course_progresses.rb → 20251029224010_create_course_progresses.rb} +1 -1
- metadata +62 -59
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ce4d1927f18104be2a36720a8932671c3a0188a1e3a235f6929a23299a8d89c4
|
|
4
|
+
data.tar.gz: e8e7a15fde1156d9485026c3039e5bcbe2c4dec3c3491b61eb2f06cc1d0ea718
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2b4b60b41f8b249baaef413d1f44ba17d124ba6cff5960bb0d8b7db43c28f7a5213a04b91f19650c31efb5889f1674ccb84937d33a21270f39a28cbfe0efcee1
|
|
7
|
+
data.tar.gz: 0a5932d0dcf129bedd5ebad761d2df9d77793ecb9ea3dcdc905b39a676f2e7da5f68e1c0bbd89b7e564ebabc92d5ee59d3722f2c73c8f7306479e3dfa5c65ee2
|
|
@@ -73,8 +73,12 @@ module CanvasSync::Concerns
|
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
def canvas_super_user?
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
canvas_account_admin?(:root)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def canvas_account_admin?(account = launch_account)
|
|
80
|
+
panda_pal_session.cache([:canvas_account_admin?, account]) do
|
|
81
|
+
panda_pal_session.canvas_site_admin? || (panda_pal_session.canvas_account_role_labels(account) & ["AccountAdmin", "Account Admin"]).present?
|
|
78
82
|
end
|
|
79
83
|
end
|
|
80
84
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module CanvasSync::Concerns
|
|
2
|
+
module User
|
|
3
|
+
module ThroughPseudonyms
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
include CanvasSync::Record
|
|
6
|
+
|
|
7
|
+
CanvasSync::Record.define_feature self, default: true
|
|
8
|
+
|
|
9
|
+
class_methods do
|
|
10
|
+
def has_many_via_pseudonyms(rel_name, *args, using_sis_id: false, **kwargs)
|
|
11
|
+
kwargs[:class_name] ||= rel_name.to_s.classify
|
|
12
|
+
kwargs[:primary_key] ||= using_sis_id ? :sis_id : :canvas_id
|
|
13
|
+
|
|
14
|
+
# TODO Try and guess the foreign key?
|
|
15
|
+
# kwargs[:foreign_key] ||= using_sis_id ? :"#{rel_name}_sis_id" : :"#{rel_name}_pseudonym_canvas_id"
|
|
16
|
+
|
|
17
|
+
through_rel = using_sis_id ? :active_pseudonyms : :all_pseudonyms
|
|
18
|
+
|
|
19
|
+
pseudo_rel = :"_user_#{rel_name}_via_pseudonym"
|
|
20
|
+
Pseudonym.has_many(pseudo_rel, *args, **kwargs)
|
|
21
|
+
|
|
22
|
+
class_eval <<~RUBY
|
|
23
|
+
has_many(:#{rel_name}, through: :#{through_rel}, source: :#{pseudo_rel}, inverse_of: :student) do
|
|
24
|
+
def scope_for_create(...)
|
|
25
|
+
# @association.reflection.inverse_of
|
|
26
|
+
super.tap do |scope|
|
|
27
|
+
user = @association.owner
|
|
28
|
+
scope[:#{kwargs[:foreign_key]}] = user.load_pseudonym_for_relation!(any: #{!using_sis_id}).canvas_id
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
RUBY
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def load_pseudonym_for_relation!(any: false)
|
|
37
|
+
return @pseudonym_for_relation if defined?(@pseudonym_for_relation)
|
|
38
|
+
|
|
39
|
+
@pseudonym_for_relation = self.active_pseudonyms[0] || Pseudonym.find_by(user: self)
|
|
40
|
+
raise ActiveRecord::RecordNotFound, "No Pseudonym for User #{self.canvas_id}" unless @pseudonym_for_relation.present?
|
|
41
|
+
raise ActiveRecord::RecordNotFound, "No Active Pseudonym for User #{self.canvas_id}" unless @pseudonym_for_relation.workflow_state != "deleted" || any
|
|
42
|
+
|
|
43
|
+
@pseudonym_for_relation
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
module CanvasSync::Concerns
|
|
2
|
+
module UserViaPseudonym
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
module RelationHook
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
def where!(*args)
|
|
9
|
+
return super unless self.respond_to?(:users_via_pseudonym)
|
|
10
|
+
|
|
11
|
+
super.tap do |q|
|
|
12
|
+
args.select { |a| a.is_a?(Hash) }.each do |hash|
|
|
13
|
+
hash.each do |key, value|
|
|
14
|
+
next unless users_via_pseudonym.key?(key)
|
|
15
|
+
q.joins!(key).references!(Arel::Nodes::SqlLiteral.new(key.to_s))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
ActiveRecord::Relation.include(RelationHook)
|
|
23
|
+
|
|
24
|
+
class RefreshUserCachesJob < CanvasSync::Job
|
|
25
|
+
def perform
|
|
26
|
+
ActiveRecord::Base.subclasses.each do |model|
|
|
27
|
+
next unless model.respond_to?(:update_cached_user_ids!)
|
|
28
|
+
model.update_cached_user_ids!
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
included do
|
|
34
|
+
class_hash :users_via_pseudonym
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
class_methods do
|
|
38
|
+
def class_hash(key)
|
|
39
|
+
class_eval <<~RUBY
|
|
40
|
+
def self.#{key}
|
|
41
|
+
@#{key} ||= superclass.try(:#{key})&.dup || {}
|
|
42
|
+
end
|
|
43
|
+
RUBY
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def belongs_to_user(rel_name = :user, using_sis_id: false)
|
|
47
|
+
rel_name = rel_name.to_sym
|
|
48
|
+
|
|
49
|
+
pseudonym_rel_name = :"#{rel_name}_pseudonym"
|
|
50
|
+
if using_sis_id
|
|
51
|
+
belongs_to pseudonym_rel_name, -> { active }, primary_key: :sis_id, foreign_key: :"#{rel_name}_sis_id", class_name: "Pseudonym"
|
|
52
|
+
else
|
|
53
|
+
belongs_to pseudonym_rel_name, primary_key: :canvas_id, foreign_key: :"#{rel_name}_pseudonym_canvas_id", class_name: "Pseudonym"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
config = users_via_pseudonym[rel_name] = {
|
|
57
|
+
user_relation: rel_name,
|
|
58
|
+
pseudonym_relation: pseudonym_rel_name,
|
|
59
|
+
by_sis_id: using_sis_id,
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
cache_column = :"#{rel_name}_cached_user_canvas_id"
|
|
63
|
+
if column_names.include?(cache_column.to_s)
|
|
64
|
+
belongs_to(rel_name, primary_key: :canvas_id, foreign_key: cache_column, class_name: "User")
|
|
65
|
+
config[:user_cache_column] = cache_column
|
|
66
|
+
else
|
|
67
|
+
has_one(rel_name, through: pseudonym_rel_name, source: :user)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class_eval <<~RUBY
|
|
71
|
+
def #{rel_name}=(user)
|
|
72
|
+
return if self.#{rel_name} == user
|
|
73
|
+
association(:#{pseudonym_rel_name}).writer(user&.load_pseudonym_for_relation!(any: #{!using_sis_id}))
|
|
74
|
+
association(:#{rel_name}).writer(user) if association(:#{rel_name}).class <= ActiveRecord::Associations::BelongsToAssociation
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def #{pseudonym_rel_name}=(pseudonym)
|
|
78
|
+
return if self.#{pseudonym_rel_name} == pseudonym
|
|
79
|
+
association(:#{pseudonym_rel_name}).writer(pseudonym)
|
|
80
|
+
association(:#{rel_name}).writer(pseudonym&.user) if association(:#{rel_name}).class <= ActiveRecord::Associations::BelongsToAssociation
|
|
81
|
+
end
|
|
82
|
+
RUBY
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def update_cached_user_ids!
|
|
86
|
+
cached_configs = users_via_pseudonym.values.select { |c| c[:user_cache_column].present? }
|
|
87
|
+
return if cached_configs.empty?
|
|
88
|
+
|
|
89
|
+
query = all
|
|
90
|
+
|
|
91
|
+
# Add JOINs
|
|
92
|
+
query = cached_configs.reduce(query) do |clause, config|
|
|
93
|
+
clause.joins(config[:pseudonym_relation]).references([ config[:pseudonym_relation], config[:user_relation] ].map { |x| Arel.sql(x.to_s) })
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Add OR clauses for filtering to only records with stale caches
|
|
97
|
+
query = cached_configs.reduce(query.where("1=0")) do |clause, config|
|
|
98
|
+
where_clause = query
|
|
99
|
+
if (updated_after = CanvasSync::JobBatches::Batch.current_context[:updated_after]).present?
|
|
100
|
+
where_clause = where_clause.where("#{config[:pseudonym_relation]}.updated_at >= ?", updated_after)
|
|
101
|
+
end
|
|
102
|
+
where_clause = where_clause.where("#{table_name}.#{config[:user_cache_column]} IS DISTINCT FROM #{config[:pseudonym_relation]}.canvas_user_id")
|
|
103
|
+
clause.or(where_clause)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
query.in_batches do |batch|
|
|
107
|
+
batch = batch.to_a
|
|
108
|
+
|
|
109
|
+
cacheable_pseudonym_ids = cached_configs.map { |config| :"#{config[:pseudonym_relation]}_canvas_id" }.map { |col| batch.map(&col) }.flatten
|
|
110
|
+
user_id_map = Pseudonym.where(canvas_id: cacheable_pseudonym_ids).pluck(:canvas_id, :canvas_user_id).to_h
|
|
111
|
+
|
|
112
|
+
transaction do
|
|
113
|
+
where(primary_key => batch.map(&:id)).delete_all
|
|
114
|
+
|
|
115
|
+
cached_configs.each do |config|
|
|
116
|
+
batch.each do |record|
|
|
117
|
+
record[config[:user_cache_column]] = user_id_map[record[:"#{config[:pseudonym_relation]}_canvas_id"]]
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
import_results = import(
|
|
122
|
+
batch,
|
|
123
|
+
validate: false,
|
|
124
|
+
timestamps: false,
|
|
125
|
+
on_duplicate_key_ignore: true,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
failures = import_results.failed_instances
|
|
129
|
+
if failures.present?
|
|
130
|
+
handle_duplicated_cache_failures(failures)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def handle_user_cache_refresh_failures(records)
|
|
137
|
+
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
class CreateAssignmentOverrides < ActiveRecord::Migration[5.1]
|
|
2
2
|
def change
|
|
3
|
-
create_table :assignment_overrides do |t|
|
|
3
|
+
create_table :assignment_overrides, id: false do |t|
|
|
4
4
|
t.bigint :canvas_id, null: false
|
|
5
5
|
t.bigint :canvas_assignment_id
|
|
6
6
|
t.bigint :canvas_group_id
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
class CreateCourseNicknames < ActiveRecord::Migration[5.1]
|
|
4
4
|
def change
|
|
5
|
-
create_table :course_nicknames do |t|
|
|
5
|
+
create_table :course_nicknames, id: false do |t|
|
|
6
6
|
t.bigint :canvas_user_preference_value_id, null: true
|
|
7
7
|
t.integer :canvas_user_id
|
|
8
8
|
t.integer :canvas_course_id
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
class CreateCourseProgresses < ActiveRecord::Migration[5.1]
|
|
4
4
|
def change
|
|
5
|
-
create_table :course_progresses do |t|
|
|
5
|
+
create_table :course_progresses, id: false do |t|
|
|
6
6
|
t.bigint :canvas_course_id, null: false
|
|
7
7
|
t.bigint :canvas_user_id, null: false
|
|
8
8
|
t.integer :requirement_count
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
class CreateGroupMemberships < ActiveRecord::Migration[5.1]
|
|
4
4
|
def change
|
|
5
|
-
create_table :group_memberships do |t|
|
|
5
|
+
create_table :group_memberships, id: false do |t|
|
|
6
6
|
t.bigint :canvas_id, null: false
|
|
7
7
|
t.bigint :canvas_user_id, null: false
|
|
8
8
|
t.bigint :canvas_group_id, null: false
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
class CreateLearningOutcomeResults < ActiveRecord::Migration[5.1]
|
|
4
4
|
def change
|
|
5
|
-
create_table :learning_outcome_results do |t|
|
|
5
|
+
create_table :learning_outcome_results, id: false do |t|
|
|
6
6
|
t.bigint :canvas_id, null: false
|
|
7
7
|
t.bigint :canvas_context_id
|
|
8
8
|
t.string :canvas_context_type
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
class CreateRubricAssociations < ActiveRecord::Migration[5.1]
|
|
4
4
|
def change
|
|
5
|
-
create_table :rubric_associations do |t|
|
|
5
|
+
create_table :rubric_associations, id: false do |t|
|
|
6
6
|
t.bigint :canvas_id, null: false
|
|
7
7
|
t.bigint :canvas_rubric_id
|
|
8
8
|
t.bigint :canvas_association_id
|
|
@@ -7,6 +7,7 @@ class CourseNickname < ApplicationRecord
|
|
|
7
7
|
include CanvasSync::Concerns::ApiSyncable
|
|
8
8
|
|
|
9
9
|
canvas_sync_features :defaults
|
|
10
|
+
self.primary_key = [:canvas_user_id, :canvas_course_id] unless column_names.include?("id")
|
|
10
11
|
|
|
11
12
|
belongs_to :user, primary_key: :canvas_id, foreign_key: :canvas_user_id, optional: true
|
|
12
13
|
belongs_to :course, primary_key: :canvas_id, foreign_key: :canvas_course_id, optional: true
|
|
@@ -6,6 +6,7 @@ class CourseProgress < ApplicationRecord
|
|
|
6
6
|
include CanvasSync::Concerns::ApiSyncable
|
|
7
7
|
|
|
8
8
|
canvas_sync_features :defaults
|
|
9
|
+
self.primary_key = [:canvas_user_id, :canvas_course_id] unless column_names.include?("id")
|
|
9
10
|
|
|
10
11
|
belongs_to :user, primary_key: :canvas_id, foreign_key: :canvas_user_id, optional: true
|
|
11
12
|
belongs_to :course, primary_key: :canvas_id, foreign_key: :canvas_course_id, optional: true
|
|
@@ -17,6 +17,8 @@ class User < ApplicationRecord
|
|
|
17
17
|
|
|
18
18
|
validates :canvas_id, uniqueness: true, presence: true
|
|
19
19
|
has_many :pseudonyms, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
|
20
|
+
has_many :active_pseudonyms, ->() { active }, primary_key: :canvas_id, foreign_key: :canvas_user_id, class_name: "Pseudonym"
|
|
21
|
+
has_many :all_pseudonyms, primary_key: :canvas_id, foreign_key: :canvas_user_id, class_name: "Pseudonym"
|
|
20
22
|
has_many :enrollments, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
|
21
23
|
has_many :admins, primary_key: :canvas_id, foreign_key: :canvas_user_id
|
|
22
24
|
has_many :admin_roles, through: :admins, source: :role
|
|
@@ -7,6 +7,8 @@ class UserObserver < ApplicationRecord
|
|
|
7
7
|
|
|
8
8
|
canvas_sync_features :defaults
|
|
9
9
|
|
|
10
|
+
self.primary_key = [:observing_user_id, :observed_user_id] unless column_names.include?("id")
|
|
11
|
+
|
|
10
12
|
validates :canvas_id, uniqueness: true, presence: true
|
|
11
13
|
|
|
12
14
|
belongs_to :observing_user, primary_key: :canvas_id, foreign_key: :observing_user_id, class_name: 'User', optional: true
|
|
@@ -150,7 +150,7 @@ module CanvasSync
|
|
|
150
150
|
}
|
|
151
151
|
global_updates.slice!(*klass.column_names.map(&:to_sym))
|
|
152
152
|
if global_updates.present? && result.ids.present?
|
|
153
|
-
klass.where(
|
|
153
|
+
klass.where(klass.primary_key => result.ids).update_all(global_updates)
|
|
154
154
|
end
|
|
155
155
|
end
|
|
156
156
|
|
|
@@ -12,10 +12,10 @@ module CanvasSync
|
|
|
12
12
|
api_client.account_admins(acc.canvas_id).all_pages_each do |admin_params|
|
|
13
13
|
admin_params[:account_id] = acc.canvas_id
|
|
14
14
|
admin = update_or_create_model(Admin, admin_params)
|
|
15
|
-
updated_admin_ids.push(admin.
|
|
15
|
+
updated_admin_ids.push(admin.canvas_id)
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
|
-
Admin.where.not(
|
|
18
|
+
Admin.where.not(canvas_id: updated_admin_ids).update_all(workflow_state: 'inactive')
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
end
|
|
@@ -14,10 +14,10 @@ module CanvasSync
|
|
|
14
14
|
end
|
|
15
15
|
api_client.list_roles(acc.canvas_id, api_params).all_pages_each do |role_params|
|
|
16
16
|
role = update_or_create_model(Role, role_params)
|
|
17
|
-
updated_role_ids.push(role.
|
|
17
|
+
updated_role_ids.push(role.canvas_id)
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
|
-
Role.where.not(
|
|
20
|
+
Role.where.not(canvas_id: updated_role_ids).update_all(workflow_state: 'inactive')
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
end
|
|
@@ -34,7 +34,7 @@ module CanvasSync
|
|
|
34
34
|
# TODO Support globalid
|
|
35
35
|
model_class = load_constant(job[:model])
|
|
36
36
|
find_by = job[:find_by]
|
|
37
|
-
target = find_by.is_a?(Hash) ? model_class.find_by(**find_by) : model_class.find_by(
|
|
37
|
+
target = find_by.is_a?(Hash) ? model_class.find_by(**find_by) : model_class.find_by(model_class.primary_key => find_by)
|
|
38
38
|
target.send(job[:method], *job_args, **job_kwargs)
|
|
39
39
|
elsif job[:class]
|
|
40
40
|
target = load_constant(job[:class])
|
data/lib/canvas_sync/version.rb
CHANGED
data/lib/canvas_sync.rb
CHANGED
|
@@ -177,6 +177,8 @@ module CanvasSync
|
|
|
177
177
|
term_scope = term_scope.to_s if term_scope
|
|
178
178
|
options = options.deep_symbolize_keys!
|
|
179
179
|
|
|
180
|
+
given_models = models.dup
|
|
181
|
+
|
|
180
182
|
model_job_map = {
|
|
181
183
|
terms: CanvasSync::Jobs::SyncTermsJob,
|
|
182
184
|
accounts: CanvasSync::Jobs::SyncAccountsJob,
|
|
@@ -255,6 +257,10 @@ module CanvasSync
|
|
|
255
257
|
# Wrap it all up
|
|
256
258
|
###############################
|
|
257
259
|
|
|
260
|
+
if given_models.include?('pseudonyms')
|
|
261
|
+
root_chain << Concerns::UserViaPseudonym::RefreshUserCachesJob
|
|
262
|
+
end
|
|
263
|
+
|
|
258
264
|
root_chain
|
|
259
265
|
end
|
|
260
266
|
|