異邦人になってみた~~上海生活写真ブログ

中国上海市在住です。もう10年を超えました。休日は星空(天の川)撮影やポートレート撮影等、連休時はカメラを持って中国各地を旅行してます。最近は内モンゴル自治区によく行っています。

 このブログについて(about)
  中国旅行/観光/写真記事一覧(省別)

Redmineプラグイン作成-既存のビューからモデル作成

ちょっとしたプラグインを作ろうと思って調べてたら結構どっぷりとはまりました。

Redmineで簡単なプラグインを作ろうとしてDB接続について調べていたのですが、
Redmineのプラグインを作る場合のDB接続で正当なやり方は、
モデル→マイグレーションという感じにしてModelクラスを作ると思いますが、
モデルを作って既存テーブルのビュー等からデータを取得したい場合、どうやったらよいのか分かりませんでしたが、結局モデルを作ったのですが。。。

まず最初やったのがチョイプロでMODELを作るのも面倒なんで。。。とりあえずゴリゴリに書こうと思って書きました。
作成したViewはこんな感じで、カスタムフィールドの値を取得する感じのものです。

CREATE VIEW `customvf` AS 
SELECT
  `cv`.`customized_id` AS `customized_id`,
  MAX((CASE WHEN (`cv`.`custom_field_id` = '1') THEN `cv`.`value` END)) AS `cf1`,
  MAX((CASE WHEN (`cv`.`custom_field_id` = '2') THEN `cv`.`value` END)) AS `cf2`,
  MAX((CASE WHEN (`cv`.`custom_field_id` = '4') THEN `cv`.`value` END)) AS `cf4`,
  ~
  MAX((CASE WHEN (`cv`.`custom_field_id` = '27') THEN `cv`.`value` END)) AS `cf27`,
  MAX((CASE WHEN (`cv`.`custom_field_id` = '28') THEN `cv`.`value` END)) AS `cf28`,
  MAX((CASE WHEN (`cv`.`custom_field_id` = '29') THEN `cv`.`value` END)) AS `cf29`,
  MAX((CASE WHEN (`cv`.`custom_field_id` = '30') THEN `cv`.`value` END)) AS `cf30`

   JOIN `bitnami_redmine`.`custom_fields` `cf`
     ON ((`cf`.`id` = `cv`.`custom_field_id`)))
GROUP BY `cv`.`customized_id`$$

ビューcustomvfを作って、これをissuesとJOINします。

SELECT
  `b`.`subject`           AS `subject`,
  `b`.`id`                   AS `id`,
  `b`.`project_id`       AS `project_id`,
  `b`.`description`     AS `description`,
  `b`.`closed_on`      AS `closed_on`,
  ~
  `a`.`customized_id`    AS `customized_id`,
  `a`.`cf1`              AS `cf1`,
  `a`.`cf2`              AS `cf2`,
  ~
  `a`.`cf29`             AS `cf29`,
  `a`.`cf30`             AS `cf30`,
  `c`.`name`           AS `name`
FROM ((`bitnami_redmine`.`issues` `b`
    JOIN `bitnami_redmine`.`customvf` `a`
      ON ((`a`.`customized_id` = `b`.`id`)))
   JOIN `bitnami_redmine`.`issue_statuses` `c`
     ON ((`b`.`status_id` = `c`.`id`)))
WHERE (`b`.`project_id` = 2)$$

こうしたのはissues通常フィールドとカスタムフィールドをいっぺんに取得したかったからなのですが、もっと他に良い方法があるのかもしれません。。
他のいろいろなプラグインを見ていけば答えが出るかもしれませんが。。。
考えているのも面倒だったので、もう直接DBに接続することにしました。最初は下記のように決め打ち(中国語では【写死】)でやってたのです。

Mysql2::Client.new(:host => "ホスト名", :username => "ユーザ名", :password => "パスワード", :database => "DB名")

そうするとサーバーを本番に持っていく際に変更する必要が出てきました。。。
それもなんか面倒なので、結局、database.ymlに接続文字があることが分かります。
ということで、
database_file = Rails.root.join('public', "../config/database.yml").to_s
としてパスを取得、続いてdatabase.ymlをロード
database_config = YAML::load(ERB.new(IO.read(database_file)).result)
後は下記のようにして取得しました。
database_config['production']['host']
database_config['production']['username']
database_config['production']['password']
database_config['production']['database']


Railsには便利な機能があってよいのですが、融通が利かないのが難点ですね。
ここまでやったらソースが結構増えてしまったので、これ結局モデル作った方が早いんじゃない?という事で。。。
私は最終的にどうしたかといいますと。。。結局モデルを作ってしまいました。

既存のビューからモデルを作成(issuesexはモデル名)

bundle exec rails g model issuesex --migration=false

と入れると以下のように表示される
DL is deprecated, please use Fiddle
invoke active_record
create app/models/issuesex.rb
invoke test_unit
create test/models/issuesex_test.rb
create test/fixtures/issuesexes.yml
Usage:
rails new APP_PATH [options]


結局コマンドを入れてもissuesex.rbしか作ってないので手で書いても問題なさそうですが。。。
できたクラスには何も入ってなかったのでViewの名前とPkeyを追加

class Issuesex < ActiveRecord::Base
self.table_name = "issuesex" #→Viewの名前
self.primary_key = :id #→Viewのプライマリキー
end


そして以下のようにして使用できる

client2 = Issuesex.where(["start_date >= ? AND start_date <= ?", sttD , endD])
client2 = Issuesex.all


rowcnt = client2.count
#loop
client2.each do |row|
Rails.logger.debug(row["subject"])
end


まあ簡単にやろうとして。。。徐々に変な方向に行ってしまいまいたが、
やはり何事も孫子の兵法「迂直之计」




急がば回れ。。。

ですね。