Railsで簡易ブログを作る その2
前回やったこと
Railsアプリケーションとデータベースを新規作成し、
ローカル環境上で動くことを確認。
truthfullscore.hatenablog.com
今回やること
- モデルのテーブルをデータベースに追加
- モデルのアソシエーション
テーブルの定義
今回はユーザーと投稿の情報を持つテーブルを作ります。
ログイン機能とユーザー情報はRailsのgemであるdeviseを使用し、
ブログの投稿情報はシンプルにタイトルと本文だけを持つものとします。
usersテーブル
列 | 型 | オプション |
---|---|---|
id | int8 | null: false, unique: true |
nickname | varchar | null: false, index: true |
encrypted_password | varchar | null: false |
... | 以下略 | ... |
postsテーブル
列 | 型 | オプション |
---|---|---|
id | int8 | null: false, unique: true |
title | varchar | null: false, index: true |
article | text | null: false |
user_id | int8 | null: false, foreign_key: true |
ユーザー(user)と投稿(post)は1:Nの関係
この情報をrailsアプリケーションに登録していきましょう。
deviseを導入しuserモデルの作成とデータベース作成
Gemfileを開き末尾に追加
gem "devise"
以下のコマンドでgemファイルをインストール
$ bundle install
以下のコマンドでdevice用のファイルとuserモデルを作成
$ rails g devise:install $ rails g devise user
この時に作られたマイグレーションファイル(db\migrate内)を開き、
ユーザー名(nickname)のカラム情報を追加。
create_table :users do |t| ## Database authenticatable t.string :nickname, null: false, index: true
マイグレーションを実行してデータベース上にusersテーブルを作成。
$ rake db:migrate
postモデルの作成とデータベース作成
以下のコマンドでpostモデルを作成
$ rails g devise post
この時に作られたマイグレーションファイル(db\migrate内)を開き、
postsテーブルの各カラム情報を追加
def change create_table :posts do |t| t.string :title, null: false t.text :article, null: false t.references :user, null: false, foreign_key: true t.timestamps end end
マイグレーションを実行してデータベース上にpostsテーブルを作成。
$ rake db:migrate
これでブログアプリケーションに必要なテーブルがデータベースに追加されました。
アソシエーションの追加
テーブルの定義でも書きましたが、
ユーザー(user)と投稿(post)は1:Nの関係
となるため、その関係性をそれぞれのモデルクラスに記述します。
user.rb
class User < ApplicationRecord devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable has_many :posts end
post.rb
class Post < ApplicationRecord belongs_to :user end
これでブログを扱うためのデータが完成しました。
次回はアプリケーションの画面を作っていこうと思います。
Railsで簡易ブログを作る その1
めちゃくちゃ久しぶりにブログ書きます。
令和になってからWeb技術(主にRuby on RailsとJavascript)を学び始めたので、
アウトプット兼・忘備録としてこれから記事書いてこうと思います。
何を作るか?
勉強課題でブログを作ってみましょうとあったので、
今回はシンプルなプログアプリケーションを作ろうと思います。
以下の機能を実現できるように進めていきます。
- ユーザー管理機能(ログイン・ログアウト・サインインができる)
- ユーザー投稿
- 投稿後の編集
- 投稿の削除
- ユーザー毎にブログが閲覧できる
これ以外の機能は必要に応じて適宜拡張します。
アプリケーションの新規作成
Railsの開発環境導入手順もまとめておきたいですが、
今回は既に開発環境がインストールされている前提でやります。
まずはこれでPostgreSQLを使うRailsアプリケーションを新規作成。
ついでにデータベースも作っておきましょう。
rails new blog_app -d postgresql
rails db:create
この状態でローカルでサーバーを起動し、
rails s
にアクセスすれば
とりあえずローカル環境ではこれで開発を進められるので、
次の記事から徐々に開発を進めていきたいと思います。
Open JTalkをWindowsでビルドして動かしてみる
オープンソースの日本語の音声合成エンジンOpen JTalk
Open JTalk - HMM-based Text-to-Speech System
日本語合成エンジンなのに公式解説は英語だらけだし、
Windowsに導入する際にはソースファイルからビルドが必要だったりと、
一癖あったので忘備録として導入手順をご紹介。
準備
必要なもの
- Open JTalk本体, open_jtalk-1.xx (記述時1.08)
- 解析用辞書ファイル, open_jtalk_dic-1.xx (記述時1.08)
- 音声合成エンジン, hts_engine_API-1.xx (記述時1.09)
- 音響モデルデータ, hts_voice_nitech_jp_atr503_m001-1.xx (記述時1.05)
- Visual Studio Community 2013 (VC++12.0)
ファイルのダウンロード
http://sourceforge.net/projects/hts-engine/から以下のファイルをダウンロード
- hts_engine_API-1.09.tar.gz
http://sourceforge.net/projects/open-jtalk/から以下のファイルをダウンロード。
- open_jtalk-1.08.tar.gz
- open_jtalk_dic_shift_jis-1.08.tar.gz
- hts_voice_nitech_jp_atr503_m001-1.05.tar.gz
辞書ファイル(open_jtalk_dic)は文字コード毎に用意されている模様で、
今回はWindows環境なのでshift_jisを選択。
他の文字コードだとどうなるか不明。
ビルド
hts_engine_APIのビルド
hts_engine_APIがないとOpen JTalkをビルドできないので、
先にhts_engine_APIを以下の手順でビルドします。
call "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"
nmake -f Makefile.mak
nmake -f Makefile.mak install
ビルドに成功すると以下のパスにhts_engine_APIが作成されます。
C:\hts_engine_API
※環境変数のPATHにダブルクォーテーション["]が含まれていると、
「vcvarsall.bat」を呼び出した時点でエラーが発生してビルドが行われません。
環境変数設定のGUI上では入力できないのですが、自分の環境ではDirectX関連のパスが
何故かダブルクォーテーションで囲まれていたのでご注意を。
音声合成
辞書・音響モデルの配置
Open JTalkはコマンドライン実行プログラムであり、
コマンドライン引数として辞書データファイルと音響モデルファイルを指定する必要があるため、
使いやすくするために予め実行ファイルディレクトリに配置しておきます。
- ダウンロートした「open_jtalk_dic_shift_jis-1.08.tar.gz」を解凍
- 解凍したフォルダ名を「dic」にして「C:\open_jtalk\bin」直下に配置
- ダウンロートしたhts_voice_nitech_jp_atr503_m001-1.05.tar.gzを解凍
- 解凍したフォルダ内の「nitech_jp_atr503_m001.htsvoice」を「C:\open_jtalk\bin」直下に配置
input.txt例
こんにちは、お元気ですか
データ配置例
実行
コマンドプロンプトを起動し以下のコマンドを入力
open_jtalk.exe -m nitech_jp_atr503_m001.htsvoice -x dic -ow output.wav input.txt
同一フォルダ内に「output.wav」の音声合成した音声ファイルの出来上がり〜
音声のモデルはどこぞやの男性っぽいですね。
声質を変化させる場合は、コマンドライン引数のパラメータを弄ればいいけど、
別の人の声に変えるにはhtsvoiceファイルを用意しないと無理そうです。
名工大の音声案内端末として使われいるメイちゃん声は落とせるようだけど、
好きな声を使うにはモデル生成する必要があるようでまだまだ謎が多いです。
C#でボックスミューラー法による正規分布に従う乱数生成
.NET Frameworkでは一様乱数を生成するクラスとして
System.Randomクラスが提供されています。
Random クラス (System)
データにノイズを加えるときに一様乱数よりも、
正規分布に従うノイズ(ホワイトガウス)を加えたいというケースがありますが、
.NET Frameworkではそこまでは提供してくれていないので、
ボックスミューラー法による正規分布に従う乱数生成クラスを作ってみました。
ボックスミューラー法
ボックスミューラー法のアルゴリズムは単純で、
(0~1]の範囲を取る一様乱数を2つ用意し(R1,R2)、
以下の式に当てはめるだけで、
N(0.0,1.0)の正規分布に従う乱数が1組生成できます。
また平均値μ、分散σ^2に従う正規分布N(μ,σ^2)での乱数は、
得られた値にσを乗算して、平均値を加えることで求まります。
参考
http://ja.wikipedia.org/wiki/乱数列
http://ja.wikipedia.org/wiki/ボックス=ミュラー法
プログラムソース
RandomBoxMuller.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace RandomBoxMuller { public class RandomBoxMuller { private Random random; public RandomBoxMuller() { random = new Random(Environment.TickCount); } public RandomBoxMuller(int seed) { random = new Random(seed); } public double next(double mu = 0.0, double sigma = 1.0, bool getCos = true) { if (getCos) { double rand = 0.0; while ((rand = random.NextDouble()) == 0.0) ; double rand2 = random.NextDouble(); double normrand = Math.Sqrt(-2.0 * Math.Log(rand)) * Math.Cos(2.0 * Math.PI * rand2); normrand = normrand * sigma + mu; return normrand; } else { double rand; while ((rand = random.NextDouble()) == 0.0) ; double rand2 = random.NextDouble(); double normrand = Math.Sqrt(-2.0 * Math.Log(rand)) * Math.Sin(2.0 * Math.PI * rand2); normrand = normrand * sigma + mu; return normrand; } } public double[] nextPair(double mu = 0.0, double sigma = 1.0) { double[] normrand = new double[2]; double rand = 0.0; while ((rand = random.NextDouble()) == 0.0) ; double rand2 = random.NextDouble(); normrand[0] = Math.Sqrt(-2.0 * Math.Log(rand)) * Math.Cos(2.0 * Math.PI * rand2); normrand[0] = normrand[0] * sigma + mu; normrand[1] = Math.Sqrt(-2.0 * Math.Log(rand)) * Math.Sin(2.0 * Math.PI * rand2); normrand[1] = normrand[1] * sigma + mu; return normrand; } } }
実行例
作成したクラスはRandom関数と同様に、
コンストラクタにシード値を指定させてオブジェクトを初期化し、
(未指定の場合はシステムの起動時刻をシード値として利用)
next関数の引数に正規分布のμとσを指定することで乱数が求まります。
Program.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace RandomBoxMuller { class Program { static void Main(string[] args) { var random = new RandomBoxMuller(); using (var sr = new System.IO.StreamWriter("output.csv")) { for (int i = 0; i < 10000; i++) { sr.WriteLine(random.next()); } } } } }
上記プログラムではN(0.0,1.0)の乱数を1万個生成しています。
得られたデータのヒストグラムは以下のようになりました。
今回-1.0~1.0のデータは6816個得られており、
Z=1.0のときの正規分布データ点数は6826個(0.3413)
なのでほぼ近い値が得られていることが確認できました。
参考
http://www.koka.ac.jp/morigiwa/sjs/standard_normal_distribution.htm
MPU-9150をArduinoに接続して9軸モーションデータを取得する
MPU-9150
MPU-9150はGoogle Grassにも使用されている(らしい)
9軸(加速度・角速度・地磁気)モーションセンサー。
ストロベリーリナックス等でモジュールが購入できます。
https://strawberry-linux.com/catalog/items?code=12150
Arduinoに繋いでセンサーと仲良くなるためのメモ。
Arduinoを使用したデータ取得
単純に9軸データを取得するだけなら、
SparkfunがGitHubで公開している以下のソースを使うと楽。
https://github.com/sparkfun/MPU-9150_Breakout
MPU-9150_Breakoutを使った9軸データ取得
3.Arduino IDEでスケッチを送信
「MPU-9150_Breakout-master.zip」を解凍し解凍したフォルダから、
firmware\MPU6050\Examples\MPU9150_raw\MPU9150_raw.ino
のArduinoスケッチを書き込めば、
シリアル通信で9軸のデータ値が取得できます。
4.物理量として利用するには
このサンプルでは全てのセンサー値が符号付き16ビットで格納されていますが、
値磁気センサーのみ分解能が13ビットなので注意が必要です。
デフォルトでは以下のようにセンサー情報が表されています。
- 加速度:±2G
- 角速度:±250(degree/sec)
- 地磁気:±1200(μT)
また物理量に変換するなら次の式を利用します。
・ 加速度:
・ 角速度:
・ 地磁気:
ちなみに地磁気は周囲の影響を受けまくっているので、
ぐりぐりと8の字に動かしてこの値からオフセットを求めて
補正することが必要になります。
5.もうちょっとできる子なんですが
実はこのセンサー実はもうちょっとできる子です。
センサー公式に概要が書かれていますがセンサーの中に、
Digital Motion Processing™ (DMP™) エンジンが搭載されており、
センサーフュージョンによる姿勢計算をして出力してくれます。
MEMS Gyro-Accel | Gyroscope | Accelerometer | Processing - MPU-9150 9軸(ジャイロ+加速度+コンパス)MEMS MotionTracking™ デバイス
MPU-9150_Breakout-master内の「MPU6050_DMP6.ino」は
DMPエンジンを利用したサンプルスケッチなんですが、
値磁気センサーが組み込まれていない下位モデルのMPU-6050用で、
このままだと6軸のみで地磁気のデータが取れてこない。
そこでまた色々と試行錯誤したわけですがそれは書く機会があれば。
Android Developer Toolkit が 22.6.1 にアップデートできないときの対処
Android SDKマネージャでAndroid SDK Toolsのアップデートを行ったら、
Android Developer Toolkitも更新するように表示されたので、
更新の確認からEclipseプラグインの更新を行おうとしたところ
No repository found containing: org.eclipse.update.feature,com.android.ide.eclipse.ddms,22.6.1.v201403111859-1066720
とエラーが発生し、更新できない&Androidプロジェクト全てがビルドエラー状態に。
サーバー側にデータが置かれてないのか、パスのスペルミスなのかは不明ですが、
新規にAndroid Developer Toolkitをインストールさせることで解決できた。
手順
- [ヘルプ]→[新規ソフトウェアのインストール]をクリック
- [追加]ボタンをクリック
- ロケーションに「https://dl-ssl.google.com/android/eclipse/」を入力し[OK]をクリック
- リスト内に表示された項目にチェックを入れ、[次へ]をクリック
- インストールダイアログの指示に従いインストール
ReadOnlyの時にチカチカしないNumericUpDownを作る
NumericUpDown
GUIで数値を上下に変化させて指定することができる、
NumericUpDownというFormコントロールがあります。
NumericUpDown クラス (System.Windows.Forms)
アプリケーションでユーザーに数値を入力してもらう際に、
ボタンを押せば一定間隔で指定ができるので、
開発側としても変な入力がされにくい便利なコントロール。
ReadOnly時のチカチカがいらないよね
ユーザが直接値を指定して変更させないために、
ReadOnlyのプロパティが用意されていますが、
ReadOnly時でもフォーカスに入るとカーソルがチカチカと点滅。
これじゃユーザが入力できると勘違いする恐れがあります。
チカチカしないNumericUpDownを作る
今回はSystem.Windows.Forms.NumericUpDownクラスを継承して、
ReadOnly時にキャレットを表示させないコントロールを実装してみました。
NumericUpDown継承クラスの作成
NumericUpDownクラスを継承した以下のクラスを作成します。
NumericUpDownNoBlinking.cs
using System; using System.Runtime.InteropServices; using System.Windows.Forms; using System.ComponentModel; namespace NumericUpDownNoBlinking { public partial class NumericUpDownNoBlinking : NumericUpDown { [DllImport("user32.dll")] static extern bool HideCaret(IntPtr hWnd); //キャレット表示の有無を指定 private bool caretVisible = true; //ReadOnlyメソッドを上書き public new bool ReadOnly { get { return base.ReadOnly; } set { base.ReadOnly = value; //キャレットの有無をReadOnly属性に応じて変更 caretVisible = !value; //ReadOnly有効時、NumericUpDownのTextBoxコントロールにカーソルを変化させない。 foreach (Control cntr in this.Controls) { if (cntr is TextBox) { if (caretVisible) { cntr.Cursor = Cursors.IBeam; } else { cntr.Cursor = Cursors.Arrow; } } } } } public NumericUpDownNoBlinking() { InitializeComponent(); } public NumericUpDownNoBlinking(IContainer container) { container.Add(this); InitializeComponent(); } //フォーカス取得時にキャレットを消去 protected override void OnGotFocus(EventArgs e) { base.OnGotFocus(e); if (!caretVisible) { //NumericUpDownのTextBoxコントロールのキャレットを非表示にする foreach (Control cntr in this.Controls) { if (cntr is TextBox) { HideCaret(cntr.Handle); } } } } } }
解説
Windwos APIのHideCaret関数を使えるように、
宣言しておきます。
[DllImport("user32.dll")] static extern bool HideCaret(IntPtr hWnd);
コントロールのOnGotFocusメソッドをオーバーライドし、
フォーカス取得時にControlsプロパティに格納されている
TextBoxのHandleをHideCaret関数の引数に渡せばOK。
protected override void OnGotFocus(EventArgs e) { base.OnGotFocus(e); if (!caretVisible) { //NumericUpDownのTextBoxコントロールのキャレットを非表示にする foreach (Control cntr in this.Controls) { if (cntr is TextBox) { HideCaret(cntr.Handle); } } } }
NumericUpDownのHandleではなくTextBoxを指定することがポイント!
また上記プログラムでは、
テキストボックス上にマウスカーソルが移動しても、
マウスポインタの形状を矢印のままにしています。
こちらもControlsプロパティに格納されているTextBoxに対して、
プロパティを変更することで対処しています。
参考
ネコキス: NumericUpDown のキャレットを消す
[C#] 独自に作成したウィンドウコントロールのコンポーネントにキャレットを表示する