当社のサービス紹介やブログ等をお読みの方の多くはRedmineに興味を持たれ、ご利用・ご検討いただいていると思います。 Redmineの改善作業を行っていますと実際に入力した情報(データ)をどのように取り扱っているのか非常に興味を惹かれます。 今回は少し異質(特徴的)なデータの持ち方をしている UserPreference についてご紹介します。
sqlite> .header on sqlite> .mode column sqlite> pragma table_info('user_preferences'); cid name type notnull dflt_value pk ---------- ---------- ---------- ---------- ---------- ---------- 0 id integer 1 1 1 user_id integer 1 0 0 2 others text 0 NULL 0 3 hide_mail boolean 0 1 0 4 time_zone varchar 0 NULL 0
user_preferencesテーブルの構造
UserPreferenceとは、Redmineの中で定義されたモデルのひとつです。そのUserPreferenceが初めて登場したのは2006年12月4日の リビジョン 62 でした。この時はマイページに表示したいブロック(カレンダーや文書等)と配置場所(レイアウト)を利用者(ユーザ)ごとに管理(保持)するために UserPreference が作成されたようです。これ以降利用者(User)ごとのさまざまな(任意の)設定情報を格納しています。
ユーザに関する任意の設定情報は主に UserPreference(実テーブル:user_preferences)の others 列(カラム)で管理しています。この others は ActiveRecord::AttributeMethods::Serialization.serialize を使って宣言します。実際のデータはHashですがこれを YAML形式 に文字列化(シリアライズ)して格納します。Hashなので特定のデータ型に縛られない点が他のモデル(テーブル)とは異なります。
UserPreference#others 宣言部(app/models/user_preference.rb)
class UserPreference < ActiveRecord::Base include Redmine::SafeAttributes belongs_to :user serialize :others
UserPreference の格納データ
$ RAILS_ENV=development bundle exec rails console Loading development environment (Rails 5.2.3) [1] pry(main)> user_preference = User.find(2).pref User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."type" IN ('User', 'AnonymousUser') AND "users"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]] UserPreference Load (0.1ms) SELECT "user_preferences".* FROM "user_preferences" WHERE "user_preferences"."user_id" = ? LIMIT ? [["user_id", 2], ["LIMIT", 1]] => #"0", :comments_sorting=>"asc", :warn_on_leaving_unsaved=>"1", :textarea_font=>"", :my_page_layout=>{"left"=>["issuesassignedtome"], "right"=>["issuesreportedbyme"], "top"=>["issuesupdatedbyme"]}, :my_page_settings=>{}, :recently_used_project_ids=>"1"}, hide_mail: true, time_zone: ""> [2] pry(main)>
others への値の設定・取得は、othersに直接ではなくアクセサメソッドを介して行っています。アクセサメソッドを使うことで設定可能な属性(キー)を制限することができます。
アクセサメソッドの一部(app/models/user_preference.rb)
def [](attr_name) if has_attribute? attr_name super else others ? others[attr_name] : nil end end def []=(attr_name, value) if has_attribute? attr_name super else h = (read_attribute(:others) || {}).dup h.update(attr_name => value) write_attribute(:others, h) value end end def no_self_notified; (self[:no_self_notified] == true || self[:no_self_notified] == '1'); end
アクセサメソッドの使用例
[2] pry(main)> user_preference.no_self_notified => false [3] pry(main)> user_preference.no_self_notified = '1' => "1" [4] pry(main)> user_preference.no_self_notified => true [5] pry(main)> user_preference => #<UserPreference:0x00007f87acac3b28 id: 2, user_id: 2, others: {:no_self_notified=>"1", :comments_sorting=>"asc", :warn_on_leaving_unsaved=>"1", :textarea_font=>"", :my_page_layout=>{"left"=>["issuesassignedtome"], "right"=>["issuesreportedbyme"], "top"=>["issuesupdatedbyme"]}, :my_page_settings=>{}, :recently_used_project_ids=>"1"}, hide_mail: true, time_zone: ""> [6] pry(main)>
UserPreference はとても便利なモデルです。同様にシリアライズ(文字列化)したデータを格納するモデルは他にもあります(Role, CustomField, Query等)が、さまざまなデータ型を格納し利用しているのは UserPreference だけではないかと思います。UserPreferenceのおかげでRedmineの使い勝手が向上している画面(機能)もあります。
個人的には Redmine.org - Feature #4016: Make app settings overridable at project level で UserPreference と同等の機能を持つ(ProjectPreference のような)モデルが組み込まれればプロジェクトごとの設定項目を拡張することも容易になる (画面テーマなどもプロジェクト単位で設定が可能になる)はずです。これによりRedmineはさらに使い勝手が良くなると思います。
Redmineには特徴的なモデルや機能(処理)が他にもありそうです。今後もRedmine改善作業を行いながら新たな技術や実装方法を見つけ出したいと思います(宝探しをしているような気持ちもありますけど)。
![]() |
ファーエンドテクノロジーによる2019年1月〜4月のRedmineの開発状況です。注目している新機能やイチ押し機能をご紹介! |
![]() |
InteropのShowNetテクニカルツアー&セッションに参加。NOC内部など裏側にも入り、スタッフの情熱を肌で感じました。 |
![]() |
redmine.tokyoでRedmine4.1の新機能16個を紹介。そのほか紹介できなかった便利な新機能10個をピックアップして紹介します。 |
![]() |
GWに旅行で韓国へ。料理は量が多くて安い、電車賃も安い韓国と日本との違いを楽しみました。 |
![]() |
Redmineで「こんな機能あったらいいのにな」と思う機能があります。どういった理由で作業が止まっているのでしょうか。 |
![]() |
社員研修に伴うサポート体制変更・休業のお知らせ(5/20〜23) 社員研修に伴い、5月20日〜23日はサポート体制の変更および休業とさせていただきます。 |
![]() |
オープンソースカンファレンス2025 Nagoyaに弊社代表の前田が登壇(ブース出展あり) オープンソースカンファレンス(OSC)2025 Nagoyaに弊社代表の前田が登壇。『Redmineの意外と知らない便利な機能(Redmine 6.0 対応版)』をテーマに発表します。 |
![]() |
エンタープライズプラン向け「優先サポート」を開始 My Redmineでは、エンタープライズプランをご契約のお客様向けにサポート対応を優先的に行う「優先サポート(プライオリティサポート)」を開始いたしました。 |
![]() |
プロジェクト管理ツール「RedMica」バージョン 3.1.0をリリース Redmine互換のオープンソースソフトウェア ファーエンドテクノロジー株式会社は、2024年11月19日(日本時間)、Redmine互換のプロジェクト管理ソフトウェア「RedMica 3.1.0」をリリースしました。 |
![]() |
Redmineの最新情報をメールでお知らせする「Redmine News」配信中 新バージョンやセキュリティ修正のリリース情報、そのほか最新情報を迅速にお届け |