The tenanted db is the account scope

This commit is contained in:
David Heinemeier Hansson
2025-04-12 20:06:34 +02:00
parent 19dbd5b325
commit 6bbf68a4f9
57 changed files with 123 additions and 297 deletions
@@ -1,10 +1,10 @@
class Accounts::JoinCodesController < ApplicationController
def show
render svg: RQRCode::QRCode.new(join_url(Current.account.join_code)).as_svg(viewbox: true, fill: :white, color: :black)
render svg: RQRCode::QRCode.new(join_url(Account.sole.join_code)).as_svg(viewbox: true, fill: :white, color: :black)
end
def update
Current.account.reset_join_code
redirect_to account_users_path
Account.sole.reset_join_code
redirect_to users_path
end
end
+4 -4
View File
@@ -3,22 +3,22 @@ class Accounts::UsersController < ApplicationController
before_action :ensure_permission_to_administer_user, only: %i[ update destroy ]
def index
@users = Current.account.users.active
@users = User.active
end
def update
@user.update(role_params)
redirect_to account_users_path
redirect_to users_path
end
def destroy
@user.deactivate
redirect_to account_users_path
redirect_to users_path
end
private
def set_user
@user = Current.account.users.active.find(params[:id])
@user = User.active.find(params[:id])
end
def ensure_permission_to_administer_user
+1 -1
View File
@@ -3,7 +3,7 @@ class Cards::StagingsController < ApplicationController
def create
if params[:stage_id].present?
@card.toggle_stage Current.account.stages.find(params[:stage_id])
@card.toggle_stage Stage.find(params[:stage_id])
else
@card.update!(stage: nil)
end
+1 -1
View File
@@ -2,7 +2,7 @@ class Cards::TaggingsController < ApplicationController
include CardScoped
def new
@tags = Current.account.tags.alphabetically
@tags = Tag.alphabetically
end
def create
@@ -11,6 +11,6 @@ class Collections::WorkflowsController < ApplicationController
private
def set_workflow
@workflow = Current.account.workflows.find(params.expect(collection: [ :workflow_id ]).require(:workflow_id))
@workflow = Workflow.find(params.expect(collection: [ :workflow_id ]).require(:workflow_id))
end
end
+3 -3
View File
@@ -2,11 +2,11 @@ class CollectionsController < ApplicationController
before_action :set_collection, except: %i[ new create ]
def new
@collection = Current.account.collections.build
@collection = Collection.new
end
def create
@collection = Current.account.collections.create! collection_params
@collection = Collection.create! collection_params
redirect_to cards_path(collection_ids: [ @collection ])
end
@@ -37,7 +37,7 @@ class CollectionsController < ApplicationController
end
def grantees
Current.account.users.active.where id: grantee_ids
User.active.where id: grantee_ids
end
def revokees
+1 -1
View File
@@ -29,7 +29,7 @@ module EventsTimeline
end
def user_events
Event.where(card: user_cards, creator: Current.account.users)
Event.where(card: user_cards)
end
def user_cards
+1 -1
View File
@@ -7,6 +7,6 @@ module WorkflowScoped
private
def set_workflow
@workflow = Current.account.workflows.find params[:workflow_id]
@workflow = Workflow.find(params[:workflow_id])
end
end
+2 -1
View File
@@ -5,7 +5,8 @@ class UploadsController < ApplicationController
before_action :set_attachment, only: :show
def create
@upload = Current.account.uploads_attachments.create! blob: create_blob!
# FIXME: Try to get upload attachments on root
@upload = Account.first.uploads_attachments.create! blob: create_blob!
end
def show
+1 -1
View File
@@ -24,7 +24,7 @@ class Users::AvatarsController < ApplicationController
end
def set_user
@user = Current.account.users.find(params[:user_id])
@user = User.find(params[:user_id])
end
def render_avatar_or_initials
+5 -5
View File
@@ -5,11 +5,11 @@ class UsersController < ApplicationController
before_action :set_account_from_join_code, only: %i[ new create ]
def new
@user = @account.users.build
@user = User.new
end
def create
user = @account.users.create!(user_params)
user = User.create!(user_params)
start_new_session_for user
redirect_to root_path
end
@@ -21,8 +21,8 @@ class UsersController < ApplicationController
end
def update
@user.update user_params
redirect_to user_path(@user)
@user.update! user_params
redirect_to @user
end
private
@@ -31,7 +31,7 @@ class UsersController < ApplicationController
end
def set_user
@user = Current.account.users.active.find(params[:id])
@user = User.active.find(params[:id])
end
def user_params
+5 -5
View File
@@ -2,15 +2,15 @@ class WorkflowsController < ApplicationController
before_action :set_workflow, only: %i[ show edit update destroy ]
def index
@workflows = Current.account.workflows
@workflows = Workflow.all
end
def new
@workflow = Current.account.workflows.new
@workflow = Workflow.new
end
def create
@workflow = Current.account.workflows.create! workflow_params
@workflow = Workflow.create! workflow_params
# FIXME: this should definitely change.
[ "Triage", "In progress", "On Hold", "Review" ].each { |name| @workflow.stages.create! name: name }
redirect_to workflows_path
@@ -34,10 +34,10 @@ class WorkflowsController < ApplicationController
private
def set_workflow
@workflow = Current.account.workflows.find params[:id]
@workflow = Workflow.find params[:id]
end
def workflow_params
params.expect workflow: [ :name ]
params.expect workflow: :name
end
end
+1 -17
View File
@@ -1,21 +1,5 @@
class Account < ApplicationRecord
include ClosureReasons, Joinable
has_many :collections, dependent: :destroy
has_many :cards, through: :collections
has_many :users, dependent: :destroy do
def system
find_or_create_system_user(proxy_association.owner)
end
end
has_many :comments, through: :users
has_many :workflows, dependent: :destroy
has_many :stages, through: :workflows, class_name: "Workflow::Stage"
has_many :tags, dependent: :destroy
include Joinable
has_many_attached :uploads
end
-29
View File
@@ -1,29 +0,0 @@
module Account::ClosureReasons
extend ActiveSupport::Concern
DEFAULT_LABELS = [
"Completed",
"Duplicate",
"Maybe later",
"Working as intended"
]
FALLBACK_LABEL = "Done"
included do
has_many :closure_reasons, dependent: :destroy, class_name: "Closure::Reason" do
def labels
pluck(:label).presence || [ FALLBACK_LABEL ]
end
end
after_create :create_default_closure_reasons
end
private
def create_default_closure_reasons
DEFAULT_LABELS.each do |label|
closure_reasons.create! label: label
end
end
end
+2 -2
View File
@@ -16,7 +16,7 @@ module Card::Closeable
class_methods do
def auto_close_all_due
due_to_be_closed.find_each do |card|
card.close(user: card.collection.account.users.system, reason: "Closed")
card.close(user: User.system, reason: "Closed")
end
end
end
@@ -41,7 +41,7 @@ module Card::Closeable
closure&.created_at
end
def close(user: Current.user, reason: Account::ClosureReasons::FALLBACK_LABEL)
def close(user: Current.user, reason: Closure::Reason::FALLBACK_LABEL)
unless closed?
transaction do
create_closure! user: user, reason: reason
+1 -1
View File
@@ -9,7 +9,7 @@ module Card::Taggable
end
def toggle_tag_with(title)
tag = collection.account.tags.find_or_create_by!(title: title)
tag = Tag.find_or_create_by!(title: title)
transaction do
if tagged_with?(tag)
+20 -1
View File
@@ -1,3 +1,22 @@
class Closure::Reason < ApplicationRecord
belongs_to :account
DEFAULT_LABELS = [
"Completed",
"Duplicate",
"Maybe later",
"Working as intended"
]
FALLBACK_LABEL = "Done"
class << self
def labels
pluck(:label).presence || [ FALLBACK_LABEL ]
end
def create_defaults
DEFAULT_LABELS.each do |label|
create! label: label
end
end
end
end
-1
View File
@@ -1,7 +1,6 @@
class Collection < ApplicationRecord
include Accessible, Broadcastable, Filterable
belongs_to :account
belongs_to :creator, class_name: "User", default: -> { Current.user }
belongs_to :workflow, optional: true
+1 -1
View File
@@ -34,6 +34,6 @@ module Collection::Accessible
private
def grant_access_to_everyone
accesses.grant_to(account.users) if all_access_previously_changed?(to: true)
accesses.grant_to(User.all) if all_access_previously_changed?(to: true)
end
end
+1 -1
View File
@@ -3,6 +3,6 @@ module Collection::Broadcastable
included do
broadcasts_refreshes
broadcasts_refreshes_to ->(collection) { [ collection.account, :collections ] }
broadcasts_refreshes_to ->(collection) { :collections }
end
end
-1
View File
@@ -2,5 +2,4 @@ class Current < ActiveSupport::CurrentAttributes
attribute :session
delegate :user, to: :session, allow_nil: true
delegate :account, to: :user, allow_nil: true
end
+3 -2
View File
@@ -1,6 +1,7 @@
class FirstRun
def self.create!(user_attributes)
account = Account.create!(name: "Fizzy")
account.users.member.create!(user_attributes)
Account.create!(name: "Fizzy")
User.member.create!(user_attributes)
Closure::Reason.create_defaults
end
end
-2
View File
@@ -1,8 +1,6 @@
class Tag < ApplicationRecord
include Filterable
belongs_to :account, default: -> { Current.account }, touch: true
has_many :taggings, dependent: :destroy
has_many :cards, through: :taggings
-2
View File
@@ -1,8 +1,6 @@
class User < ApplicationRecord
include Accessor, Assignee, Avatar, Role, Transferable
belongs_to :account
has_many :sessions, dependent: :destroy
has_secure_password validations: false
+1 -1
View File
@@ -11,6 +11,6 @@ module User::Accessor
private
def grant_access_to_collections
Access.insert_all account.collections.all_access.pluck(:id).collect { |collection_id| { collection_id: collection_id, user_id: id } }
Access.insert_all Collection.all_access.pluck(:id).collect { |collection_id| { collection_id: collection_id, user_id: id } }
end
end
+2 -4
View File
@@ -10,10 +10,8 @@ module User::Role
end
class_methods do
def find_or_create_system_user(account)
account.users.find_or_create_by!(role: :system) do |user|
user.name = "System"
end
def system
find_or_create_by!(role: :system) { it.name = "System" }
end
end
-1
View File
@@ -1,4 +1,3 @@
class Workflow < ApplicationRecord
belongs_to :account
has_many :stages, dependent: :delete_all
end
+1 -1
View File
@@ -1,5 +1,5 @@
<div class="flex flex-column align-center gap">
<% url = join_url(Current.account.join_code) %>
<% url = join_url(Account.sole.join_code) %>
<label class="flex flex-column gap full-width txt-align-center">
<strong id="invite_label" class="invite-label">Share to invite more people</strong>
+1 -1
View File
@@ -11,7 +11,7 @@
<%= icon_tag "caret-down" %>
</summary>
<div class="expander__content btn borderless">
<% Current.account.closure_reasons.labels.each do |label| %>
<% Closure::Reason.labels.each do |label| %>
<%= button_to card_closure_path(card, reason: label), class: "expander__item btn" do %>
<span class="overflow-ellipsis"><%= label %></span>
<% end %>
+1 -1
View File
@@ -75,7 +75,7 @@
<strong class="txt-large">Choose a workflow</strong>
<p class="margin-none">Use a workflow to track progress in this collection.</p>
<%= form_with model: @collection, url: collection_workflow_path(@collection), local: true, method: :patch, data: { controller: "form" } do |form| %>
<%= form.select :workflow_id, Current.account.workflows.map { |w| [w.name, w.id] }, { include_blank: "Choose…" }, class: "input input--select full-width", data: { action: "change->form#submit" } %>
<%= form.select :workflow_id, Workflow.all.map { |w| [w.name, w.id] }, { include_blank: "Choose…" }, class: "input input--select full-width", data: { action: "change->form#submit" } %>
<% end %>
<p><%= link_to "Manage workflows", workflows_path, class: "btn btn--plain txt-link" %></p>
</div>
+2 -2
View File
@@ -5,11 +5,11 @@
<div class="btn btn--circle btn--placeholder flex-item-justify-start"></div>
<div class="events__index-header flex-inline flex-column center gap-half margin-block-end-double txt-align-center">
<h2 class="txt-large txt-nowrap center"><%= Current.account.name %> / Latest activity</h2>
<h2 class="txt-large txt-nowrap center"><%= Account.sole.name %> / Latest activity</h2>
<%= render "events/filter" %>
</div>
<%= link_to account_users_path, class: "btn flex-item-justify-end" do %>
<%= link_to users_path, class: "btn flex-item-justify-end" do %>
<%= icon_tag "settings" %>
<span class="for-screen-reader">Account settings</span>
<% end %>
+1 -1
View File
@@ -35,7 +35,7 @@
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
</div>
<% Current.account.users.active.order(:name).each do |user| %>
<% User.active.order(:name).each do |user| %>
<div class="btn popup__item">
<%= form.check_box "assignee_ids[]", {
checked: filter.assignees.include?(user),
+1 -1
View File
@@ -3,5 +3,5 @@
<%= turbo_stream_from collection %>
<% end %>
<% else %>
<%= turbo_stream_from Current.account, :collections %>
<%= turbo_stream_from :collections %>
<% end %>
+1 -1
View File
@@ -37,7 +37,7 @@
<%= icon_tag "check", class: "checked flex-item-justify-end" %>
</div>
<% Current.account.users.active.without(Current.user).order(:name).each do |user| %>
<% User.active.without(Current.user).order(:name).each do |user| %>
<div class="btn popup__item">
<%= form.check_box :creator_ids, {
multiple: true,
+4 -4
View File
@@ -78,7 +78,7 @@
<% end %>
</menu>
<% if workflow = Current.account.workflows.first %>
<% if workflow = Workflow.first %>
<menu class="filter__menu">
<li class="filter__label"><strong>In Stage</strong></li>
<% workflow.stages.each do |stage| %>
@@ -93,7 +93,7 @@
</menu>
<% end %>
<% if (tags = Current.account.tags.order(:title)).any? %>
<% if (tags = Tag.all.order(:title)).any? %>
<div class="filter__menu" role="group" aria-label="Tagged">
<div class="filter__label"><strong>Tagged</strong></div>
@@ -133,7 +133,7 @@
</label>
</div>
<% Current.account.users.active.without(Current.user).order(:name).each do |user| %>
<% User.active.without(Current.user).order(:name).each do |user| %>
<div>
<label class="btn filter__button">
<%= check_box_tag "assignee_ids[]", user.id, filter.assignees.include?(user), class: "visually-hidden",
@@ -157,7 +157,7 @@
</label>
</div>
<% Current.account.users.active.without(Current.user).order(:name).each do |user| %>
<% User.active.without(Current.user).order(:name).each do |user| %>
<div>
<label class="btn filter__button">
<%= check_box_tag "creator_ids[]", user.id, filter.creators.include?(user), class: "visually-hidden" %>
+2 -3
View File
@@ -1,4 +1,4 @@
<% if Current.account.workflows.any? %>
<% if Workflow.any? %>
<div class="quick-filter position-relative" data-controller="dialog" data-action="keydown.esc->dialog#close click@document->dialog#closeOnClickOutside">
<button class="btn input input--select flex-inline txt-small" data-action="click->dialog#open:stop">
<span class="overflow-ellipsis">
@@ -20,8 +20,7 @@
<%= filter_hidden_field_tag key, value %>
<% end %>
<% workflow = Current.account.workflows.first %>
<% workflow.stages.each do |stage| %>
<% Workflow.first.stages.each do |stage| %>
<div class="btn popup__item">
<%= form.check_box :stage_ids, {
multiple: true,
+1 -1
View File
@@ -22,7 +22,7 @@
<span class="overflow-ellipsis">Clear all</span>
<% end %>
<% Current.account.tags.order(:title).each do |tag| %>
<% Tag.order(:title).each do |tag| %>
<div class="btn popup__item">
<%= form.check_box "tag_ids[]", {
checked: filter.tags.include?(tag),
+1 -1
View File
@@ -2,7 +2,7 @@
<% content_for :header do %>
<nav>
<%= link_to_back fallback_path: account_users_path %>
<%= link_to_back fallback_path: users_path %>
<span class="btn btn--placeholder"></span>
+3 -4
View File
@@ -2,12 +2,11 @@ Rails.application.routes.draw do
resource :first_run
resource :account do
scope module: :accounts do
resource :join_code
resources :users
end
resource :join_code, module: :accounts
end
resources :users
resources :collections do
scope module: :collections do
resource :subscriptions
@@ -0,0 +1,9 @@
class RemoveAccountIds < ActiveRecord::Migration[8.1]
def change
remove_column :closure_reasons, :account_id
remove_column :collections, :account_id
remove_column :tags, :account_id
remove_column :users, :account_id
remove_column :workflows, :account_id
end
end
Generated
+1 -13
View File
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.1].define(version: 2025_04_12_162339) do
ActiveRecord::Schema[8.1].define(version: 2025_04_12_170620) do
create_table "accesses", force: :cascade do |t|
t.integer "collection_id", null: false
t.datetime "created_at", null: false
@@ -129,11 +129,9 @@ ActiveRecord::Schema[8.1].define(version: 2025_04_12_162339) do
end
create_table "closure_reasons", force: :cascade do |t|
t.integer "account_id"
t.datetime "created_at", null: false
t.string "label"
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_closure_reasons_on_account_id"
end
create_table "closures", force: :cascade do |t|
@@ -148,14 +146,12 @@ ActiveRecord::Schema[8.1].define(version: 2025_04_12_162339) do
end
create_table "collections", force: :cascade do |t|
t.integer "account_id", null: false
t.boolean "all_access", default: false, null: false
t.datetime "created_at", null: false
t.integer "creator_id", null: false
t.string "name", null: false
t.datetime "updated_at", null: false
t.integer "workflow_id"
t.index ["account_id"], name: "index_collections_on_account_id"
t.index ["creator_id"], name: "index_collections_on_creator_id"
t.index ["workflow_id"], name: "index_collections_on_workflow_id"
end
@@ -287,15 +283,12 @@ ActiveRecord::Schema[8.1].define(version: 2025_04_12_162339) do
end
create_table "tags", force: :cascade do |t|
t.integer "account_id", null: false
t.datetime "created_at", null: false
t.string "title"
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_tags_on_account_id"
end
create_table "users", force: :cascade do |t|
t.integer "account_id", null: false
t.boolean "active", default: true, null: false
t.datetime "created_at", null: false
t.string "email_address"
@@ -303,7 +296,6 @@ ActiveRecord::Schema[8.1].define(version: 2025_04_12_162339) do
t.string "password_digest"
t.string "role", default: "member", null: false
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_users_on_account_id"
t.index ["email_address"], name: "index_users_on_email_address", unique: true
t.index ["role"], name: "index_users_on_role"
end
@@ -328,11 +320,9 @@ ActiveRecord::Schema[8.1].define(version: 2025_04_12_162339) do
end
create_table "workflows", force: :cascade do |t|
t.integer "account_id", null: false
t.datetime "created_at", null: false
t.string "name", null: false
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_workflows_on_account_id"
end
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
@@ -353,11 +343,9 @@ ActiveRecord::Schema[8.1].define(version: 2025_04_12_162339) do
add_foreign_key "sessions", "users"
add_foreign_key "taggings", "cards"
add_foreign_key "taggings", "tags"
add_foreign_key "users", "accounts"
add_foreign_key "watches", "cards"
add_foreign_key "watches", "users"
add_foreign_key "workflow_stages", "workflows"
add_foreign_key "workflows", "accounts"
# Virtual tables defined in this database.
# Note that virtual tables may not work with other database engines. Be careful if changing database.
+12 -115
View File
@@ -463,7 +463,7 @@ columns:
default_function:
collation:
comment:
- &33 !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
- &32 !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
auto_increment:
name: title
cast_type: *7
@@ -486,16 +486,6 @@ columns:
comment:
closure_reasons:
- *5
- !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
auto_increment:
name: account_id
cast_type: *1
sql_type_metadata: *2
'null': true
default:
default_function:
collation:
comment:
- !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
auto_increment:
name: label
@@ -535,24 +525,14 @@ columns:
comment:
collections:
- *5
- &32 !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
auto_increment:
name: account_id
cast_type: *1
sql_type_metadata: *2
'null': false
default:
default_function:
collation:
comment:
- !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
auto_increment:
name: all_access
cast_type: &34 !ruby/object:ActiveModel::Type::Boolean
cast_type: &33 !ruby/object:ActiveModel::Type::Boolean
precision:
scale:
limit:
sql_type_metadata: &35 !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata
sql_type_metadata: &34 !ruby/object:ActiveRecord::ConnectionAdapters::SqlTypeMetadata
sql_type: boolean
type: :boolean
limit:
@@ -860,18 +840,16 @@ columns:
- *9
tags:
- *5
- *32
- *6
- *33
- *32
- *9
users:
- *5
- *32
- !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
auto_increment:
name: active
cast_type: *34
sql_type_metadata: *35
cast_type: *33
sql_type_metadata: *34
'null': false
default: true
default_function:
@@ -919,8 +897,8 @@ columns:
- !ruby/object:ActiveRecord::ConnectionAdapters::SQLite3::Column
auto_increment:
name: watching
cast_type: *34
sql_type_metadata: *35
cast_type: *33
sql_type_metadata: *34
'null': false
default: true
default_function:
@@ -953,7 +931,6 @@ columns:
comment:
workflows:
- *5
- *32
- *6
- *10
- *9
@@ -1421,23 +1398,7 @@ indexes:
nulls_not_distinct:
comment:
valid: true
closure_reasons:
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
table: closure_reasons
name: index_closure_reasons_on_account_id
unique: false
columns:
- account_id
lengths: {}
orders: {}
opclasses: {}
where:
type:
using:
include:
nulls_not_distinct:
comment:
valid: true
closure_reasons: []
closures:
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
table: closures
@@ -1489,22 +1450,6 @@ indexes:
comment:
valid: true
collections:
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
table: collections
name: index_collections_on_account_id
unique: false
columns:
- account_id
lengths: {}
orders: {}
opclasses: {}
where:
type:
using:
include:
nulls_not_distinct:
comment:
valid: true
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
table: collections
name: index_collections_on_creator_id
@@ -1994,23 +1939,7 @@ indexes:
nulls_not_distinct:
comment:
valid: true
tags:
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
table: tags
name: index_tags_on_account_id
unique: false
columns:
- account_id
lengths: {}
orders: {}
opclasses: {}
where:
type:
using:
include:
nulls_not_distinct:
comment:
valid: true
tags: []
users:
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
table: users
@@ -2044,22 +1973,6 @@ indexes:
nulls_not_distinct:
comment:
valid: true
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
table: users
name: index_users_on_account_id
unique: false
columns:
- account_id
lengths: {}
orders: {}
opclasses: {}
where:
type:
using:
include:
nulls_not_distinct:
comment:
valid: true
watches:
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
table: watches
@@ -2110,21 +2023,5 @@ indexes:
nulls_not_distinct:
comment:
valid: true
workflows:
- !ruby/object:ActiveRecord::ConnectionAdapters::IndexDefinition
table: workflows
name: index_workflows_on_account_id
unique: false
columns:
- account_id
lengths: {}
orders: {}
opclasses: {}
where:
type:
using:
include:
nulls_not_distinct:
comment:
valid: true
version: 20250412162339
workflows: []
version: 20250412170620
+1 -1
View File
@@ -10,7 +10,7 @@ Current.session = user.sessions.last
workflow = account.workflows.first
COLLECTIONS_COUNT.times do |collection_index|
collection = account.collections.create!(name: "Collection #{collection_index}", creator: user, workflow: workflow)
collection = Collection.create!(name: "Collection #{collection_index}", creator: user, workflow: workflow)
CARDS_PER_COLLECTION.times do |card_index|
collection.cards.create!(title: "Card #{card_index}", creator: user, status: :published)
end
+2 -2
View File
@@ -4,9 +4,9 @@ CARDS_COUNT = 200
ApplicationRecord.current_tenant = "development-tenant"
account = Account.first
user = account.users.first
user = User.first
Current.session = user.sessions.last
collection = account.collections.first
collection = Collection.first
# Doing
@@ -8,34 +8,34 @@ class Accounts::UsersControllerTest < ActionDispatch::IntegrationTest
test "update" do
assert_not users(:david).admin?
put account_user_url(users(:david)), params: { user: { role: "admin" } }
put user_url(users(:david)), params: { user: { role: "admin" } }
assert_redirected_to account_users_path
assert_redirected_to users_path
assert users(:david).reload.admin?
end
test "can't promote to special roles" do
assert_no_changes -> { users(:david).reload.role } do
put account_user_url(users(:david)), params: { user: { role: "system" } }
put user_url(users(:david)), params: { user: { role: "system" } }
end
end
test "destroy" do
assert_difference -> { User.active.count }, -1 do
delete account_user_url(users(:david))
delete user_url(users(:david))
end
assert_redirected_to account_users_path
assert_redirected_to users_path
assert_nil User.active.find_by(id: users(:david).id)
end
test "non-admins cannot perform actions" do
sign_in_as :jz
put account_user_url(users(:david)), params: { user: { role: "admin" } }
put user_url(users(:david)), params: { user: { role: "admin" } }
assert_response :forbidden
delete account_user_url(users(:david))
delete user_url(users(:david))
assert_response :forbidden
end
end
@@ -43,7 +43,7 @@ class CollectionsControllerTest < ActionDispatch::IntegrationTest
test "update all access" do
collection = Current.set(session: sessions(:kevin)) do
accounts("37s").collections.create! name: "New collection", all_access: false
Collection.create! name: "New collection", all_access: false
end
assert_equal [ users(:kevin) ], collection.users
@@ -51,7 +51,7 @@ class CollectionsControllerTest < ActionDispatch::IntegrationTest
assert_redirected_to cards_path(collection_ids: [ collection ])
assert collection.reload.all_access?
assert_equal accounts("37s").users, collection.users
assert_equal User.all, collection.users
end
test "destroy" do
-1
View File
@@ -1,6 +1,5 @@
writebook:
name: Writebook
account: 37s
creator: david
all_access: true
workflow: qa
-2
View File
@@ -1,7 +1,5 @@
web:
account: 37s
title: web
mobile:
account: 37s
title: mobile
-3
View File
@@ -1,21 +1,18 @@
<% digest = BCrypt::Password.create("secret123456") %>
david:
account: 37s
name: David
email_address: david@37signals.com
password_digest: <%= digest %>
role: member
jz:
account: 37s
name: JZ
email_address: jz@37signals.com
password_digest: <%= digest %>
role: member
kevin:
account: 37s
name: Kevin
email_address: kevin@37signals.com
password_digest: <%= digest %>
-2
View File
@@ -1,7 +1,5 @@
qa:
account: 37s
name: QA
on_call:
account: 37s
name: "On call"
@@ -1,8 +0,0 @@
require "test_helper"
class ClosureReasonsTest < ActiveSupport::TestCase
test "create defaults closure reasons on creation" do
account = Account.create! name: "Rails"
assert_equal Account::ClosureReasons::DEFAULT_LABELS, account.closure_reasons.pluck(:label)
end
end
+2 -2
View File
@@ -54,7 +54,7 @@ class CardTest < ActiveSupport::TestCase
end
assert cards(:logo).tagged_with?(tags(:web))
assert_difference %w[ cards(:logo).taggings.count accounts("37s").tags.count ], +1 do
assert_difference %w[ cards(:logo).taggings.count Tag.count ], +1 do
cards(:logo).toggle_tag_with "prioritized"
end
assert_equal "prioritized", cards(:logo).taggings.last.tag.title
@@ -87,7 +87,7 @@ class CardTest < ActiveSupport::TestCase
end
test "in collection" do
new_collection = accounts("37s").collections.create! name: "New Collection", creator: users(:david)
new_collection = Collection.create! name: "New Collection", creator: users(:david)
assert_equal cards(:logo, :shipping, :layout, :text), Card.in_collection(collections(:writebook))
assert_empty Card.in_collection(new_collection)
end
+4 -4
View File
@@ -16,18 +16,18 @@ class CollectionTest < ActiveSupport::TestCase
test "grants access to everyone after creation" do
collection = Current.set(session: sessions(:david)) do
accounts("37s").collections.create! name: "New collection", all_access: true
Collection.create! name: "New collection", all_access: true
end
assert_equal accounts("37s").users, collection.users
assert_equal User.all, collection.users
end
test "grants access to everyone after update" do
collection = Current.set(session: sessions(:david)) do
accounts("37s").collections.create! name: "New collection"
Collection.create! name: "New collection"
end
assert_equal [ users(:david) ], collection.users
collection.update! all_access: true
assert_equal accounts("37s").users, collection.users.reload
assert_equal User.all, collection.users.reload
end
end
+1 -1
View File
@@ -3,7 +3,7 @@ require "test_helper"
class FilterTest < ActiveSupport::TestCase
test "cards" do
Current.set session: sessions(:david) do
@new_collection = accounts("37s").collections.create! name: "Inaccessible Collection"
@new_collection = Collection.create! name: "Inaccessible Collection"
@new_card = @new_collection.cards.create!
@new_card.update!(stage: workflow_stages(:qa_triage))
+1 -1
View File
@@ -7,7 +7,7 @@ class NotifierTest < ActiveSupport::TestCase
test "generate does not create notifications if the event was system-generated" do
cards(:logo).drafted!
events(:logo_published).update!(creator: accounts("37s").users.system)
events(:logo_published).update!(creator: User.system)
assert_no_difference -> { Notification.count } do
Notifier.for(events(:logo_published)).generate
+1 -15
View File
@@ -1,21 +1,7 @@
require "test_helper"
class TagTest < ActiveSupport::TestCase
setup do
@account = accounts("37s")
end
test "creating or deleting a tag touches the account, so tags dialog fragment cache is invalidated" do
assert_changes -> { @account.reload.updated_at } do
@account.tags.create!(title: "ReleaseBlocker")
end
assert_changes -> { @account.reload.updated_at } do
@account.tags.find_by(title: "ReleaseBlocker").destroy
end
end
test "downcase title" do
assert_equal "a tag", @account.tags.create!(title: "A TAG").title
assert_equal "a tag", Tag.create!(title: "A TAG").title
end
end
+1 -4
View File
@@ -3,19 +3,16 @@ require "test_helper"
class UserTest < ActiveSupport::TestCase
test "create" do
user = User.create! \
account: accounts("37s"),
role: "member",
name: "Victor Cooper",
email_address: "victor@hey.com",
password: "secret123456"
assert_equal accounts("37s"), user.account
assert_equal user, User.authenticate_by(email_address: "victor@hey.com", password: "secret123456")
end
test "creation gives access to all_access collections" do
user = User.create! \
account: accounts("37s"),
role: "member",
name: "Victor Cooper",
email_address: "victor@hey.com",
@@ -37,7 +34,7 @@ class UserTest < ActiveSupport::TestCase
end
test "system user" do
system_user = accounts("37s").users.system
system_user = User.system
assert system_user.system?
assert_equal "System", system_user.name