Implement Badge & BadgeAchievement model (#273)
* Create migration for Badge & BadgeAchievement * Create Badge model with spec & BadgeUploader * Create BadgeAchievement with spec * Add badges & badge_achievements assoc to User * Fix typo * Clean up BadgeUploader * Remove storage config & Fix lint * Add allow-duplicate-badge spec
This commit is contained in:
parent
524052234a
commit
1663e7e2c8
12 changed files with 141 additions and 15 deletions
17
app/models/badge.rb
Normal file
17
app/models/badge.rb
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
class Badge < ApplicationRecord
|
||||
mount_uploader :badge_image, BadgeUploader
|
||||
|
||||
has_many :badge_achievements
|
||||
has_many :users, through: :badge_achievements
|
||||
|
||||
validates :title, presence: true, uniqueness: true
|
||||
validates :description, presence: true
|
||||
|
||||
before_validation :generate_slug
|
||||
|
||||
private
|
||||
|
||||
def generate_slug
|
||||
self.slug = title.to_s.downcase.tr(" ", "-").gsub(/[^\w-]/, "").tr("_", "")
|
||||
end
|
||||
end
|
||||
5
app/models/badge_achievement.rb
Normal file
5
app/models/badge_achievement.rb
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
class BadgeAchievement < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :badge
|
||||
belongs_to :rewarder, class_name: "User"
|
||||
end
|
||||
|
|
@ -13,6 +13,8 @@ class User < ApplicationRecord
|
|||
|
||||
belongs_to :organization, optional: true
|
||||
has_many :articles
|
||||
has_many :badge_achievements
|
||||
has_many :badges, through: :badge_achievements
|
||||
has_many :collections
|
||||
has_many :comments
|
||||
has_many :email_messages, class_name: "Ahoy::Message"
|
||||
|
|
|
|||
11
app/uploaders/badge_uploader.rb
Normal file
11
app/uploaders/badge_uploader.rb
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
class BadgeUploader < CarrierWave::Uploader::Base
|
||||
include CarrierWave::BombShelter
|
||||
|
||||
def store_dir
|
||||
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
||||
end
|
||||
|
||||
def extension_whitelist
|
||||
%w(jpg jpeg gif png)
|
||||
end
|
||||
end
|
||||
|
|
@ -1,20 +1,19 @@
|
|||
require 'carrierwave/storage/abstract'
|
||||
require 'carrierwave/storage/file'
|
||||
require 'carrierwave/storage/fog'
|
||||
require "carrierwave/storage/abstract"
|
||||
require "carrierwave/storage/file"
|
||||
require "carrierwave/storage/fog"
|
||||
|
||||
CarrierWave.configure do |config|
|
||||
|
||||
if Rails.env.development? || Rails.env.test?
|
||||
config.storage = :file
|
||||
else
|
||||
# config.fog_provider = 'fog-aws'
|
||||
config.storage = :fog
|
||||
config.fog_credentials = {
|
||||
:provider => 'AWS',
|
||||
:aws_access_key_id => ENV['AWS_ID'],
|
||||
:aws_secret_access_key => ENV['AWS_SECRET'],
|
||||
:region => 'us-east-1'
|
||||
provider: "AWS",
|
||||
aws_access_key_id: ENV["AWS_ID"],
|
||||
aws_secret_access_key: ENV["AWS_SECRET"],
|
||||
region: "us-east-1",
|
||||
}
|
||||
config.fog_directory = ENV['AWS_BUCKET_NAME']
|
||||
config.fog_directory = ENV["AWS_BUCKET_NAME"]
|
||||
end
|
||||
end
|
||||
|
|
|
|||
14
db/migrate/20180502152520_create_badges.rb
Normal file
14
db/migrate/20180502152520_create_badges.rb
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
class CreateBadges < ActiveRecord::Migration[5.1]
|
||||
def change
|
||||
create_table :badges do |t|
|
||||
t.string :title, null: false
|
||||
t.string :slug, null: false
|
||||
t.string :description, null: false
|
||||
t.string :badge_image
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :badges, :title, unique: true
|
||||
end
|
||||
end
|
||||
13
db/migrate/20180502152621_create_badge_achievements.rb
Normal file
13
db/migrate/20180502152621_create_badge_achievements.rb
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
class CreateBadgeAchievements < ActiveRecord::Migration[5.1]
|
||||
def change
|
||||
create_table :badge_achievements do |t|
|
||||
t.references :user, foreign_key: true, null: false
|
||||
t.integer :rewarder_id
|
||||
t.references :badge, foreign_key: true, null: false
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :badge_achievements, [:user_id, :badge_id]
|
||||
end
|
||||
end
|
||||
23
db/schema.rb
23
db/schema.rb
|
|
@ -116,6 +116,27 @@ ActiveRecord::Schema.define(version: 20180502174301) do
|
|||
t.index ["user_id"], name: "index_articles_on_user_id"
|
||||
end
|
||||
|
||||
create_table "badge_achievements", force: :cascade do |t|
|
||||
t.bigint "badge_id", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.integer "rewarder_id"
|
||||
t.datetime "updated_at", null: false
|
||||
t.bigint "user_id", null: false
|
||||
t.index ["badge_id"], name: "index_badge_achievements_on_badge_id"
|
||||
t.index ["user_id", "badge_id"], name: "index_badge_achievements_on_user_id_and_badge_id"
|
||||
t.index ["user_id"], name: "index_badge_achievements_on_user_id"
|
||||
end
|
||||
|
||||
create_table "badges", force: :cascade do |t|
|
||||
t.string "badge_image"
|
||||
t.datetime "created_at", null: false
|
||||
t.string "description", null: false
|
||||
t.string "slug", null: false
|
||||
t.string "title", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["title"], name: "index_badges_on_title", unique: true
|
||||
end
|
||||
|
||||
create_table "blocks", id: :serial, force: :cascade do |t|
|
||||
t.text "body_html"
|
||||
t.text "body_markdown"
|
||||
|
|
@ -652,6 +673,8 @@ ActiveRecord::Schema.define(version: 20180502174301) do
|
|||
t.index ["user_id", "role_id"], name: "index_users_roles_on_user_id_and_role_id"
|
||||
end
|
||||
|
||||
add_foreign_key "badge_achievements", "badges"
|
||||
add_foreign_key "badge_achievements", "users"
|
||||
add_foreign_key "messages", "chat_channels"
|
||||
add_foreign_key "messages", "users"
|
||||
end
|
||||
|
|
|
|||
6
spec/factories/badges.rb
Normal file
6
spec/factories/badges.rb
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
FactoryBot.define do
|
||||
factory :badge do
|
||||
title { Faker::Overwatch.quote }
|
||||
description { Faker::Lorem.sentence }
|
||||
end
|
||||
end
|
||||
21
spec/models/badge_achievement_spec.rb
Normal file
21
spec/models/badge_achievement_spec.rb
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe BadgeAchievement, type: :model do
|
||||
let(:user) { create(:user) }
|
||||
let(:badge) { create(:badge) }
|
||||
|
||||
describe "validations" do
|
||||
subject { BadgeAchievement.create(user_id: user.id, badge_id: badge.id) }
|
||||
|
||||
it { is_expected.to belong_to(:user) }
|
||||
it { is_expected.to belong_to(:badge) }
|
||||
it { is_expected.to belong_to(:rewarder).class_name("User") }
|
||||
end
|
||||
|
||||
it "allow duplicate badges" do
|
||||
BadgeAchievement.create(user_id: user.id, badge_id: badge.id, rewarder_id: create(:user).id)
|
||||
expect do
|
||||
BadgeAchievement.create!(user_id: user.id, badge_id: badge.id, rewarder_id: create(:user).id)
|
||||
end.not_to raise_error
|
||||
end
|
||||
end
|
||||
13
spec/models/badge_spec.rb
Normal file
13
spec/models/badge_spec.rb
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
require "rails_helper"
|
||||
|
||||
RSpec.describe Badge, type: :model do
|
||||
describe "validations" do
|
||||
subject { Badge.create(title: Faker::Overwatch.quote, description: Faker::Lorem.sentence) }
|
||||
|
||||
it { is_expected.to have_many(:users).through(:badge_achievements) }
|
||||
it { is_expected.to have_many(:badge_achievements) }
|
||||
it { is_expected.to validate_presence_of(:title) }
|
||||
it { is_expected.to validate_presence_of(:description) }
|
||||
it { is_expected.to validate_uniqueness_of(:title) }
|
||||
end
|
||||
end
|
||||
|
|
@ -9,15 +9,17 @@ RSpec.describe User, type: :model do
|
|||
let(:org) { create(:organization) }
|
||||
|
||||
it { is_expected.to have_many(:articles) }
|
||||
it { is_expected.to have_many(:reactions) }
|
||||
it { is_expected.to have_many(:comments) }
|
||||
it { is_expected.to have_many(:identities) }
|
||||
it { is_expected.to have_many(:badge_achievements) }
|
||||
it { is_expected.to have_many(:badges).through(:badge_achievements) }
|
||||
it { is_expected.to have_many(:collections) }
|
||||
it { is_expected.to have_many(:tweets) }
|
||||
it { is_expected.to have_many(:notifications) }
|
||||
it { is_expected.to have_many(:mentions) }
|
||||
it { is_expected.to have_many(:comments) }
|
||||
it { is_expected.to have_many(:email_messages).class_name("Ahoy::Message") }
|
||||
it { is_expected.to have_many(:identities) }
|
||||
it { is_expected.to have_many(:mentions) }
|
||||
it { is_expected.to have_many(:notes) }
|
||||
it { is_expected.to have_many(:notifications) }
|
||||
it { is_expected.to have_many(:reactions) }
|
||||
it { is_expected.to have_many(:tweets) }
|
||||
it { is_expected.to validate_uniqueness_of(:username).case_insensitive }
|
||||
it { is_expected.to validate_uniqueness_of(:github_username).allow_blank }
|
||||
it { is_expected.to validate_uniqueness_of(:twitter_username).allow_blank }
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue