-
Notifications
You must be signed in to change notification settings - Fork 0
Redmine Social Extends
Im Modul RedmineSocialExtends werden bestehende Modell-Klassen und Controller-Klassen von Redmine zur Laufzeit um weitere Funktionalitäten ergänzt. Alle Erweiterungen befinden sich im Projektverzeichnis escience/plugins/redmine_social/lib/redmine_social. Ausnahme hiervon bildet patch_pagination.rb, welches nicht zum RedmineSocialExtends gehört.
- Ablaufbeschreibung init.rb
- User
- UsersController
- AppointmentsController
- CommentsController
- UserMessage
- UserMessagesController
- Project
- ProjectsHelper
- ProjectsController
- Mailer
- MyController
- Attachment
- AttachmentsController
- AccountController
- SettingsHelper
- ApplicationController
- AccountController
Zur Laufzeit werden die Klassen um weitere Klassen- und Instanzmethoden ergänzt, die vom Plugin redmine_social benötigt werden. Koordiniert wird das über init.rb. Sie ist für das Plugin redmine_social also essentiell. Für das Testen des Plugins wird sie bspw. über redmine_social/test/test_helper.rb eingebunden.
Anhand von User soll der Ablauf beschrieben werden. In der init.rb wird die Klasse User zur Laufzeit via
User.send(:include, ::RedmineSocialExtends::UserExtension)erweitert. User.send(:include, <Module>) ist synonym zu User.include(<Module>). User wird damit zu einem sog. Mixin, d. h. eine Klasse kombiniert mit einem Modul. Das Modul UserExtension ist in lib/patch_user.rb definiert und hat folgenden Aufbau:
module UserExtension
module ClassMethods
# ...
end
module InstanceMethods
# ...
end
def self.included(receiver)
receiver.extend ClassMethods
receiver.send :include, InstanceMethods
receiver.class_eval do
# ...
end
end
end- Nach dem Aufruf von
User.send :include, RedmineSocialExtends::UserExtensionwird die Methode UserExtension#self.included(receiver) aufgerufen. Der Methode wird hier das Klassenobjekt User an receiver übergeben. - Über
receiver.extend ClassMethodswerden receiver alle Methoden des Moduls UserExtension::ClassMethods als Klassenmethoden hinzugefügt. - Analog dazu werden über
receiver.send :include, InstanceMethodsreceiver alle Methoden des Moduls UserExtension::InstanceMethods als Instanzmethoden hinzugefügt.
Danach stehen also receiver (hier der Klasse User) alle Methoden von ClassMethods als Klassenmethoden und alle Methoden von InstanceMethods als Instanzmethoden zur Verfügung. Sie können über User.a_class_method bzw. my_user.a_instance_method aufgerufen werden.
receiver.class_eval führt den übergebenen Code-Block zur Laufzeit zwischen
class User
# und
endaus. Das Redmine-Social-Plugin nutzt das, um bspw. zusätzliche Action-Filter, Assoziationen und Validatoren zu ergänzen:
# Modul UserExtension
def self.included(receiver)
receiver.class_eval do
validates :skill_list, length: { maximum: 20 }
has_many :photos, :order => "created_at desc", :dependent => :destroy
end
end
# Modul UsersController
def self.included(receiver)
receiver.class_eval do
before_filter :require_admin, :except => [:show, :user_search, :contact_member_search, :online_live_count, :crop_profile_photo, :upload_profile_photo]
end
endLeider werden auch über receiver.class_eval Methoden ergänzt, sodass nicht alle Methoden in den Modulen ClassMethods und InstanceMethods zu finden sind:
# Modul UsersController
def self.included(receiver)
receiver.class_eval do
def update
#...
end
def contact_member_search
#...
end
def require_user_security(user_id)
#...
end
end
endDie instanzmethoden update, contact_member_search, require_user_security(user_id) sind also nicht im Modul InstanceMethods sondern im Codeblock für receiver.class_eval definiert. Auch sie können dann über bspw. my_user.update aufgerufen werden.
Im Folgenden werden alle Erweiterungen nach Klassen geordnet aufgelistet
- security_hash
- calc_security_number(sec_hash)
- method_missing(method_name, *args, &block)
- avatar_photo_url(size = :original)
- selected_security_options
- sort
- can_request_friendship_with(user)
- friendship_exists_with?(friend)
- has_reached_daily_friend_request_limit?
- create_private_project(user=self)
validates :interest_list, length: { maximum: 20 }validates :skill_list, length: { maximum: 20 }
has_many :photoshas_many :albumsbelongs_to :avatarhas_many :friendshipshas_many :accepted_friendshipshas_many :pending_friendshipshas_many :friendships_initiated_by_mehas_many :friendships_not_initiated_by_mehas_many :occurances_as_friendbelongs_to :private_project
- upload_profile_photo
- tag_search
- crop_profile_photo
- update
- contact_member_search
- require_user_security(user_id)
before_filter :require_admin, ...before_filter(:only => [:show]){ ... }
- edit
- create_general_comment
before_filter :find_model_objectbefore_filter :find_project_from_associationbefore_filter :authorize
- send_mails
- get_history
- generate_sent_receiver_copy(receiver_id = self.receiver_id, receiver_list = nil)
- recipients_mail
- receiver_list
has_and_belongs_to_many :group_invitationsbelongs_to :parent
after_save :send_mails
- private get_reply_message
- create
- history_messages
before_filter :get_reply_message, :only => [:new, :create, :show]
has_many :albumshas_one :exclusive_user
- private_project_settings_tabs(project=nil)
- private no_private_project
before_filter :no_private_project, :only => [:show]
- message_id_for(object)
- comment_added(comment)
- user_message_sent(user_message)
- interest_search
- skill_search
- prepare_tag_params
- render_block
- account
- sort
- render_to_image(options=nil)
- image_convertable?
- thumbnailable?
- thumbnail(options={})
- show
- thumbnail
- sent_render_to_image(options=nil)
- set_initial_session_scope
after_filter :set_initial_session_scope, :only => [:login]
- generate_select_from_key(key,value,name_pre,display_attribute="name")
- settings_hash_to_html(settings,name_pre="settings")
- set_user_session_scope
- generate_qr_code(url = params[:p_url], size_x=30, size_y=30)
- set_initial_session_scope
after_filter :set_initial_session_scope, :only => [:login]