Module: Organizations::ViewHelpers

Defined in:
lib/organizations/view_helpers.rb

Overview

View helpers for displaying organization information. Provides formatted data for building UI components without HTML opinions.

Examples:

Include in your ApplicationHelper

module ApplicationHelper
  include Organizations::ViewHelpers
end

Using the organization switcher

<% data = organization_switcher_data %>
<div class="org-switcher">
  <button><%= data[:current][:name] %></button>
  <ul>
    <% data[:others].each do |org| %>
      <li><%= link_to org[:name], data[:switch_path].call(org[:id]) %></li>
    <% end %>
  </ul>
</div>

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object

Host App Route Helper Delegation ===

When views are rendered from engine controllers, route helpers like root_path resolve to the engine's routes, not the host app's routes. This delegation forwards missing route methods to main_app so host app routes work transparently.

Instead of requiring main_app.root_path everywhere, you can just use root_path.



32
33
34
35
36
37
38
# File 'lib/organizations/view_helpers.rb', line 32

def method_missing(method, *args, &block)
  if _organizations_route_helper?(method) && respond_to?(:main_app) && main_app.respond_to?(method)
    main_app.public_send(method, *args, &block)
  else
    super
  end
end

Instance Method Details

#can_change_member_role?(user, membership) ⇒ Boolean

Check if current user can change a member's role

Parameters:

Returns:

  • (Boolean)


257
258
259
260
261
262
263
264
265
266
267
# File 'lib/organizations/view_helpers.rb', line 257

def can_change_member_role?(user, membership)
  return false unless user_has_permission_in_org?(user, membership.organization, :edit_member_roles)
  return false if membership.user_id == user.id # Can't change own role

  # Only owners can change roles to/from owner
  if membership.owner?
    user_has_permission_in_org?(user, membership.organization, :transfer_ownership)
  else
    true
  end
end

#can_delete_organization?(user, organization) ⇒ Boolean

Check if current user can delete the organization

Parameters:

Returns:

  • (Boolean)


281
282
283
# File 'lib/organizations/view_helpers.rb', line 281

def can_delete_organization?(user, organization)
  user_has_permission_in_org?(user, organization, :delete_organization)
end

#can_invite_members?(user, organization) ⇒ Boolean

Check if current user can invite members Uses permission-based check to respect custom role configurations

Parameters:

Returns:

  • (Boolean)


220
221
222
# File 'lib/organizations/view_helpers.rb', line 220

def can_invite_members?(user, organization)
  user_has_permission_in_org?(user, organization, :invite_members)
end

#can_manage_billing?(user, organization) ⇒ Boolean

Check if current user can manage billing Uses permission-based check to respect custom role configurations

Parameters:

Returns:

  • (Boolean)


238
239
240
# File 'lib/organizations/view_helpers.rb', line 238

def can_manage_billing?(user, organization)
  user_has_permission_in_org?(user, organization, :manage_billing)
end

#can_manage_organization?(user, organization) ⇒ Boolean

Check if current user can manage organization settings Uses permission-based check to respect custom role configurations

Parameters:

Returns:

  • (Boolean)


211
212
213
# File 'lib/organizations/view_helpers.rb', line 211

def can_manage_organization?(user, organization)
  user_has_permission_in_org?(user, organization, :manage_settings)
end

#can_remove_member?(user, membership) ⇒ Boolean

Check if current user can remove a member

Parameters:

Returns:

  • (Boolean)


246
247
248
249
250
251
# File 'lib/organizations/view_helpers.rb', line 246

def can_remove_member?(user, membership)
  return false unless user_has_permission_in_org?(user, membership.organization, :remove_members)
  return false if membership.owner? # Can't remove owner

  true
end

#can_transfer_ownership?(user, organization) ⇒ Boolean

Check if current user can transfer ownership

Parameters:

Returns:

  • (Boolean)


273
274
275
# File 'lib/organizations/view_helpers.rb', line 273

def can_transfer_ownership?(user, organization)
  user_has_permission_in_org?(user, organization, :transfer_ownership)
end

#can_view_billing?(user, organization) ⇒ Boolean

Check if current user can view billing information Uses permission-based check to respect custom role configurations

Parameters:

Returns:

  • (Boolean)


229
230
231
# File 'lib/organizations/view_helpers.rb', line 229

def can_view_billing?(user, organization)
  user_has_permission_in_org?(user, organization, :view_billing)
end

#organization_invitation_badge(user) ⇒ String?

Returns pending invitation badge HTML or nil

Examples:

<%= organization_invitation_badge(current_user) %>
# => 3

Parameters:

  • user (User)

    The user

Returns:

  • (String, nil)

    Badge HTML or nil if no invitations



85
86
87
88
89
90
91
92
# File 'lib/organizations/view_helpers.rb', line 85

def organization_invitation_badge(user)
  return nil unless user&.respond_to?(:pending_organization_invitations)

  count = user.pending_organization_invitations.count
  return nil if count.zero?

  (:span, count.to_s, class: "badge")
end

#organization_invitation_status(invitation) ⇒ Symbol

Returns invitation status as a symbol

Parameters:

Returns:

  • (Symbol)

    :pending, :accepted, or :expired



133
134
135
136
137
138
# File 'lib/organizations/view_helpers.rb', line 133

def organization_invitation_status(invitation)
  return :accepted if invitation.accepted_at.present?
  return :expired if invitation.expires_at && invitation.expires_at < Time.current

  :pending
end

#organization_invitation_status_info(invitation) ⇒ Hash

Returns a hash of invitation status information

Parameters:

Returns:

  • (Hash)


152
153
154
155
156
157
158
159
# File 'lib/organizations/view_helpers.rb', line 152

def organization_invitation_status_info(invitation)
  status = organization_invitation_status(invitation)
  {
    status: status,
    label: organization_invitation_status_label(invitation),
    color: invitation_status_color(status)
  }
end

#organization_invitation_status_label(invitation) ⇒ String

Returns a human-readable invitation status label

Parameters:

Returns:

  • (String)


143
144
145
146
147
# File 'lib/organizations/view_helpers.rb', line 143

def organization_invitation_status_label(invitation)
  status = organization_invitation_status(invitation)
  # I18n-backed (organizations.invitation_status.*) — see role labels.
  Organizations.t(:"invitation_status.#{status}", default: status.to_s.humanize)
end

#organization_invitations_data(organization) ⇒ Array<Hash>

Returns data for displaying pending invitations

Parameters:

Returns:

  • (Array<Hash>)


186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/organizations/view_helpers.rb', line 186

def organization_invitations_data(organization)
  organization.invitations.pending.includes(:invited_by).map do |invitation|
    inviter = invitation.invited_by
    {
      id: invitation.id,
      email: invitation.email,
      role: invitation.role.to_sym,
      role_label: organization_role_label(invitation.role),
      invited_by: inviter,
      invited_by_name: inviter_display_name(inviter),
      status: organization_invitation_status(invitation),
      status_info: organization_invitation_status_info(invitation),
      expires_at: invitation.expires_at,
      created_at: invitation.created_at
    }
  end
end

#organization_members_data(organization) ⇒ Array<Hash>

Returns data for displaying organization members

Parameters:

Returns:

  • (Array<Hash>)


166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/organizations/view_helpers.rb', line 166

def organization_members_data(organization)
  organization.memberships.includes(:user).by_role_hierarchy.map do |membership|
    user = membership.user
    {
      id: user.id,
      membership_id: membership.id,
      name: user.respond_to?(:name) && user.name.present? ? user.name : user.email,
      email: user.email,
      role: membership.role.to_sym,
      role_label: organization_role_label(membership.role),
      role_info: organization_role_info(membership.role),
      joined_at: membership.created_at,
      is_owner: membership.owner?
    }
  end
end

#organization_role_info(role) ⇒ Hash

Returns a hash of role information for building badges

Examples:

organization_role_info(:admin)
# => { role: :admin, label: "Admin", color: :blue }

Parameters:

  • role (Symbol, String)

    The role

Returns:

  • (Hash)

    Hash with :role, :label, and :color keys



119
120
121
122
123
124
125
126
# File 'lib/organizations/view_helpers.rb', line 119

def organization_role_info(role)
  role_sym = role.to_sym
  {
    role: role_sym,
    label: organization_role_label(role_sym),
    color: role_color(role_sym)
  }
end

#organization_role_label(role) ⇒ String

Returns a human-readable role label

Examples:

organization_role_label(:admin) # => "Admin"

Parameters:

  • role (Symbol, String)

    The role

Returns:

  • (String)


103
104
105
106
107
108
109
# File 'lib/organizations/view_helpers.rb', line 103

def organization_role_label(role)
  # I18n-backed (organizations.roles.*) so hosts localize/retheme labels
  # by overriding locale keys instead of monkey-patching this helper.
  # Custom roles defined via config.roles fall back to humanize unless
  # the host adds a matching organizations.roles.<name> key.
  Organizations.t(:"roles.#{role}", default: role.to_s.humanize)
end

#organization_switcher_dataHash

Returns optimized data for building an organization switcher Only selects needed columns (id, name) for performance Memoized within the request

Examples:

organization_switcher_data
# => {
#   current: { id: "...", name: "Acme Corp" },
#   others: [
#     { id: "...", name: "Personal" },
#     { id: "...", name: "StartupCo" }
#   ],
#   switch_path: ->(org_id) { "/organizations/switch/#{org_id}" }
# }

Returns:

  • (Hash)

    Hash with :current, :others, and :switch_path



71
72
73
# File 'lib/organizations/view_helpers.rb', line 71

def organization_switcher_data
  @_organization_switcher_data ||= build_switcher_data
end

#respond_to_missing?(method, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


40
41
42
# File 'lib/organizations/view_helpers.rb', line 40

def respond_to_missing?(method, include_private = false)
  (_organizations_route_helper?(method) && respond_to?(:main_app) && main_app.respond_to?(method)) || super
end