Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Course::Group and Course::GroupUser #161

Merged
merged 4 commits into from
May 31, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/models/course.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Course < ActiveRecord::Base
has_many :announcements, inverse_of: :course, dependent: :destroy
has_many :achievements, inverse_of: :course, dependent: :destroy
has_many :levels, inverse_of: :course, dependent: :destroy
has_many :groups, inverse_of: :course, dependent: :destroy, class_name: Course::Group.name

delegate :staff, to: :course_users

Expand Down
19 changes: 19 additions & 0 deletions app/models/course/group.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class Course::Group < ActiveRecord::Base
stampable

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

has_many :users, through: :group_users...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

=_= Haven't noticed this when refactoring

after_initialize :set_defaults, if: :new_record?
before_validation :set_defaults, if: :new_record?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after_initialize and before_validate, and allow it to run twice. Sometimes not all the arguments are given at initialise.


belongs_to :course, inverse_of: :groups
has_many :group_users, inverse_of: :course_group, dependent: :destroy,
class_name: Course::GroupUser.name, foreign_key: :course_group_id
has_many :users, through: :group_users
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

empty name validation, no default owner?


private

# Set default values
def set_defaults
return unless creator && creator.courses.include?(course) && group_users.empty?
group_users.build(user: creator, role: :manager, creator: creator, updater: updater)
end
end
26 changes: 26 additions & 0 deletions app/models/course/group_user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class Course::GroupUser < ActiveRecord::Base
stampable

after_initialize :set_defaults, if: :new_record?

enum role: { normal: 0, manager: 1 }

validate :user_and_group_in_same_course

belongs_to :user, inverse_of: :course_group_users
belongs_to :course_group, class_name: Course::Group.name, inverse_of: :group_users

alias_method :group, :course_group

private

# Set default values
def set_defaults
self.role ||= :normal
end

def user_and_group_in_same_course #:nodoc:
return if user.courses.include?(group.course)
errors.add(:user, I18n.t('activerecord.errors.models.course_group_user.not_enrolled'))
end
end
3 changes: 3 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ class User < ActiveRecord::Base
has_many :instances, through: :instance_users
has_many :course_users, inverse_of: :user, dependent: :destroy
has_many :courses, through: :course_users
has_many :course_group_users, inverse_of: :user, dependent: :destroy,
class_name: Course::GroupUser.name
has_many :course_groups, through: :course_group_users, class_name: Course::Group.name

accepts_nested_attributes_for :emails

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
en:
activerecord:
errors:
models:
course_group_user:
not_enrolled: 'user must be enrolled in same course as group'
13 changes: 13 additions & 0 deletions db/migrate/20150513110737_create_course_groups.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class CreateCourseGroups < ActiveRecord::Migration
def change
create_table :course_groups do |t|
t.belongs_to :course, null: false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

course before the name.

t.string :name, null: false, default: ''

t.userstamps null: false, foreign_key: { references: :users }
t.timestamps null: false

t.index [:course_id, :name], unique: true
end
end
end
14 changes: 14 additions & 0 deletions db/migrate/20150513111716_create_course_group_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class CreateCourseGroupUsers < ActiveRecord::Migration
def change
create_table :course_group_users do |t|
t.belongs_to :course_group, null: false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

course group before user.

t.belongs_to :user, null: false
t.integer :role, null: false

t.userstamps null: false, foreign_key: { references: :users }
t.timestamps null: false

t.index [:user_id, :course_group_id], unique: true
end
end
end
37 changes: 29 additions & 8 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20150512015621) do
ActiveRecord::Schema.define(version: 20150513111716) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand Down Expand Up @@ -105,13 +105,6 @@
t.datetime "updated_at", null: false
end

create_table "course_levels", force: :cascade do |t|
t.integer "course_id", null: false, index: {name: "fk__course_levels_course_id"}, foreign_key: {references: "courses", name: "fk_course_levels_course_id", on_update: :no_action, on_delete: :no_action}
t.integer "experience_points_threshold", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "course_users", force: :cascade do |t|
t.integer "course_id", null: false, index: {name: "fk__course_users_course_id"}, foreign_key: {references: "courses", name: "fk_course_users_course_id", on_update: :no_action, on_delete: :no_action}
t.integer "user_id", null: false, index: {name: "fk__course_users_user_id"}, foreign_key: {references: "users", name: "fk_course_users_user_id", on_update: :no_action, on_delete: :no_action}
Expand Down Expand Up @@ -139,6 +132,27 @@
t.datetime "updated_at", null: false
end

create_table "course_groups", force: :cascade do |t|
t.integer "course_id", null: false, index: {name: "fk__course_groups_course_id"}, foreign_key: {references: "courses", name: "fk_course_groups_course_id", on_update: :no_action, on_delete: :no_action}
t.string "name", default: "", null: false
t.integer "creator_id", null: false, index: {name: "fk__course_groups_creator_id"}, foreign_key: {references: "users", name: "fk_course_groups_creator_id", on_update: :no_action, on_delete: :no_action}
t.integer "updater_id", null: false, index: {name: "fk__course_groups_updater_id"}, foreign_key: {references: "users", name: "fk_course_groups_updater_id", on_update: :no_action, on_delete: :no_action}
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "course_groups", ["course_id", "name"], name: "index_course_groups_on_course_id_and_name", unique: true

create_table "course_group_users", force: :cascade do |t|
t.integer "course_group_id", null: false, index: {name: "fk__course_group_users_course_group_id"}, foreign_key: {references: "course_groups", name: "fk_course_group_users_course_group_id", on_update: :no_action, on_delete: :no_action}
t.integer "user_id", null: false, index: {name: "fk__course_group_users_user_id"}, foreign_key: {references: "users", name: "fk_course_group_users_user_id", on_update: :no_action, on_delete: :no_action}
t.integer "role", null: false
t.integer "creator_id", null: false, index: {name: "fk__course_group_users_creator_id"}, foreign_key: {references: "users", name: "fk_course_group_users_creator_id", on_update: :no_action, on_delete: :no_action}
t.integer "updater_id", null: false, index: {name: "fk__course_group_users_updater_id"}, foreign_key: {references: "users", name: "fk_course_group_users_updater_id", on_update: :no_action, on_delete: :no_action}
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "course_group_users", ["user_id", "course_group_id"], name: "index_course_group_users_on_user_id_and_course_group_id", unique: true

create_table "course_lesson_plan_items", force: :cascade do |t|
t.integer "actable_id"
t.string "actable_type", index: {name: "index_course_lesson_plan_items_on_actable_type_and_actable_id", with: ["actable_id"], unique: true}
Expand All @@ -154,6 +168,13 @@
t.datetime "updated_at", null: false
end

create_table "course_levels", force: :cascade do |t|
t.integer "course_id", null: false, index: {name: "fk__course_levels_course_id"}, foreign_key: {references: "courses", name: "fk_course_levels_course_id", on_update: :no_action, on_delete: :no_action}
t.integer "experience_points_threshold", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "instance_announcements", force: :cascade do |t|
t.integer "instance_id", null: false, index: {name: "fk__instance_announcements_instance_id"}, foreign_key: {references: "instances", name: "fk_instance_announcements_instance_id", on_update: :no_action, on_delete: :no_action}
t.string "title", limit: 255, null: false
Expand Down
20 changes: 20 additions & 0 deletions spec/factories/course_group_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FactoryGirl.define do
factory :course_group_user, class: Course::GroupUser.name do
course_group
user
role :normal
creator
updater

after(:build) do |group_user|
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this can be cleaned up, I'm not sure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not

transient do
course_user = create(:course_user)
...
end

then create the course_group_user last?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this, but cannot make it work

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created course_user in after build now

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  factory :course_group_user, class: Course::GroupUser.name do
    role :normal
    course_group
    user
    creator
    updater

    after(:build) do |group_user|
      create(:course_user, course: group_user.course_group.course, user: group_user.user)
    end
  end

course = group_user.course_group.course
user = group_user.user
create(:course_user, course: course, user: user) unless user.courses.include?(course)
end

factory :course_group_student
factory :course_group_manager do
role :manager
end
end
end
8 changes: 8 additions & 0 deletions spec/factories/course_groups.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FactoryGirl.define do
factory :course_group, class: Course::Group.name do
course
sequence(:name) { |n| "Group #{n}" }
creator
updater
end
end
7 changes: 7 additions & 0 deletions spec/models/course/group_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'rails_helper'

RSpec.describe Course::Group, type: :model do
it { is_expected.to belong_to(:course).inverse_of(:groups) }
it { is_expected.to have_many(:group_users).inverse_of(:course_group).dependent(:destroy) }
it { is_expected.to have_many(:users).through(:group_users) }
end
16 changes: 16 additions & 0 deletions spec/models/course/group_user_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require 'rails_helper'

RSpec.describe Course::GroupUser, type: :model do
it { is_expected.to belong_to(:user).inverse_of(:course_group_users) }
it { is_expected.to belong_to(:course_group).inverse_of(:group_users) }

let!(:instance) { create(:instance) }
with_tenant(:instance) do
subject { build(:course_group_user) }

context 'when user is not enrolled in group\'s course' do
before { subject.user.course_users.delete_all }
it { is_expected.not_to be_valid }
end
end
end
1 change: 1 addition & 0 deletions spec/models/course_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
it { is_expected.to have_many(:users).through(:course_users) }
it { is_expected.to have_many(:announcements).inverse_of(:course).dependent(:destroy) }
it { is_expected.to have_many(:levels).inverse_of(:course).dependent(:destroy) }
it { is_expected.to have_many(:groups).inverse_of(:course).dependent(:destroy) }

it { is_expected.to validate_presence_of(:title) }

Expand Down
3 changes: 3 additions & 0 deletions spec/models/user_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
it { is_expected.to have_many(:instances).through(:instance_users) }
it { is_expected.to have_many(:course_users).inverse_of(:user).dependent(:destroy) }
it { is_expected.to have_many(:courses).through(:course_users) }
it { is_expected.to have_many(:course_group_users).inverse_of(:user).dependent(:destroy) }
it { is_expected.to have_many(:course_groups).through(:course_group_users) }


describe '#email' do
context 'when the user has no email addresses' do
Expand Down