Skip to content

Commit

Permalink
Add organization relationship to posts
Browse files Browse the repository at this point in the history
  • Loading branch information
jameswilliamiii committed Oct 17, 2024
1 parent 7adea99 commit ed41ff0
Show file tree
Hide file tree
Showing 18 changed files with 107 additions and 33 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ group :test do
gem "minitest-rails"
gem "minitest-spec-rails"
gem "mocha"
gem "rails-controller-testing"
gem "selenium-webdriver"
gem "shoulda-context"
gem "shoulda-matchers"
Expand Down
5 changes: 5 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,10 @@ GEM
rackup (2.1.0)
rack (>= 3)
webrick (~> 1.8)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
actionview (>= 5.0.1.rc1)
activesupport (>= 5.0.1.rc1)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
Expand Down Expand Up @@ -419,6 +423,7 @@ DEPENDENCIES
pry-rails
puma (>= 5.0)
rails!
rails-controller-testing
rbui!
rubocop-rails-omakase
selenium-webdriver
Expand Down
1 change: 1 addition & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class ApplicationController < ActionController::Base
include Authentication
include Organizationable
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
# TODO: Turn on after styling is complete.
# allow_browser versions: :modern
Expand Down
21 changes: 21 additions & 0 deletions app/controllers/concerns/organizationable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module Organizationable
extend ActiveSupport::Concern

included do
before_action :assign_organization
end

def current_organization
Current.organization || Current.user.base_organization
end

def assign_organization
return unless Current.user

Current.organization = find_organization_by_cookie
end

def find_organization_by_cookie
Organization.find_by(id: cookies.signed[:organization_id]) || Current.user.base_organization
end
end
9 changes: 7 additions & 2 deletions app/controllers/posts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class PostsController < ApplicationController

# GET /posts
def index
@posts = Post.all
@posts = current_organization.posts.order(created_at: :desc)
end

def show
Expand Down Expand Up @@ -47,7 +47,12 @@ def set_post
end

def post_params
params.expect(post: [ :title, :message, :user_id ]).merge(user_id: current_user.id)
params.expect(
post: [ :title, :message, :user_id ]
).merge(
user_id: current_user.id,
organization_id: current_organization.id
)
end

def authorize_user!
Expand Down
9 changes: 1 addition & 8 deletions app/controllers/registrations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def create
User.transaction do
@user = User.new(user_params)
if @user.save
create_organization_for(@user)
@user.create_base_organization!
start_new_session_for(@user)
redirect_to root_path, notice: "Welcome to PostIt! Start adding projects and tasks."
else
Expand All @@ -32,11 +32,4 @@ def user_params
]
)
end

def create_organization_for(user)
Organization.transaction do
organization = Organization.create!(name: user.name)
user.memberships.create!(organization: organization, role: :owner)
end
end
end
2 changes: 1 addition & 1 deletion app/models/current.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class Current < ActiveSupport::CurrentAttributes
attribute :session
attribute :session, :organization
delegate :user, to: :session, allow_nil: true
end
1 change: 1 addition & 0 deletions app/models/organization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ class Organization < ApplicationRecord

has_many :memberships, dependent: :destroy
has_many :users, through: :memberships
has_many :posts, dependent: :destroy
end
1 change: 1 addition & 0 deletions app/models/post.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ class Post < ApplicationRecord
# Associations
#-----------------------------------------------------------------------------
belongs_to :user
belongs_to :organization
has_rich_text :message

#-----------------------------------------------------------------------------
Expand Down
14 changes: 14 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,18 @@ class User < ApplicationRecord
#-----------------------------------------------------------------------------

normalizes :email_address, with: ->(e) { e.strip.downcase }

#-----------------------------------------------------------------------------
# Instance Methods
#-----------------------------------------------------------------------------

def base_organization
organizations.joins(:memberships).merge(Membership.owner).first || create_base_organization!
end

def create_base_organization!
organization = Organization.create!(name: name)
memberships.create!(organization: organization, role: :owner)
organization
end
end
29 changes: 9 additions & 20 deletions app/views/posts/show.html.erb
Original file line number Diff line number Diff line change
@@ -1,28 +1,17 @@
<div class="mx-auto md:w-2/3 w-full flex">
<div class="mx-auto w-full">
<% if notice.present? %>
<p class="py-2 px-3 bg-green-50 mb-5 text-green-500 font-medium rounded-lg inline-block" id="notice"><%= notice %></p>
<% end %>

<%= render @post %>

<%= render RBUI::Link.new(href: edit_post_path(@post), variant: :outline, class: "me-3") { "Edit" } %>
<%#= render RBUI::Link.new(
href: post_path(@post),
variant: :destructive,
data: { turbo_method: :delete, turbo_confirm: "Are you sure you want to delete this post?" },
class: "ms-3") {
"Delete"
} %>

<%= render Components::ConfirmDialog.new(
variant: :destructive,
href: post_path(@post),
title: "Are you sure?",
description: "This action cannot be undone. This will permanently delete your post.",
action_text: "Delete post",
cancel_text: "Cancel",
data: { turbo_method: :delete },
) { "Delete" } %>
<%= render Components::ConfirmDialog.new(
variant: :destructive,
href: post_path(@post),
title: "Are you sure?",
description: "This action cannot be undone. This will permanently delete your post.",
action_text: "Delete post",
cancel_text: "Cancel",
data: { turbo_method: :delete },
) { "Delete" } %>
</div>
</div>
5 changes: 5 additions & 0 deletions db/migrate/20241017211831_add_organization_to_post.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddOrganizationToPost < ActiveRecord::Migration[8.0]
def change
add_reference :posts, :organization, null: false, foreign_key: true
end
end
5 changes: 4 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion test/controllers/posts_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,21 @@ class PostsControllerTest < ActionDispatch::IntegrationTest

assert_response :success
end

test "should only get posts for the current organization" do
organization = create(:organization)
user.organizations << organization
Current.stubs(:organization).returns(organization)

post = create(:post, organization: organization)
get posts_url

assert_includes assigns(:posts), post
end
end # GET /posts

describe "GET /posts/new" do
test "should be successful" do
create(:user) # TODO: replace once authentication built
get new_post_url

assert_response :success
Expand Down
4 changes: 4 additions & 0 deletions test/factories/memberships.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,9 @@
trait :admin do
role { :admin }
end

trait :owner do
role { :owner }
end
end
end
1 change: 1 addition & 0 deletions test/factories/posts.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
FactoryBot.define do
factory :post do
user
organization
title { "MyString" }
end
end
1 change: 1 addition & 0 deletions test/models/organization_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class OrganizationTest < ActiveSupport::TestCase

should have_many(:memberships).dependent(:destroy)
should have_many(:users).through(:memberships)
should have_many(:posts).dependent(:destroy)
end

describe "Validations" do
Expand Down
19 changes: 19 additions & 0 deletions test/models/user_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,23 @@ class UserTest < ActiveSupport::TestCase
assert_equal email.downcase, user.email_address
end
end

describe "Instance Methods" do
describe "#base_organization" do
it "should return the user's base organization" do
membership = create(:membership, :owner)
user = membership.user
assert_equal membership.organization, user.base_organization
end

it "should create a base organization if one does not exist" do
user = create(:user)
assert_difference("Organization.count", 1) do
assert_difference("Membership.count", 1) do
user.base_organization
end
end
end
end
end
end

0 comments on commit ed41ff0

Please sign in to comment.