スポンサーリンク

2015年6月30日

Webホワイトボードの情報収集

目的

Web上で使えるホワイトボードの情報収集

実行環境

なし

始める前に

利用したくなったので調べてみた。

目次

  1. まとめリンク

1. まとめリンク

FlockDraw
シンプルなWebホワイトボードです。
逆に言えば凝ったことをやるとなると、少し大変かもしれませんね。
紹介記事リンク: lifehack - ほぼリアルタイムで共有できるオンライン上のホワイトボード「FlockDraw」
Whiteboard Fox
日本語サイトはありがたい。
リアルタイム共有はできないっぽいですが、
ちょっと図解作成するのであれば便利ですね。
紹介記事リンク: Gigazine - ブラウザ上でホワイトボードを共有できる「Whiteboard Fox」を使ってみた
A Web Whiteboard
これもシンプルなWebホワイトボードです。
アカウント登録がいらないのは助かります。
共有機能もなかなか良さそうです。
紹介記事リンク: ITpro - アカウント登録も不要!ブラウザだけで使える共有ホワイトボード
RealtimeBoard
商用のWebサービスですね。
何と言っても高機能です。そして無料プランがあるのがナイス!
制限はあるけど、他のサービスと併用すればそこまで問題なさそう。
紹介記事リンク1: Web上にホワイトボードを設置できる「Realtime Board」が、あまりに万能すぎてヤバイ!
紹介記事リンク2: Realtime Boardでアイデア管理「便利すぎ!」
RocketBoard
ちょっとWebホワイトボードと言うと違うかもしれないですが・・・
物理的なホワイトボードを認識させてWeb上でリアルタイム共有できる。
っといったところですね。こちらも参考にしてみて下さい。
紹介記事リンク: ホワイトボードの内容をリアルタイムに共有!会議に役立つ、ちょっとハイテクなサービスが海外で登場!
MetaMoJi Share
有料だけど使いやすい。
iOS版のMetaMoJi Noteは確か購入しました。
後は、面白そうなものをNode.jsで作成された方がいるのでリンク貼っておきます。
node.websocket.jsで超適当ホワイトボードアプリ

管理人の独り言~

RealtimeBoardをメインで使用して、
見られても構わないものはA Web Whiteboardを使う形で運用しようかな。
どうせ共有する人、自分を入れて二人だけですし・・・

参考文献

なし

WebRTCって何?

目的

WebRTCの情報についてまとめる。

実行環境

特になし

始める前に

ちょっと前に何かのニュースサイト記事でWebRTCと言う単語を目にした。
何だろうなと思ったので、WebRTCの情報をまとめます。

目次

  1. WebRTCって何?
  2. 何ができるの?
  3. 使われている技術はどんなものがある?
  4. 学習に良さげなサイトリンク

1. WebRTCって何?

Web Real-Time Communicationの略。
W3Cが提唱するリアルタイムコミュニケーション用のAPI。
HTML5のAPI群の一つ。
P2P通信を行っている。

2. 何ができるの?

プラグイン無しでブラウザ間のボイスチャット、ビデオチャット、ファイル共有ができる。
つまりブラウザで何へ入れなくても、双方向のリアルタイムコミュニケーションが実現できると言うことか。
APIは二つで構成されている。
  • ブラウザで映像(Webカメラ)や音声(マイク)を扱うAPI
  • ブラウザ間でP2P(Peer to Peer)の双方向リアルタイム通信を扱うAPI

3. 使われているプロトコルはどんなものがある?

それぞれのプロトコルは調べていないため説明はなし。
プロトコル多いな・・・。
  • SDP
  • STUN
  • TURN
  • ICE
  • DTLS
  • SRTP
  • RTP
  • RTCP
  • SCTP
後は、下位層でUDPを使っているらしい。

4. 学習に良さげなサイトリンク

管理人の独り言~

15分で調べ15分でまとめるとここらが限界だ。
何か、サーバいらないとか書いてある記事があったけど、
STUNサーバ、TURNサーバは必要なことも書いてあった。
(無料で公開しているところがあるとのことだが・・・)
結局サーバいるんじゃん・・・
現状のところまだやろうって気がしないな。
双方向のリアルタイム通信だってPhoenixのチャネル使えば実現できるし。
まぁ、こんなところだろう。

参考文献

[Phoenix]Ectoを使って再マイグレーションする

目的

Ectoで再マイグレーションを行う。

実行環境

OS: Windows8.1
Erlang: Eshell V6.4, OTP-Version 17.5
Elixir: v1.0.4
Phoenix Framework: v0.13.1
PostgreSQL: postgres (PostgreSQL) 9.4.4

始める前に

おそらく必要となると思うので先行して書いておく。
先日の記事を元に実施しますので、
プロジェクトの作成とマイグレーションは終わらせておいて下さい。
よければ参考に・・・
[Elixir+Phoenix]EctoModelsの機能を使う
準備良し。
以降、この記事でのプロジェクトと言えば、
“ecto_models_sample”を指し示す。

目次

  1. マイグレーション再び
  2. カラム追加
  3. カラム削除

1. マイグレーション再び

再マイグレーションの検証を行う。
マイグレーションして生成したテーブルにカラムの追加/削除を行う。
まぁ、データモデルやDB設計の段階でしっかりしろよ!
と言われるかもしれないが、往々にして起こり得ることだと思う。
なので、Ectoで再マイグレーションする方法を書いておく。
カラムの追加/削除だけですが・・・おつきあいくだせー。
今回は、usersテーブルに対してageの項目を追加/削除してみる。

2. カラム追加

さて、ではカラムの追加をしていきます。
まずはマイグレーションファイルを作成します。
マイグレーションする際の名前は重要。
一目で分かるような名前にしておく。
>mix ecto.gen.migration add_age_to_users
* creating priv/repo/migrations
* creating priv/repo/migrations/20150630005902_add_age_to_users.exs
priv/repo/migrationsディレクトリへ行き、
20150630005902_add_age_to_users.exsを開いて下さい。
内容を以下のように編集して下さい。
defmodule EctoModelsSample.Repo.Migrations.AddAgeToUsers do
  use Ecto.Migration

  def change do
    alter table(:users) do
      add :age, :integer
    end
  end
end
マイグレーションしてみます。
>mix ecto.migrate
[info] == Running EctoModelsSample.Repo.Migrations.AddAgeToUsers.change/0 forward
[info] alter table users
[info] == Migrated in 0.0s
動作にエラーは出てない。
問題ないですね。
Tips
再マイグレーションした場合、どのソースに変更を加えればいいのでしょうか?
今回のプロジェクトには、”mix phoenix.gen.html”で生成されたソースコードがあります。
こちらを例に説明します。
まずはモデルモジュールを変更しなくてはなりません。
スキーマへと@required_fieldsへカラムを追加しています。
web/models/user.ex
defmodule EctoModelsSample.User do
  ...
  schema "users" do
    field :name, :string
    field :email, :string
    field :age, :integer

    timestamps
  end

  @required_fields ~w(name email age)
  @optional_fields ~w()
  ...
end
テンプレートを変更しないと表示されませんね。
(やらなくてもエラーは出なかったですけど・・・)
対象としたのは以下のテンプレートです。
web/templates/user/index.html.eex
web/templates/user/show.html.eex
web/templates/user/form.html.eex
一応ソースコードを載せますが・・・参考になることはないと思います。(所詮コピペ)
皆さんが表示したいように実施して下さい。
index.html.eex
<h2>Listing users</h2>

<table class="table">
  <thead>
    <tr>
      <th>Name</th>
      <th>Email</th>
      <th>Age</th>

      <th></th>
    </tr>
  </thead>
  <tbody>
<%= for user <- @users do %>
    <tr>
      <td><%= user.name %></td>
      <td><%= user.email %></td>
      <td><%= user.age %></td>

      <td class="text-right">
        <%= link "Show", to: user_path(@conn, :show, user), class: "btn btn-default btn-xs" %>
        <%= link "Edit", to: user_path(@conn, :edit, user), class: "btn btn-default btn-xs" %>
        <%= link "Delete", to: user_path(@conn, :delete, user), method: :delete, class: "btn btn-danger btn-xs" %>
      </td>
    </tr>
<% end %>
  </tbody>
</table>

<%= link "New user", to: user_path(@conn, :new) %>
show.html.eex
<h2>Listing users</h2>

<table class="table">
  <thead>
    <tr>
      <th>Name</th>
      <th>Email</th>
      <th>Age</th>

      <th></th>
    </tr>
  </thead>
  <tbody>
    <%= for user <- @users do %>
    <tr>
      <td><%= user.name %></td>
      <td><%= user.email %></td>
      <td><%= user.age %></td>

      <td class="text-right">
        <%= link "Show", to: user_path(@conn, :show, user), class: "btn btn-default btn-xs" %>
        <%= link "Edit", to: user_path(@conn, :edit, user), class: "btn btn-default btn-xs" %>
        <%= link "Delete", to: user_path(@conn, :delete, user), method: :delete, class: "btn btn-danger btn-xs" %>
      </td>
    </tr>
<% end %>
  </tbody>
</table>

<%= link "New user", to: user_path(@conn, :new) %>
form.html.eex
<%= form_for @changeset, @action, fn f -> %>
  <%= if f.errors != [] do %>
    <div class="alert alert-danger">
      <p>Oops, something went wrong! Please check the errors below:</p>
      <ul>
        <%= for {attr, message} <- f.errors do %>
          <li><%= humanize(attr) %> <%= message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div class="form-group">
    <label>Name</label>
    <%= text_input f, :name, class: "form-control" %>
  </div>

  <div class="form-group">
    <label>Email</label>
    <%= text_input f, :email, class: "form-control" %>
  </div>

  <div class="form-group">
    <label>Age</label>
    <%= text_input f, :age, class: "form-control" %>
  </div>

  <div class="form-group">
    <%= submit "Submit", class: "btn btn-primary" %>
  </div>
<% end %>

3. カラム削除

ではでは、ageカラムを削除します。
>mix ecto.gen.migration remove_age_to_users
* creating priv/repo/migrations
* creating priv/repo/migrations/20150630014132_remove_age_to_users.exs
作成されたファイルを以下のように編集します。
defmodule EctoModelsSample.Repo.Migrations.RemoveAgeToUsers do
  use Ecto.Migration

  def change do
    alter table(:users) do
      remove :age
    end
  end
end
マイグレーションします。
>mix ecto.migrate
[info] == Running EctoModelsSample.Repo.Migrations.RemoveAgeToUsers.change/0 forward
[info] alter table users
[info] == Migrated in 0.0s
これで削除完了です。

管理人の独り言~

今回はすんなり終わった。
毎回こうだと楽でいいのだが・・・
最近、リモートワークのルールを学習プロセスに取り入れてみようと思った。
ルールができたら、また駄文の記事を作成しようと思う。

参考文献

2015年6月29日

[Elixir+Phoenix]Ecto.ChangesetのValidate関数を使う

目的

Ecto.ChangesetのValidate関数を利用する。

実行環境

OS: Windows8.1
Erlang: Eshell V6.4, OTP-Version 17.5
Elixir: v1.0.4
Phoenix Framework: v0.13.1
PostgreSQL: postgres (PostgreSQL) 9.4.4

始める前に

Ectoを使ってchangeset内でvalidationを行います。
以前のTutorial記事内でも少しだけやる機会がありました。
あまり説明もしていなかったのでまとめます。
先日の記事を元に実施しますので、
プロジェクトの作成とマイグレーションは終わらせておいて下さい。
よければ参考に・・・
[Elixir+Phoenix]EctoModelsの機能を使う
準備良し。
以降、この記事でのプロジェクトと言えば、
“ecto_models_sample”を指し示す。

目次

  1. お前を検証してやる
  2. length(長さ)
  3. format(フォーマット)
  4. unique(一意性)
  5. confirmation(確証)
  6. presence(存在性)

1. お前を検証してやる

検証の仕方は色々とあると思う。
その中でもEcto.Changesetを利用した検証を利用する。
ある程度、使いそうな5つの項目を紹介する。
使い方は非常に簡単です。
これにメソッドチェーンで検証の関数を追加していくだけ。
def changeset(model, params \\ :empty) do
  model
  |> cast(params, @required_fields, @optional_fields)
end
プロジェクトには既に、Userモデル(web/models/user.ex)を作成してますね。
そちらを利用して実施していきます。
お前の:nameと:emailを検証してやる!!

2. length(長さ)

validate_length/3の関数を利用します。
:nameフィールドに対して、最低でも入力されなければならない長さを設定します。
こんな感じになりました。
def changeset(model, params \\ :empty) do
  model
  |> cast(params, @required_fields, @optional_fields)
  |> validate_length(:name, min: 8)
end
今回だけ実行して確認する方法を書いておきます。
以降、実行確認したい場合は、ご自身で実施願います。
>iex -S mix
iex(1)> alias EctoModelsSample.User
iex(2)> params = %{name: "hoge", email: "hoge"}
iex(3)> changeset = User.changeset(%User{}, params)
%Ecto.Changeset{changes: %{email: "hoge", name: "hoge"},
 errors: [name: {"should be at least %{count} characters", 8}], filters: %{},
 model: %EctoModelsSample.User{__meta__: %Ecto.Schema.Metadata{source: "users",
   state: :built}, email: nil, id: nil, inserted_at: nil, name: nil,
  updated_at: nil}, optional: [],
 params: %{"email" => "hoge", "name" => "hoge"}, repo: nil,
 required: [:name, :email], valid?: false,
 validations: [name: {:length, [min: 8]}]}
iex(4)> changeset.valid?()
false
minの値は適当に修正して下さい。
あくまで今回の検証を失敗させるために設定した値です。
(名前が最低でも8文字以上って・・・)

3. format(フォーマット)

validate_format/4の関数を利用します。
:emailフィールドに対して、
アドレスのフォーマットを伴ってなければエラーが出るようにします。
こんな感じになりました。
def changeset(model, params \\ :empty) do
  model
  |> cast(params, @required_fields, @optional_fields)
  |> validate_format(:email, ~r/\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i)
end
さっきの実行確認を流すだけでも失敗してくれます。

4. unique(一意性)

validate_unique/3の関数を利用します。
:nameフィールドに対して一意性を追加します。
こんな感じになりました。
def changeset(model, params \\ :empty) do
  model
  |> cast(params, @required_fields, @optional_fields)
  |> validate_unique(:name, on: EctoModelsSample.Repo)
end
scope:を使うと検証に別のフィールドを追加することもできるみたいです。
例えば、:user_idに紐づく:post_idがあれば、:user_idかつ:post_idと言ったように。
ここではやりませんが、
その内使うことがあると思いますので頭の片隅にでも置いておいて下さい。
(1対多の関係をするときとか使えそうな気がする・・・)

5. confirmation(確証)

validate_confirmation/3の関数を利用します。
パスワードのフィールドがないので、:emailフィールドに対して行います。
def changeset(model, params \\ :empty) do
  model
  |> cast(params, @required_fields, @optional_fields)
  |> validate_confirmation(:email)
end
さて困った(その1)、これで検証動作してくれてるのか?
別にスキーマにemail_confirmationのフィールドがあるわけでもなく・・・
ちょっと不安が残る。
説明では下記のように書かれているのだが・・・
引用:
Validates that the given field matches the confirmation parameter of that field.
By calling validate_confirmation(changeset, :email), this validation will check if both “email” and “email_confirmation” in the parameter map matches.
Note that this does not add a validation error if the confirmation field is nil.
Note “email_confirmation” does not need to be added as a virtual field in your schema.
翻訳:
渡されたフィールドが確証パラメータにマッチすることを確認する。
validate_confirmation(changeset, :email)を呼ぶと、このValidationは”email”と”email_confirmation”がマッチするか調べます。
検証するフィールドが無であるならば、これが確認エラーを加えないことに注意すべきです。
“email_confirmation”がスキーマの仮想フィールドとして加えられる必要はない点に注意して下さい。
Note that this does not add a validation error if the confirmation field is nil.
これ!!
あれ?でもオプションは:messageしかないけど、
どうやってemail_confirmationを指定するの?
スキーマに作ればいいのだろうか?でもこうも言っている。
Note “email_confirmation” does not need to be added as a virtual field in your schema.
申し訳ないですが調査不足ですね。
動作自体はするんだが・・・

6. presence(存在性)

さて困った(その2)・・・presenceに相当するものが分からなかった。
一応、情報っぽいのを見つけたのだが・・・実行できなかった。
Github - Validations in Ecto #94
Github - Validations in Ecto #95
追記(20150629-2125)
友人のエンジニアが調べてくれました。
Ectoのv0.6.0で非推奨になったため上記の機能はなくなったみたいですね。
誤った情報を書いてしまい申し訳ないです。
仕方ないから自分で作るか・・・
幸いなことにこちらは参考になりそうなQA記事が見つかったからね。
しかし、やっぱりと言うべきか・・・見つかったのはStackOverflow。
Ecto - validate presence of associated model
こんな感じに使いたい。
キャストした値の取り方が分からなかったので、直接paramsから取得している。
(あんまり良いやり方じゃないな・・・)
def changeset(model, params \\ :empty) do
  model
  |> cast(params, @required_fields, @optional_fields)
  |> validate_name_presence()
end
先ほどの記事を元にして自作で検証の関数を作成する。
汎用性とか考えないでシンプルに作成する。
def validate_name_presence(changeset) do
  name = Ecto.Changeset.get_field(changeset, :name)
  cond do
    name == nil ->
      add_error changeset, :name, "Name is nil"
    name == "" ->
      add_error changeset, :name, "No Name"
    true ->
      changeset
  end
end
文字列だからnilと空文字のチェックだけしている。
(ハッシュとかきたらどうするんでしょうね?)
後は、実際に使ってみる。
自作してしまったので一応、実行確認を載せておきます。
>iex -S mix
iex(1)> alias EctoModelsSample.User
nil
iex(2)> params = %{name: "hoge", email: "hoge@hoge.com"}
%{email: "hoge@hoge.com", name: "hoge"}
iex(3)> changeset = User.changeset(%User{}, params)
hoge
%Ecto.Changeset{changes: %{email: "hoge@hoge.com", name: "hoge"}, errors: [],
 filters: %{},
 model: %EctoModelsSample.User{__meta__: %Ecto.Schema.Metadata{source: "users",
   state: :built}, email: nil, id: nil, inserted_at: nil, name: nil,
  updated_at: nil}, optional: [],
 params: %{"email" => "hoge@hoge.com", "name" => "hoge"}, repo: nil,
 required: [:name, :email], valid?: true, validations: []}

iex(4)> params = %{name: "", email: "hoge@hoge.com"}
%{email: "hoge@hoge.com", name: ""}
iex(5)> changeset = User.changeset(%User{}, params)
%Ecto.Changeset{changes: %{email: "hoge@hoge.com", name: ""},
 errors: [name: "No Name"], filters: %{},
 model: %EctoModelsSample.User{__meta__: %Ecto.Schema.Metadata{source: "users",
   state: :built}, email: nil, id: nil, inserted_at: nil, name: nil,
  updated_at: nil}, optional: [],
 params: %{"email" => "hoge@hoge.com", "name" => ""}, repo: nil,
 required: [:name, :email], valid?: false, validations: []}

iex(6)> params = %{name: nil, email: "hoge@hoge.com"}
%{email: "hoge@hoge.com", name: nil}
iex(7)> changeset = User.changeset(%User{}, params)
%Ecto.Changeset{changes: %{email: "hoge@hoge.com"},
 errors: [name: "Name is nil", name: "can't be blank"], filters: %{},
 model: %EctoModelsSample.User{__meta__: %Ecto.Schema.Metadata{source: "users",
   state: :built}, email: nil, id: nil, inserted_at: nil, name: nil,
  updated_at: nil}, optional: [],
 params: %{"email" => "hoge@hoge.com", "name" => nil}, repo: nil,
 required: [:name, :email], valid?: false, validations: []}
iex(8)>
うん、動作も大丈夫そうだ。

管理人の独り言~

ちょっと、”validate_confirmation”が怪しいけど、概ね問題はなさそうだ。
そういえば、前にSherrifでValidationうんたら言ってた気がするけど、
あれの機能って本当にValidationなのか・・・う~む、また恥を晒したのだろうか・・・

参考文献

人気の投稿