Rails 4 public_activity с двумя типами владельцев

Я использую gem public_activity в своем приложении и отслеживаю владельца, который создал запись для отслеживания модели событий, я использую devise и у меня есть два типа пользователей, индивидуальный и корпоративный, мой код предназначен для отслеживания владельца

class Event < ActiveRecord::Base
  include PublicActivity::Model
  tracked owner: ->(controller, model) { controller && controller.current_individual }

end

Здесь проблема в том, что я хочу отслеживать владельца как current_company, если компания вошла в систему, но гем public_activity не предоставляет несколько типов владельцев

Я хочу отследить, что если current_individual войдет в систему, то тип владельца и идентификатор будут индивидуальными, и если компания войдет в систему, то в соответствии с этим.

что я делаю

class Event < ActiveRecord::Base
  include PublicActivity::Model
  tracked owner: ->(controller, model) { controller &&  controller.individual_signed_in? ? controller.current_individual : controller.current_company  }
end

но я получаю идентификатор владельца и тип, когда человек вошел в систему, но не получаю тип владельца и идентификатор, когда компания вошла

2 ответа

Решение

На самом деле owner является полиморфным, как можно увидеть здесь:

create_table :activities do |t|
  t.belongs_to :trackable, :polymorphic => true
  t.belongs_to :owner, :polymorphic => true
  t.string  :key
  t.text    :parameters
  t.belongs_to :recipient, :polymorphic => true

  t.timestamps
end

Так что это не проблема, чтобы назначить владельца другого типа.

Если вы хотите назначить компанию владельцем, когда пользователь компании вошел в систему, и лицом, когда вошел в личный кабинет, вам следует просто внести соответствующие изменения в свой код:

tracked owner: ->(controller, model) { controller.current_user.organization? ? controller.current_user.organization : controller.current_user.person }

Я надеюсь, что мой подход не заставляет людей кровоточить. Возможно, это не лучший код для копирования (рад за советы), но я надеюсь, что идея полезна (и она работает):-p

У меня есть большая сеть модельных элементов, которые можно использовать для создания "предпланирования" для чего угодно, от одного здания до целого университетского городка, заполненного десятками структур, сотнями пожарных гидрантов... И структура может иметь все виды вещи (крыша, подъезды (двери), опасные материалы, системы обнаружения пожара, системы защиты, разбрызгиватели и т. д.).

К любому элементу может быть прикреплена / отредактирована / удалена одна или несколько фотографий.

Полиморфный владелец: мне нравится украшать трекинг активности, чтобы показать, кто добавил / отредактировал / удалил фотографию и для какого "владеющего" элемента, независимо от класса.

Таким образом, многоразовый фрагмент используется для создания хорошей зоны "Добавить фото" для любого элемента. Частичное передается локальному, чтобы сказать, что является "владельцем" элемента (структура, или крыша, или система сигнализации):

= render partial: 'photos/photos', locals: {owner: item}

И внутри этой части элемент-владелец анализируется немного дальше... (возможно, излишний, мог бы просто передать владельца и разобрать его в контроллере, теперь, когда я смотрю на него!)

= link_to new_photo_path(:owner_id => owner, :owner_class => owner.class, :tag => owner.class::TAG),

Тогда у контроллера есть некоторые действия, чтобы иметь дело с "владельцем" объекта...

class PhotosController < ApplicationController

  before_action :set_owning_object, only: [:new, :index]
  before_action :get_owning_object, only: [:create, :update]
  ...      
  def set_owning_object
    @owner_class = params["owner_class"]
    @owner_id = params["owner_id"]
    @photo_tag = params["tag"]
    session[:owner_class] = @owner_class if @owner_class
    session[:owner_id] = @owner_id if @owner_id
    session[:photo_tag] = @photo_tag if @photo_tag
    # Unsafe reflection method constantize called with parameter value
    # Let's whitelist the allowable classes that can have Photos
    if @owner_class
      if (%w(Preplan Structure Organization PreplanLayout StagingArea) + Structure::Default_Elements).include? @owner_class
        @owning_object = (@owner_class.constantize).find(@owner_id)
      else
        Rails.logger.warn("OWNING CLASS NEEDS TO BE ADDED: #{@owner_class} was not cleared for use in #{__method__}.")
      end
    else
      @owning_object = nil
    end

  end

И контроллер вручную добавляет действия под желаемыми действиями CRUD с этим очень полиморфным классом "владельца" (который включает модуль HasActivities, который включает гем public_activity):

  def create
    authorize Photo
    @photo = Photo.new(photo_params)
    @photo.tags << @photo_tag
    add_photo(@owning_object, @photo)

    respond_to do |format|
      if @photo.save
        if @owning_object.respond_to? :create_activity
          @owning_object.create_activity(:add_photo,
                                         owner: view_context.current_user,
                                         organization: view_context.current_org,
                                         recipient: @owning_object,
                                         parameters: { name: @photo.caption, file: @photo.photo_name, owner: @owning_object.name })
        end
        pseudo_url = owning_object_url(@owning_object)
        format.html {
          redirect_to pseudo_url, notice: "Photo was successfully added."
        }
        format.json {render json: { photo: render_to_string(partial: 'photos/photo', layout: false, :formats => [:html], locals: { photo: @photo, photo_counter: @photo.id }) }}
      else
        format.html {render action: 'new'}
        format.json {render json: { error: @photo.errors.full_messages.join(',') }, :status => 406}
      end
    end
  end

  def update
    authorize @photo
    if @photo.update_attributes(photo_params)
      @photo.create_activity(:update,
                             owner: view_context.current_user,
                             organization: view_context.current_org,
                             recipient: @owning_object,
                             parameters: { name: @photo.caption, file: @photo.photo_name })
      respond_to do |format|
        format.js
      end
    end
  end

  def destroy
    authorize @photo
    @photo.create_activity(key: 'photo.destroy',
                           owner: current_user,
                           organization: view_context.current_org,
                           parameters: { name: @photo.caption, file: @photo.photo_name })
    @photo.destroy

    respond_to do |format|
      format.html {redirect_to :back}
      format.json {head :no_content}
    end
  end

Вышеупомянутый модуль HasActivities:

module HasActivities
  extend ActiveSupport::Concern

  included do
    include PublicActivity::Common
  end
end

Образец полиморфной активности

Другие вопросы по тегам