異邦人になってみた~上海の人blog

上海在住です。中国時代劇をよく見ています、中国旅行の事、weiboやQQの設定、一眼レフカメラの写真掲載、上海での日々の生活情報を書いています

 このブログについて(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


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




急がば回れ。。。

ですね。