Ruby on Railsでヘッダディテール型(親子テーブル)のデータを1画面で表現、登録する。

ヘッダディテール型、ヘッダのテーブルと明細のテーブルが1つになった画面を作りたいと思います。

実装仕様(イメージ)について

ヘッダと明細が同じ画面で表示されて、それを更新するパターン

実装環境

今回の利用したRails環境は以下のとおりです。

OS:    Windows XP (そろそろ変えたい…そればっかやな…)
Ruby:  Ruby 2.0.0p247
Rails: Rails 4.0.0
* 前回の記事内容のDevise実装が出来ている事とします。

実施内容

テスト用の新規アプリを作成

$ rails new headerdetail --no-test-framework

ヘッダのモデル・ビュー・コントローラを作る(Scaffoldを利用)

$ rails generate scaffold header header_number:integer header_description:string

明細(ディテール)のモデルを作る ※明細はモデルのみで対応するビュー等は必要ない。

$ rails generate model detail detail_number:integer detail_description:string header_id:integer

DB定義を反映する

$ bundle exec rake db:migrate

モデルに親子関係を記載する。

1.ヘッダ側のファイル
ファイル:app/models/header.rb
以下の記述を追加
has_many :details
accepts_nested_attributes_for :details, allow_destroy: true

2.明細側のファイル
ファイル:app/models/detail.rb
以下の記述を追加
belongs_to :header
validates :header_id, ;detail_number, presence: true

コントローラを修正する。

ファイル:app/controllers/header_controller.rb
1. newメソッドにヘッダの行を追加(とりあえず3行)
   そのうち、手動で増やすオプションが必要だと思われるが、それは別途調べる事にする。

  def new
    @header = Header.new
    #ここから追加
    3.times{
      @header.details.build
    }
  end

2. Strong Parametersをいじる。これは資料が少なくて結構ハマったけど、明細側のファイルは :(明細モデル)_attributes => [:id, :_destroy, (要素)]となるようです。

    def header_params
        params.require(:header).permit(:header_number, :header_description,
               :details_attributes => [:id, :detail_number, :detail_description, :_destroy])
    end

ビューを修正する。明細の表示を追加

ファイル:app/views/headers/_form.html.erb
  <div class="field">
    <%= f.fields_for :details do |dtl| %>
       <%= dtl.label :detail_number %><br/>
       <%= dtl.number_field :detail_number %><br/>
       <%= dtl.label :detail_description %><br/>
       <%= dtl.text_field :detail_description %><br/>
    <% end %>
  </div>

これで、レイアウトの問題は無視して、とりあえずヘッダと明細の同時更新が可能になりました。今日は疲れたので、ここまでとします。

Ruby on RailsでユーザIDと入力データの関連付けをする

前回の記事では、Deviseを利用して、ユーザ認証を実装しました。今回はその続きでログインユーザ自身が入力したデータのみ参照・追加・更新が出来るようにデータのアクセスコントロールをしていこうを思います。

実装仕様

1. ログインしたユーザ自身が投稿した内容しか表示されない。
2. もちろんですが、ログインしないと投稿が出来ない。

上記のイメージで作っていきたいと思います。

利用環境

今回の利用したRails環境は以下のとおりです。

OS:    Windows XP (そろそろ変えたい…)
Ruby:  Ruby 2.0.0p247
Rails: Rails 4.0.0
* 前回の記事内容のDevise実装が出来ている事とします。

実施内容

まず、scaffoldを利用して、postsモデルとビューを作成とdb:migrate

$ rails generate scaffold post content:string
$ bundle exec rake db:migrate

postsモデルにuser_idを追加する。

$ rails generate migration add_user_id_to_posts user_id

user_idの型をIntegerに変更

ファイル:db/migrate/(日付時間)_add_user_id_to_posts.rb
以下の記述に変更
add_column :posts, :user_id, :integer

db:migrateを実施し、DBに変更を反映する。

$ bundle exec rake db:migrate

モデル間の関係を記載する。

1. postsがusersに所属している。かつpostのuser_idは必須
ファイル:app/models/post.rb
以下の記述を追加
belongs_to :user
validates :user_id, presence: true

2. usersとpostsは1対多になる。
ファイル:app/models/user.rb
以下の記述を追加
belongs_to :user

コントローラを修正する。自分が投稿した内容のみを表示するようにする。

current_userというDeviseのヘルパーを利用すると、現在ログインしているuserオブジェクトを返してくれるみたいなので、それを利用する。基本現状Postとなっている箇所をcurrent_user.postsに変更する。

ファイル:app/controllers/posts_controller.rb
まずは、以下の記述を追加
before_filter :authenticate_user!

修正1:自分で投稿した内容のみ表示する。(index)
・修正前
  def index
    @posts = Post.all
  end

・修正後
  def index
    @posts = current_user.posts.all
  end

修正2:自分で投稿した内容のみ表示する。(show)
・修正前
    def set_post
      @post = Post.find(params[:id])
    end

・修正後
    def set_post
      @post = current_user.posts.find(params[:id])
    end

修正3:セキュリティの設定をいじって、user_idデータも許すようにする。
・修正前
    def post_params
      params.require(:post).permit(:content)
    end

・修正後
    def post_params
      params.require(:post).permit(:content, :user_id)
    end

ビューを修正する。_form.html.erb(newとeditで利用している)のviewを修正。内容は、user_idをhiddenで追加して、Submitするようにする。

ファイル:app/views/posts/_form.html.erb
・修正前
  <div class="field">
    <%= f.label :content %><br>
    <%= f.text_field :content %>
  </div>

・修正後
  <div class="field">
    <%= f.label :content %><br>
    <%= f.text_field :content %>
    <%= f.hidden_field :user_id, value: current_user.id %>
  </div>

これで、ログインしたユーザの投稿内容のみ表示できるようになりました。今日の所は疲れたので、ここまでとします。

Ruby on Rails環境にてDeviseを利用する

Deviseとは

Deviseとは、RubyGemsで公開されている。最も有名な認証機能のプラグインです。

Deviseを利用するメリット

  1. ノーコーディングで、入会、退会、ログイン、ログアウト、入会時のメール認証等の機能を利用出来る。
  2. 設定が柔軟で、例えば入会時のメール認証の有無や、メールアドレスでの認証、ユーザ名での認証等、たくさんのパターンに対応可能

というような事が書いてありますので、使ってみたいと思います。

利用環境

今回のDeviseで利用したRails環境は以下のとおりです。

OS:    Windows XP (古いな…)
Ruby:  Ruby 2.0.0p247
Rails: Rails 4.0.0

セットアップと基本的な使い方

Deviseを試す為に新しいRailsアプリケーションを作成する。

$ rails new authentication_test --no-test-framework

GemFileにDeviseの記述を追加→bundle installコマンドを利用してDeviseをインストール

gem 'devise'
$ bundle install

アプリ内にコンフィグファイルを作成する為のコマンドらしい

$ rails generate devise:install

環境ファイルの設定(とりあえず開発環境のみ)

ファイル:config/environments/development.rb
最終行に以下の記述を追加
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
* localhost:3000は適宣変更する必要がある。

ここで認証ホーム画面用にScaffoldを作成する。テスト用

$ rails generate scaffold home code:string name:string

Devise用のユーザモデルを作成する

$ rails generate devise user

モデルを作成したので、db:migrateコマンドを実行する。

$ bundle exec rake db:migrate

ログイン後、サインアップ後のパスはrootパスになるので、rootパスの明示をする。先程Scaffoldで作ったhomes#indexを設定する。

ファイル:config/route.rb
以下の記述を追加
root :to => "homes#index"

レイアウトファイルに以下の記述を追加。基本RailsCastからコピーした。

ファイル:app/views/layouts/application.html.rb
<div id="container">
  <div id="user_nav">
    <% if user_signed_in? %>
     Logged in as <strong><%= current_user.email %></strong>.
      <%= link_to 'Edit profile', edit_user_registration_path %> |
     <%= link_to "Logout", destroy_user_session_path, method: :delete %>
    <% else %>
      <%= link_to "Sign up", new_user_registration_path %> |
     <%= link_to "Login", new_user_session_path %>
   <% end %>
 </div>

  <% flash.each do |name, msg| %>
    <%= content_tag :div, msg, id: "flash_#{name}" %>
  <% end %>
</div>

一回サーバを起動してみる。

$ rails s
* とりあえず動作していそうな事は確認できた。

Viewのカスタマイズをするために、Viewを作成する。

$ rails generate devise:views
* 出来たViewファイルをカスタマイズ可能
* カスタマイズは適当に対応可能

ログインをしていない場合、データを入力できないようにFilterを設定

ファイル:app/controllers/homes_controller.rb
以下の記述を追加
before_filter :authenticate_user!, except: [:index, :show]

後は、Indexの画面を出した時にNewボタンを表示しないようにする

ファイル:app/views/homes/index.html.erb
<% if user_signed_in? %>...<% end %>で囲むと、ログインしないとデータが出力されなくなる。

とりあえずこんな所です。今後サインアップ画面に名前とか住所とかの項目を追加したりする方法も今後考えていきたい。

携帯変えました…

朝起きたら、携帯の画面が血のような赤に染まっていました…

MBKに持って行ったんですが、どうも携帯の基板が腐食しているらしく 直すのは困難だという回答を頂きました…

というわけで、2年以上と人生で一番長く使った携帯になる ソニーエリクソンのXPERIA Arcともついにお別れです…

ソニーのAndroid携帯に完全に慣れてしまったので、 新しい携帯もソニーにしようと思い、 XPERIA Zに惹かれましたが、最終的には XPERIA ZRに決めました。

ただ、買った後に問題に気づいたんですが、 ケースがどこにも売っていない… やっぱソニーブランドはタイでは弱いな… ちまたにはサムスンかAppleしかない。頑張ってくれよ。ソニー…

日本では一番売れているXPERIA Aと同じタイプなので 日本の人にケースを買ってきてもらおうかと考えています。

でも、2年以上買い換えてなかったので、凄い快適 速い速い!!今までメールを取ったり送ったりするのも それなりに時間がかかっていたのですが、今は一瞬。 結構嬉しいです。

時間管理

今後の予定を組み立てる際に、時間管理は必須だと思っている。 時間管理に関して、シゴタノの記事(http://cyblog.jp/modules/weblogs/12501) で、L+PDCAという言葉を見た。これは凄いいい言葉だと思う。 とりあえずL(ログ)をひたすら取って、自分がどういう行動をしているのか どういう時間の使い方をしているのか具に観察してみる事が大事だと思う。

というわけで、とりあえず、これから1週間の行動を 観察する事にします。その際、利用するツールのリストを記載する事にします。

1.思考記録

何を考えたか、何を思ったかを記録するようにします。
僕はAndroid携帯(Sony XPERIA ZR)を利用しているので、
Google Keepを利用して、何を考えたか何を思ったかを記録します。
Evernoteでも良いんですが、ちょっと重いので、純粋な時系列なメモには
向いていないと感じます。

2.行動記録

ちょっと迷っているのですが、行動記録には、Toggl (http://www.toggl.com)を
利用して、行動の記録を取っていきます。そのTogglで取った行動記録を
LibreOfficeを使って編集するイメージです

行動の記録を1週間取って、今後どのように行動を改善していくか考えていきたいと思います。

ダイエット(というか生活習慣改善)

大学院に行っている2年間の間に、65キロから79キロまで体重が増加しました… 大学院が土日にあって、平日は仕事しているという状態で、平日に宿題やらプレゼンの準備で 深夜まで作業をしないといけないという状況にあった為、ストレスや夜更かしによって、 夜食やらお菓子やらをたくさん食べてしまった事で体重が増加してしまいました。

しかも、なぜかお腹だけポッコリと出ているメタボ肥満です。 今年の4月に卒業したのですが、その後ダイエットの為にやったことを記載します。

1.自分の状況を正確に知る。

4月卒業してから、5月のゴールデンウィークで1回日本の実家に帰りました。
その際、TANITAの体脂肪計付き体重計と、EPSONの手首式血圧計を買いました。
これを使って、体重・体脂肪率・血圧を毎日測ってExcelで付けていきました。

2.ジムと契約

職場の近くのジムと契約しました。ジムには平日の早朝に通うようにしました。
休日は予定が不安定で毎週通えるとは限らないので、それなら最初から休日に行かずに
平日だけ行くようにしました。早朝6時前に出ると、早朝ラッシュにも引っかからず
快適に通勤出来るというメリットもあります。ジムに行ってから、タバコも辞められたし、
運動には凄い効果があると認識しました。

3.何も約束が無い場合、夕食は控えめにする。

昼は普通に食べて、夕食は豆腐とかサラダをメインで炭水化物を取らないようにしています。
特に炭水化物ダイエット等は考えていませんが、豆腐もサラダも量は結構とっているので、
お腹いっぱい近くまで食べています。
なので、お腹が減って死にそうなんて事にはなっていません。

現状の成果

上記の事を開始してからだいたい3ヶ月くらい経ちました。
成果としては
体重79キロ→69キロ
体脂肪率29%→21%
血圧(上)137→118(日によってバラつきはありますが、昨日の値)
と十分に成果が出ています。個人的には元の65キロくらいまでは落としたいと思っています。

タスク管理手法

タスク管理手法について、僕はいろいろ試していますが、 今の方法は以下の手順になります。

概要

やり方としては、
1.仕事のタスク管理(Toodledoを利用)
2.個人のタスク(Any.Doを利用)
3.今やっているタスク(Togglを利用)
の3つに分けてタスクを管理しています。

1.仕事のタスク

仕事のタスクはToodledoで管理しています。
なぜToodledoで管理しているかというと、仕事のタスクは
ほとんどがPCを利用したタスクになりますので、
ブラウザで見れれば十分で、かつ細かい納期やらを設定したいので、
設定項目が多いToodledoを選んで利用しています。

2.個人のタスク

個人のタスクはAny.Doを利用しています。
個人のタスクは外出時の買い物リストや、
個人プロジェクト、その他個人で実行するタスクになりますので、
PCを使っている状態とは限りませんので、
携帯でデータを見れる必要があります。
その為、僕が使っているAndroidアプリのある
Any.Doを利用しています。

3.今やっているタスク

俗にいうDoingリストになりますが、これは定番アプリのTogglを利用しています。
これを登録しておくと、無意識にネットサーフィンをしてしまった場合、
それを認識して、すぐにDoingリストに書かれている
作業に戻る事が出来ますので必須だと思います。