11月 25

Crab apples
Creative Commons License photo credit: ahisgett

Redmine Clientというアプリケーションがあります。Windows(.NET)上で動作するRedmineのクライアントで、機能的には、

  • チケットに費やした時間を計測する
  • 時間をRedmineへ登録する
  • 新しいチケットを登録する

というシンプルなものです。C#で書かれています。

このアプリケーションにはRedmineへアクセスするためのライブラリ(DLL)が添付されており、APIの仕様も公開されています。(どちらかと言うと、アプリケーションはこのライブラリのサンプル的な位置付けなのかな?)

Redmineは0.9でRESTfulになるらしいので、それまで待とうか…という気もしないではないのですが、このライブラリのFUTURE PLANSには“Making use of Redmine 0.9 RESTfull interface”とあり、0.9でRESTfullになったら対応する模様。

ということで、安心して?試してみました。

インストールと設定

  1. ここからredmineclient-0.3.0.zipをダウンロードする。
  2. アーカイブを解凍しNohal.Redmine.dllをVisual Studioのプロジェクトで参照設定する。

これだけです。

チケット一覧を取得するための基本的な流れ

以下のような流れでチケット一覧を取得できます。簡単。

  1. Redmineオブジェクトの生成
  2. RedmineのURLを設定(Redmine.RedmineBaseUriプロパティ)
  3. Redmineへのログイン(Redmine.LogInメソッド)
  4. プロジェクト一覧の取得(Redmine.GetProjectsメソッド)
  5. プロジェクトIDを指定してチケット一覧の取得(Redmine.GetIssuesメソッド)

(載せるまでも無いですが)実際のコードはこんな感じ。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Nohal.Redmine;

namespace RedmineTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Redmine redmine = new Redmine();
            redmine.RedmineBaseUri = "RedmineのURL";
            redmine.LogIn("Redmineのユーザ名", "Redmineのパスワード");

            List<Project> projects = redmine.GetProjects();
            textBox1.Text = "プロジェクト一覧\r\n";
            foreach (Project project in projects)
                textBox1.Text += project.Id.ToString() + ": " + project.Name + "\r\n";

            textBox1.Text += "チケット一覧\r\n";
            // GetIssues(3)の3はプロジェクトID。本来はGetProjects()で取得したIDを指定する。
            foreach (Issue issue in redmine.GetIssues(3))
                textBox1.Text += issue.Id + ": " + issue.Subject + "\r\n";
        }
    }
}

ざっとAPI仕様を眺めた限りでは、条件を指定してチケットを絞り込む方法が無さそうです。
このため、指定したプロジェクトの全チケットがListで返却されますので、チケット数が数千~数万のオーダーになると厳しいかもしれませんが、チケットの登録はイケるでしょう。

C#から簡単にRedmineへアクセスできるのはいいですね。Redmineクライアントの開発をお考えての方はお試しください。

Tagged with:
11月 07

evernote

Evernoteは開発者向けにAPIを提供しています。

C#で書こうとしているちょっとしたプログラムの調査のため、Evernote APIをラップするC#のライブラリEvernoteSharp試してみました。

Evernote APIを使うためには、API Keyを払い出してもらう必要があります。Request an API Keyから、必要事項を書いて申し込みます。私の場合は申し込んでから1時間半ぐらいでAPI Keyがメールで送られてきました。仕事が速いですね!

API Keyは開発用環境であるSandBoxのみで有効です。このため、普段使っているアカウントとは別にEvernote Registrationからテスト専用のアカウントを登録します。

次に、Visual StudioでWindowsアプリケーションのプロジェクトを作成します。EvernoteSharpをダウンロードし、アーカイブを解凍してEvernoteSharp.dllをプロジェクトの参照設定へ追加します。準備はこれで完了。

以下のコードは、指定した画像ファイルをEvernoteのデフォルトのノートブックへ追加するものです。

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Security.Cryptography;
using EvernoteSharp;

namespace EvernoteSample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            StoreFactory sf = new StoreFactory(new Uri("http://sandbox.evernote.com/"), "your-api-key-here!", "your-api-secret-here!");
            UserStoreWrapper userStore = sf.CreateUserStore();

            if (!userStore.CheckVersion())
                throw new Exception("Invalid API version");
            userStore.Authenticate("your-username", "your-password");

            NoteStoreWrapper noteStore = sf.CreateNoteStore();
            Evernote.EDAM.Type.Data data = new Evernote.EDAM.Type.Data();

            FileStream fs = new FileStream(tbTitle.Text, FileMode.Open, FileAccess.Read);
            byte[] bImageFile = new byte[fs.Length];
            fs.Read(bImageFile, 0, bImageFile.Length);
            fs.Close();

            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            byte[] bs = md5.ComputeHash(bImageFile);
            string hashHex = BitConverter.ToString(bs).ToLower().Replace("-","");

            data.Size = bImageFile.Length;
            data.BodyHash = bs;
            data.Body = bImageFile;

            Evernote.EDAM.Type.Resource resource = new Evernote.EDAM.Type.Resource();
            resource.Mime= "image/png";
            resource.Data = data;

            Evernote.EDAM.Type.Note note = new Evernote.EDAM.Type.Note();
            var defaultNotebook = noteStore.GetDefaultNotebook();

            note.NotebookGuid = defaultNotebook.Guid;
            note.Title = tbTitle.Text;
            note.Content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                            "<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml.dtd\">" +
                            "<en-note>" +
                            "<en-media type=\"image/png\" hash=\"" + hashHex + "\"/>" +
                            "</en-note>";

            note.Updated = note.Created;
            List<Evernote.EDAM.Type.Resource> resourceList = new List<Evernote.EDAM.Type.Resource>();
            resourceList.Add(resource);
            note.Resources = resourceList;

            noteStore.CreateNote(note);

            MessageBox.Show(tbTitle.Text + "をEvernoteへ追加しました");
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
                tbTitle.Text = openFileDialog1.FileName;
        }
    }
}

うん、これでなんとかいけそう。

Evernote APIの資料はこちらです。

Tagged with:
9月 05

ActiveSalesforceというSalesforceのデータベースをActiveRecord経由でアクセスできるアダプタを触ってみました。ちょっとハマった部分があるのでメモしておきます。

インストールと設定

私が試した環境はRails 2.1.0です。Rails 2.xだと、

$ gem install activerecord-activesalesforce-adapter

だけでOK。Rails 1.xだとインストールと設定の手順が違いますのでこちらを参照してください。

インストール後、すぐに下にあるようなコードを書いて動かしてみたのですが、RubyForge: ActiveSalesforce: トラッカー詳細: 19960 defining belongs_to with :dependent => :nullify is broken in edge rails > r8675と同じ事象が発生し動作しませんでした。このチケットにあるパッチをあてたところ、うまく動くように。

次にRailsでプロジェクトを作成し、config/database.ymlを次のように書き換えます。

development:
  adapter: activesalesforce
  url: https://www.salesforce.com/services/Soap/u/8.0
  username: Salesforceのアカウント
  password: Salesforceのパスワード|セキュリティトークン

ActiveSalesforceのドキュメントではパスワードだけを指定するように書かれていますが、今のSalesforceでは(ネットワークを信頼済みに設定しない限り)API経由でアクセスする際はパスワードに続けてセキュリティートークンを指定する必要があります。

セキュリティトークンはSalesforceにログインし、[設定] | [私の個人情報] | [セキュリティトークンのリセット] から参照できます。

尚、上記のconfig/database.ymlのサンプルでは、パスワードとセキュリティトークンの間に|がありますが、これは可読性のために入れてあります。

実際に指定するときはパスワードに続けてセキュリティトークンを指定してください。

Salesforceのデータにアクセスする

あとはRailsの世界です。ここではSalesforceの取引先(account)の一覧を出力してみます。accountのコントローラとビューを作成します。コントローラの方はこんな感じ。

def index
  @accounts = Account.find(:all)
  respond_to do |format|
    format.html # index.html.erb
    format.xml  { render :x ml => @accounts }
  end
end

ビュー(index.html.erb)はこんな感じ。

<h1>取引先一覧</h1>

<table>
  <tr>
    <th>取引先番号</th>
    <th>取引先名</th>
    <th>住所(請求先)</th>
    <th>電話</th>
    <th>Fax</th>
    <th>説明</th>
  </tr>

<% for account in @accounts %>
  <tr>
    <td><%=h account.account_number %></td>
    <td><%=h account.name %></td>
    <td>
        <%=h account.billing_postal_code %>
        <%=h account.billing_state %>
        <%=h account.billing_city %>
        <%=h account.billing_street %>
    </td>
    <td><%=h account.phone %></td>
    <td><%=h account.fax %></td>
    <td><%=h account.description %></td>
  </tr>
<% end %>
</table>

http://localhost:3000/accountsへアクセスしたらこんな感じに。

account.png

うん、普通にRailsアプリですね。とは言え、Salesforceのスキーマを知らないと何もできません。

SalesforceのスキーマはForce.com Web Services API Developer’s GuideのReference – Standard Objectsから参照可能です。

なお、RailsからSalesforceのデータへアクセスする場合、メンバ名を以下のように読み替える必要がありますのでご注意。

Filed Name(ドキュメントの表記) Railsのメンバ名
BillingPostalCode billing_postal_code

Salesforceを導入するような企業は既に基幹システムを持っているケースも多いと思います。

その場合、Force.com APIを使ってAjaxリクエストでデータを取得したり、バッチを開発したりして既存システムとSalesforceのデータ連係を実現する方法が主流だと思いますが、ActiveSalesforce + Railsという構成で、Railsの生産性の高さを生かしたSalesforce連携システム開発というのも可能性を感じます。

Salesforceに関しては標準のカスタマイズの他に、システム間連携の開発も可能です。そのような案件がありましたら、ぜひご相談ください。連絡先はこちらです。

Tagged with:
preload preload preload