class Mumuki::Classroom::App

Constants

MASSIVE_BATCH_LIMIT

Public Instance Methods

add_failed_tags(report_json, exercises) click to toggle source
# File lib/mumuki/classroom/sinatra/courses.rb, line 38
def add_failed_tags(report_json, exercises)
  report_json.each do |student|
    items_to_review = Mumuki::Classroom::Assignment.items_to_review(student_assignment_query(student), exercises)
    student['items_to_review'] = items_to_review.join ', '
  end
end
add_massive_response_field(field, list, message, hash) click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 124
def add_massive_response_field(field, list, message, hash)
  unless list.empty?
    hash["#{field}_reason".to_sym] = message
    hash["#{field}_count".to_sym] = list.size
    hash[field.to_sym] = list
  end
end
allowed_courses() click to toggle source
# File lib/mumuki/classroom/sinatra/courses.rb, line 3
def allowed_courses
  {courses: Course.allowed_for(current_user).as_json}
end
as_guide_progress_response(guide_progress) click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 197
def as_guide_progress_response(guide_progress)
  {
    student: guide_progress.student.uid,
    guide: guide_progress.slug,
    progress: guide_progress.as_json.except(:student, :guide)
  }
end
assignment_query() click to toggle source
# File lib/mumuki/classroom/sinatra/messages.rb, line 16
def assignment_query
  with_organization_and_course 'exercise.eid': json_body[:exercise_id], 'student.uid': json_body[:uid], 'guide.slug': json_body[:guide_slug]
end
authenticate!() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 21
def authenticate!
  halt 401 unless current_user?
end
authorization_slug() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 47
def authorization_slug
  slug
end
chapter_as_json_opts() click to toggle source
# File lib/mumuki/classroom/sinatra/guides.rb, line 44
def chapter_as_json_opts
  {except: except_fields, include: {lessons: guide_container_as_json_opts}, methods: :name}
end
chapter_needed_fields(chapters) click to toggle source
# File lib/mumuki/classroom/sinatra/guides.rb, line 66
def chapter_needed_fields(chapters)
  chapters.as_json(chapter_as_json_opts).tap do |chs|
    chs.each do |chapter|
      with_guide_progress_count(chapter['lessons'])
    end
  end
end
collection_for(role) click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 113
def collection_for(role)
  "Mumuki::Classroom::#{role.to_s.titleize}".constantize
end
course() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 65
def course
  params[:course]
end
course_slug() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 93
def course_slug
  @course_slug ||= Mumukit::Auth::Slug.join_s(*route_slug_parts)
end
create_course_member!(role) click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 117
def create_course_member!(role)
  member_collection = collection_for role

  member_collection.normalized_attributes_from_json(json_body).tap do |member_json|
    ensure_member_not_exists! member_json, member_collection
    member = member_collection.create!(with_organization_and_course member_json)
    upsert_user! role, member.as_user
  end
end
create_members!(role, &block) click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 144
def create_members!(role, &block)
  members_collection = collection_for role
  massive_members = massive_members_for role
  existing_members = existing_members_in_course(members_collection, massive_members)
  existing_members_uids = existing_members.map { |it| it[:uid] }
  processed_members = massive_members.reject { |it| existing_members_uids.include? it[:uid] }.uniq { |it| it[:uid]}
  members_collection.collection.insert_many(processed_members.map { |member| with_organization_and_course member })
  upsert_users! role, processed_members, &block
  massive_response(processed_members, unprocessed_members_for(role), existing_members,
                   "#{role.to_s.pluralize.titleize} already belong to current course", status: :created)
end
csv_projection_for(projection) click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 182
def csv_projection_for(projection)
  projection.transform_values do |val|
    next val if val == 0
    {'$ifNull': [val, nil]}
  end
end
csv_with_headers(csv, projection) click to toggle source
# File lib/mumuki/classroom/sinatra/courses.rb, line 33
def csv_with_headers(csv, projection)
  headers = projection.symbolize_keys.except(:_id).keys.join(',')
  "#{headers}\n#{csv}"
end
current_course() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 139
def current_course
  @current_course ||= Course.locate!(course_slug)
end
current_organization() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 135
def current_organization
  @current_organization ||= Organization.locate!(organization).switch!
end
ensure_course_existence!() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 105
def ensure_course_existence!
  Course.locate! course_slug
end
ensure_course_exists!() click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 181
def ensure_course_exists!
  Course.locate!(course_slug)
end
ensure_member_not_exists!(member_json, member_collection) click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 109
def ensure_member_not_exists!(member_json, member_collection)
  member_collection.ensure_not_exists! with_organization_and_course uid: member_json[:uid]
end
ensure_organization_existence!() click to toggle source
# File lib/mumuki/classroom/sinatra/courses.rb, line 51
def ensure_organization_existence!
  Organization.locate! organization
end
ensure_organization_exists!() click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 185
def ensure_organization_exists!
  Organization.locate!(organization).tap &:switch!
end
exam_as_json_response(exam) click to toggle source
# File lib/mumuki/classroom/sinatra/exams.rb, line 21
def exam_as_json_response(exam)
  exam.as_json
      .merge(eid: exam.classroom_id, name: exam.guide.name, language: exam.guide.language.name,
             slug: exam.guide.slug, uids: exam.users.map(&:uid), course: exam.course.slug,
             organization: exam.organization.name, passing_criterion: exam.passing_criterion.as_json)
      .except(:classroom_id, :guide_id, :course_id, :organization_id,
              :passing_criterion_type, :passing_criterion_value)
end
exam_body() click to toggle source
# File lib/mumuki/classroom/sinatra/exams.rb, line 17
def exam_body
  exam_from_classroom_json with_current_organization_and_course(json_body)
end
exam_from_classroom_json(json) click to toggle source
# File lib/mumuki/classroom/sinatra/exams.rb, line 11
def exam_from_classroom_json(json)
  exam = json.with_indifferent_access
  Exam.adapt_json_values exam
  Exam.whitelist_attributes exam
end
exam_id() click to toggle source
# File lib/mumuki/classroom/sinatra/exams.rb, line 3
def exam_id
  params[:exam_id]
end
exam_query() click to toggle source
# File lib/mumuki/classroom/sinatra/exams.rb, line 7
def exam_query
  {classroom_id: exam_id}
end
except_fields() click to toggle source
# File lib/mumuki/classroom/sinatra/guides.rb, line 32
def except_fields
  [:id, :created_at, :updated_at, :language_id, :guide_id, :topic_id, :book_id]
end
exercise_id() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 73
def exercise_id
  params[:exercise_id].to_i
end
exercise_student_progress_query() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 77
def exercise_student_progress_query
  {'guide.slug': repo_slug, 'student.uid': uid}
end
existing_members_in_course(col, massive_members) click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 156
def existing_members_in_course(col, massive_members)
  col.where(with_organization_and_course)
    .in(uid: massive_members.map { |it| it[:uid] })
    .map { |it| col.normalized_attributes_from_json(it) }
end
find_or_create_suggestion(assignment) click to toggle source
# File lib/mumuki/classroom/sinatra/messages.rb, line 20
def find_or_create_suggestion(assignment)
  suggestion_id ? Mumuki::Classroom::Suggestion.find(suggestion_id) : Mumuki::Classroom::Suggestion.create_from(message, assignment)
end
follower_query() click to toggle source
# File lib/mumuki/classroom/sinatra/followers.rb, line 3
def follower_query
  with_organization_and_course email: current_user.uid
end
followers_criteria(collection) click to toggle source
# File lib/mumuki/classroom/sinatra/searching.rb, line 22
def followers_criteria(collection)
  uids = Mumuki::Classroom::Follower.find_by(with_organization_and_course email: current_user_uid)&.uids.to_a
  {collection.uid_field.to_sym => {'$in': uids}}
end
get_current_guides() click to toggle source

TODO: Use JSON Builder

# File lib/mumuki/classroom/sinatra/guides.rb, line 21
def get_current_guides
  authorize! :teacher
  ensure_organization_exists!
  ensure_course_exists!
  {
    chapters: chapter_needed_fields(current_organization.book.chapters.includes(topic: {lessons: {guide: :language}})),
    complements: guide_container_needed_fields(current_organization.book.complements.includes(guide: :language)),
    exams: guide_container_needed_fields(current_organization.exams.where(course: current_course).includes(guide: :language))
  }
end
group_report(matcher, projection) click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 210
def group_report(matcher, projection)
  projection = csv_projection_for projection
  aggregation = Mumuki::Classroom::Student.where(matcher).project(projection)
  pipeline_with_sort_criterion = aggregation.pipeline << {'$sort': {passed_count: -1, passed_with_warnings_count: -1, failed_count: -1, last_name: 1, first_name: 1}}
  json = Mumuki::Classroom::Student.collection.aggregate(pipeline_with_sort_criterion).as_json
  content_type 'application/csv'
  csv_with_headers(Mumuki::Classroom::Reports::Formats.format_report('csv', json), projection)
end
group_report_projection() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 189
def group_report_projection
  {
    '_id': 0,
    'last_name': '$last_name',
    'first_name': '$first_name',
    'email': '$email',
    'personal_id': '$personal_id',
    'detached': {'$eq': ['$detached', true]},
    'created_at': '$created_at',
    'last_submission_date': '$last_assignment.submission.created_at',
    'passed_count': '$stats.passed',
    'passed_with_warnings_count': '$stats.passed_with_warnings',
    'failed_count': '$stats.failed',
    'last_lesson_type': '$last_assignment.guide.parent.type',
    'last_lesson_name': '$last_assignment.guide.parent.name',
    'last_exercise_number': '$last_assignment.exercise.number',
    'last_exercise_name': '$last_assignment.exercise.name',
    'last_chapter': '$last_assignment.guide.parent.chapter.name',
  }
end
guide_as_json_opts() click to toggle source
# File lib/mumuki/classroom/sinatra/guides.rb, line 36
def guide_as_json_opts
  {except: except_fields, include: {language: {only: [:name, :devicon]}}}
end
guide_container_as_json_opts() click to toggle source
# File lib/mumuki/classroom/sinatra/guides.rb, line 40
def guide_container_as_json_opts
  {except: except_fields, include: {guide: guide_as_json_opts}}
end
guide_container_needed_fields(containers) click to toggle source
# File lib/mumuki/classroom/sinatra/guides.rb, line 62
def guide_container_needed_fields(containers)
  with_guide_progress_count containers.as_json(guide_container_as_json_opts)
end
guide_needed_fields(guide) click to toggle source
# File lib/mumuki/classroom/sinatra/guides.rb, line 48
def guide_needed_fields(guide)
  guide.as_json guide_as_json_opts
end
guide_progress_at_page(per_page) click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 189
def guide_progress_at_page(per_page)
  Mumuki::Classroom::GuideProgress
    .where(with_organization_and_course)
    .sort('organization': :asc, 'course': :asc, 'student.uid': :asc)
    .limit(per_page)
    .skip(page * per_page)
end
guide_progress_query() click to toggle source
# File lib/mumuki/classroom/sinatra/courses.rb, line 7
def guide_progress_query
  with_detached_and_search with_organization_and_course('guide.slug': repo_slug), Mumuki::Classroom::GuideProgress
end
guide_progress_report(matcher, projection) click to toggle source
# File lib/mumuki/classroom/sinatra/courses.rb, line 63
def guide_progress_report(matcher, projection)
  projection = csv_projection_for projection
  aggregation = Mumuki::Classroom::GuideProgress.where(matcher).project(projection)
  pipeline_with_sort_criterion = aggregation.pipeline << {'$sort': {email: 1, passed_count: -1, passed_with_warnings_count: -1, failed_count: -1, last_name: 1, first_name: 1}}
  json = Mumuki::Classroom::GuideProgress.collection.aggregate(pipeline_with_sort_criterion).as_json
  content_type 'application/csv'
  csv_with_headers(Mumuki::Classroom::Reports::Formats.format_report('csv', json), projection)
end
guide_progress_report_projection() click to toggle source
# File lib/mumuki/classroom/sinatra/courses.rb, line 72
def guide_progress_report_projection
  {
      '_id': 0,
      'last_name': '$student.last_name',
      'first_name': '$student.first_name',
      'email': '$student.email',
      'last_submission': '$last_assignment.submission.created_at',
      'detached': {'$eq': ['$detached', true]},
      'guide_slug': '$guide.slug',
      'passed_count': '$stats.passed',
      'passed_with_warnings_count': '$stats.passed_with_warnings',
      'failed_count': '$stats.failed'
  }
end
guide_report_projection() click to toggle source
# File lib/mumuki/classroom/sinatra/courses.rb, line 20
def guide_report_projection
  {
    '_id': 0,
    'last_name': '$student.last_name',
    'first_name': '$student.first_name',
    'email': '$student.email',
    'passed_count': '$stats.passed',
    'passed_with_warnings_count': '$stats.passed_with_warnings',
    'failed_count': '$stats.failed',
    'items_to_review': ''
  }
end
json_body() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 25
def json_body
  @json_body ||= JSON.parse(request.body.read).with_indifferent_access rescue nil
end
list_students(matcher) click to toggle source
# File lib/mumuki/classroom/sinatra/students.rb, line 9
def list_students(matcher)
  authorize! :teacher
  count, students = Sorting.aggregate(Mumuki::Classroom::Student, with_detached_and_search(matcher, Mumuki::Classroom::Student), paginated_params, query_params)
  {page: page + 1, total: count, students: students}
end
list_teachers(matcher) click to toggle source
# File lib/mumuki/classroom/sinatra/teachers.rb, line 4
def list_teachers(matcher)
  authorize! :headmaster
  {teachers: Mumuki::Classroom::Teacher.where(matcher).as_json}
end
manual_evaluation_assignment_query() click to toggle source
# File lib/mumuki/classroom/sinatra/manual_evaluation.rb, line 3
def manual_evaluation_assignment_query
  with_organization_and_course 'exercise.eid': params[:exercise_id].to_i, 'student.uid': params[:uid], 'guide.slug': repo_slug
end
massive_members_for(role) click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 136
def massive_members_for(role)
  send "massive_#{role.to_s.pluralize}"
end
massive_response(processed, unprocessed, errored, errored_msg, hash = {}) click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 110
def massive_response(processed, unprocessed, errored, errored_msg, hash = {})
  add_massive_response_field(:errored_members, errored, errored_msg, hash)
  add_massive_response_field(:unprocessed, unprocessed, unprocessed_msg, hash)
  hash.merge(processed_count: processed.size, processed: processed)
end
massive_students() click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 85
def massive_students
  @massive_students ||= with_massive_batch_limit students
end
massive_teachers() click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 89
def massive_teachers
  @massive_teachers ||= with_massive_batch_limit teachers
end
massive_uids() click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 69
def massive_uids
  with_massive_batch_limit uids
end
members_for(role) click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 132
def members_for(role)
  send role.to_s.pluralize
end
message() click to toggle source
# File lib/mumuki/classroom/sinatra/messages.rb, line 3
def message
  message = json_body[:message]
  message[:sender] = current_user.uid
  message
end
normalize_student!() click to toggle source
# File lib/mumuki/classroom/sinatra/students.rb, line 3
def normalize_student!
  json_body[:email] = json_body[:email]&.downcase
  json_body[:last_name] = json_body[:last_name]&.downcase&.titleize
  json_body[:first_name] = json_body[:first_name]&.downcase&.titleize
end
normalized_exercises() click to toggle source
# File lib/mumuki/classroom/sinatra/courses.rb, line 45
def normalized_exercises
  json_body[:exercises].map do |it|
    {language: json_body[:language]}.merge(it.symbolize_keys)
  end
end
order_by() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 178
def order_by
  params[:order_by] || :asc
end
organization() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 85
def organization
  tenant
end
organization_json() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 131
def organization_json
  @organization_json ||= current_organization.as_json
end
page() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 150
def page
  (params[:page] || 1).to_i - 1
end
paginated_params() click to toggle source
# File lib/mumuki/classroom/sinatra/pagination.rb, line 3
def paginated_params
  {
    page: page,
    sort_by: sort_by,
    order_by: order_by,
    per_page: per_page,
    with_detached: with_detached
  }
end
per_page() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 154
def per_page
  (params[:per_page] || 30).to_i
end
permissions() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 61
def permissions
  current_user.permissions
end
query() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 166
def query
  params[:q] || ''
end
query_criteria() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 170
def query_criteria
  params[:query_criteria]
end
query_criteria_class_for(collection) click to toggle source
# File lib/mumuki/classroom/sinatra/searching.rb, line 10
def query_criteria_class_for(collection)
  Searching.filter_for(collection, query_params)
end
query_operand() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 174
def query_operand
  params[:query_operand]
end
query_params() click to toggle source
# File lib/mumuki/classroom/sinatra/searching.rb, line 14
def query_params
  {
    query_param: query,
    query_criteria: query_criteria,
    query_operand: query_operand
  }
end
render_threads(course) click to toggle source
# File lib/mumuki/classroom/sinatra/messages.rb, line 9
def render_threads(course)
  authorize! :student
  query = with_organization exercise_student_progress_query.merge(course: course, 'exercise.eid': exercise_id)
  threads = Mumuki::Classroom::Assignment.find_by!(query).threads(params[:language])
  erb :'threads.html', locals: {threads: threads, user: current_user}
end
repo_slug() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 97
def repo_slug
  @repo_slug ||= Mumukit::Auth::Slug.join_s(params[:organization], params[:repository])
end
route_slug_parts() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 89
def route_slug_parts
  [tenant, course].compact
end
set_locale!() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 127
def set_locale!
  I18n.locale = current_organization.locale
end
slug() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 51
def slug
  if route_slug_parts.present?
    Mumukit::Auth::Slug.join(*route_slug_parts)
  elsif json_body
    Mumukit::Auth::Slug.parse(json_body['slug'])
  else
    raise Mumukit::Auth::InvalidSlugFormatError.new('Slug not available')
  end
end
sort_by() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 158
def sort_by
  params[:sort_by] || :name
end
student_assignment_query(student) click to toggle source
# File lib/mumuki/classroom/sinatra/courses.rb, line 15
def student_assignment_query(student)
  student_info = student.slice('first_name', 'last_name', 'email').transform_keys { |it| "student.#{it}" }
  student_query.merge(student_info)
end
student_query() click to toggle source
# File lib/mumuki/classroom/sinatra/courses.rb, line 11
def student_query
  with_organization_and_course('guide.slug': repo_slug)
end
students() click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 73
def students
  @students ||= json_body[:students].map do |it|
    Mumuki::Classroom::Student.normalized_attributes_from_json it
  end
end
students_does_not_belong_msg() click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 120
def students_does_not_belong_msg
  'Students does not belong to current course'
end
students_from(uids) click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 177
def students_from(uids)
  Mumuki::Classroom::Student.where(with_organization_and_course).in(uid: uids)
end
submission_id() click to toggle source
# File lib/mumuki/classroom/sinatra/messages.rb, line 24
def submission_id
  json_body[:submission_id]
end
suggestion_id() click to toggle source
# File lib/mumuki/classroom/sinatra/messages.rb, line 28
def suggestion_id
  json_body[:suggestion_id]
end
teachers() click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 79
def teachers
  @teachers ||= json_body[:teachers].map do |it|
    Mumuki::Classroom::Teacher.normalized_attributes_from_json it
  end
end
tenant() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 81
def tenant
  Mumukit::Platform.organization_name(request)
end
tenantized_json_body() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 101
def tenantized_json_body
  json_body.merge(tenant: tenant)
end
uid() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 69
def uid
  params[:uid]
end
uids() click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 65
def uids
  json_body[:uids]
end
unprocessed_members_for(role) click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 140
def unprocessed_members_for(role)
  members_for(role) - massive_members_for(role)
end
unprocessed_msg() click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 116
def unprocessed_msg
  "This endpoint process only first #{MASSIVE_BATCH_LIMIT} elements"
end
update_students!() { |processed| ... } click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 162
def update_students!
  processed = students_from(massive_uids).map(&:uid)
  yield processed if block_given?
  massive_response processed, (uids - massive_uids), (massive_uids - processed),
                   students_does_not_belong_msg, status: :updated
end
update_students_at_course!(method, action, students_uids) click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 169
def update_students_at_course!(method, action, students_uids)
  Mumuki::Classroom::Student.send "#{method}_all_by!", students_uids, with_organization_and_course
  User.where(uid: students_uids).each do |user|
    user.send "#{action}_permission!", :student, course_slug
    user.save!
  end
end
update_user_permissions!(uid, method, *slugs) { |user| ... } click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 143
def update_user_permissions!(uid, method, *slugs)
  user = User.locate!(uid)
  user.send("#{method}_permission!", :student, *slugs)
  yield user if block_given?
  user.save!
end
upsert_user!(role, member) { |user| ... } click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 97
def upsert_user!(role, member)
  user = User.find_or_initialize_by(uid: member[:uid])
  user.assign_attributes user_from_member_json(member)
  user.add_permission! role, course_slug
  user.verify_name!
  yield user if block_given?
end
upsert_users!(role, members, &block) click to toggle source

FIXME: This method now doesn't perform a bulk update as PG doesn't support it

# File lib/mumuki/classroom/sinatra/massive.rb, line 106
def upsert_users!(role, members, &block)
  members.each { |it| upsert_user! role, it, &block }
end
user_from_member_json(member_json) click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 93
def user_from_member_json(member_json)
  User.whitelist_attributes member_json
end
validate_usage!(guide) click to toggle source

TODO: Extract to domain

# File lib/mumuki/classroom/sinatra/guides.rb, line 75
def validate_usage!(guide)
  raise ActiveRecord::RecordNotFound, "Couldn't find #{Guide.name} with #{Guide.sync_key_id_field}: #{guide.slug}" unless guide.usage_in_organization
end
with_current_organization(hash = {}) click to toggle source

FIXME only provisional

# File lib/mumuki/classroom/sinatra.rb, line 34
def with_current_organization(hash = {})
  {organization: current_organization}.merge hash.except(:organization)
end
with_current_organization_and_course(hash = {}) click to toggle source

FIXME only provisional

# File lib/mumuki/classroom/sinatra.rb, line 39
def with_current_organization_and_course(hash = {})
  with_current_organization.merge(course: current_course).merge hash.except(:organization, :course)
end
with_detached() click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 162
def with_detached
  params[:with_detached].boolean_value
end
with_guide_progress_count(containers) click to toggle source
# File lib/mumuki/classroom/sinatra/guides.rb, line 52
def with_guide_progress_count(containers)
  containers.each do |container|
    container.tap do |it|
      it['guide']['students_count'] = Mumuki::Classroom::GuideProgress
                                        .where(with_organization_and_course 'guide.slug': it['guide']['slug'])
                                        .count
    end
  end
end
with_last_invitation(course) click to toggle source

TODO: Use JSON Builder

# File lib/mumuki/classroom/sinatra/courses.rb, line 56
def with_last_invitation(course)
  course.as_json(except: [:created_at, :updated_at, :id], methods: [:current_invitation]).tap do |it|
    it['invitation'] = it['current_invitation']
    it.except! 'current_invitation'
  end
end
with_massive_batch_limit(elements) click to toggle source
# File lib/mumuki/classroom/sinatra/massive.rb, line 61
def with_massive_batch_limit(elements)
  elements.to_a.take MASSIVE_BATCH_LIMIT
end
with_organization(hash = {}) click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 29
def with_organization(hash = {})
  {organization: organization}.merge hash
end
with_organization_and_course(hash = {}) click to toggle source
# File lib/mumuki/classroom/sinatra.rb, line 43
def with_organization_and_course(hash = {})
  with_organization.merge(course: course_slug).merge hash
end