ラベル Ruby の投稿を表示しています。 すべての投稿を表示
ラベル Ruby の投稿を表示しています。 すべての投稿を表示
2014/12/09

Ruby on Rails 開発環境構築 in Mac OS X Mavericks

久しぶりに Ruby on Rails で開発することになり、開発環境を再構築しました。
関連: Mac OSX10.8でrbenvを使ってRuby1.9とRails4.0をインストールする

HomeBrew を使用するので MacPorts の人は読み替えてください。
また、僕は zsh を使っているので bash の人も読み替えてください。
HomeBrew や zsh をインストールしようという人は以下の事が参考になるかと思います。
Homebrew + Homebrew-caskで Mac の開発環境を構築する | DevAchieve
MacにHomeBrewとzshを導入してみた | DevAchieve

rbenv と ruby-build のインストール

brew install rbenv
brew install ruby-build
# rbenv の初期化
eval "$(rbenv init -)"
source .zshrc
eval "$(rbenv init -)" で rbenv へのパスを通すのとコマンドの補完や引数の処理、rehash をしています。
echo "$(rbenv init -)" で処理内容を確認できます。

rehashとは、
rbenv -h で確認すると以下のように書かれています。
rehash: Rehash rbenv shims (run this after installing binaries)
gem とか入れたらやれってことでいいのだと思います。
gem を入れまくると重くなる?のか rehash が重くなることがあるらしいです。
猫好きモバイルアプリケーション開発者記録 rbenv init が重い問題に対する対処法
gem を(アン)インストールしたら自動で rehash してくれる gem があるのでこれを入れておくと良いかも。
ryansouza/rbenv-rehash - github

依存パッケージのインストール

brew install readline
brew link readline
brew install openssl
brew link openssl

Ruby をインストールする

CONFIGURE_OPTS="--with-readline-dir=/usr/local --with-openssl-dir=/usr/local" rbenv install 2.1.5
CONFIGURE_OPTS="--with-readline-dir=/usr/local --with-openssl-dir=/usr/local" rbenv install まで
入力して Tab で補完すればバージョンを指定できます。

rehash して使用するバージョンを指定する

rbenv rehash
rbenv global 2.1.5

バージョンを確認する

rbenv version
2.1.5 (set by /Users/wada/.rbenv/version)
ruby -v
ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin13.0]

gem 管理システム bundler のインストール

Ruby のライブラリである gem をパッケージ管理できる Bundler をインストールします。
gem install bundler
基本的にシステムにgemをインストールせず、
bundler でプロジェクトごとに gem をインストールするのが環境をクリーンに保てて良いとされています。
Rails も bundler でインストールしたいと思います。

Rails をインストールする

% mkdir project
% cd project
% bundle init
Writing new Gemfile to /path/to/project/Gemfile
Rails プロジェクト作成する際にbundle initして Gemfile を作成します。
# A sample Gemfile
source "https://rubygems.org"

# gem "rails"
4行目のコメントアウトを外して以下のコマンドを実行すれば rails をインストールできます。
bundle install --path vendor/bundle
他の gem を追加するときも上のコマンドでプロジェクト内にインストールします。

bundle exec rails new .
bundler でインストールした gem は
プロジェクトのディレクトリで bundle exec を付けてコマンドを実行する必要があります。

参考
Ruby - システムのgemにrailsをインストールせずrails newする - Qiita

libiconv is missing. で gem install nokogiri が失敗する場合

Homebrew で libiconv とその依存パッケージをインストールします。
### For nokogiri
brew tap homebrew/dupes
brew install libiconv
brew install libxml2
brew install libxslt
brew link --force libxml2
brew link --force libxslt

nokogiri をインストールします。
gem install nokogiri -- --use-system-libraries
Bundler を使用している場合は以下のコマンドを実行します。
bundle config build.nokogiri --use-system-libraries
bundle install

参考
Ruby - bundle install でnokogiriをインストールしろと言われる - Qiita
OSX - Mac OS X Mavericksで”gem i nokogiri”失敗の解決方法 - Qiita
2013/08/19

Rails4のMass Assignment脆弱性対策のStrong Parametersについて

Mac OSX10.8でrbenvを使ってRuby1.9とRails4.0をインストールする
ひょんなことから Rails4 をインストールしてしまった俺達は
attr_accessibleattr_protectedを使わずに
Strong Parameters を使うことになってしまっていた!
ActionController::StrongParameters
rails/strong_parameters

初めての Rails で右も左も分からない状況で
いきなり Strong Parameters と言われてもよくわからないので以下についてまとめます。

Mass Assignment とは

Rails ではこんなコードをよく見ると思います。
def create
  @user = User.new(params[:user])
  unless @user.save
    render 'new'    
  end
end
Userモデルにnameemailという属性が設定されていて、
params[:user]{name: 'willnet', email: 'willnet@example.com'}のような
パラメータが入っていたとき、上記のUser.new(params[:user])で一度にnameemail
設定されます。これが mass assignment です。属性が多いときなど大変便利です。
Rails4.0に含まれる strong_parameters について - willnet.in

Mass Assignment 脆弱性

先ほどの例ではnameemailという属性が設定されていました。
この2つの属性の他に、システム側で自動で割り振られるtokenという属性が存在したとします。
tokenはユーザには変更させたくありません。

さて、 それではUser#nameUser#emailを変更するための
update アクションを書いてみましょう。
edit の view には name と email を変更するための text_field だけが存在するとします。
def update
  @user = User.find(params[:id])
  unless @user.update_attributes(params[:user])    render 'edit'&
  end
end
上記のコードは基本的にはうまく動くはずです。ただしユーザが普通にブラウザを使う限りは。
  • chromeのデベロッパーツールなどで
    <input type="text" name="user[token]" value="hoge" />などのタグを
    form中に生成してsubmitする
  • curlやtelnetなどで直接user[token]=hogeのようなリクエストを、
    通常のリクエストに追加して送信する
上記のような方法を使った場合、ユーザに編集させたくないtoken属性が更新されてしまいます。
これが mass assignment の脆弱性と呼ばれるものです。
Rails4.0に含まれる strong_parameters について - willnet.in

Rails4 以前の Mass Assignment 脆弱性対策

attr_accessibleattr_protectedが提供されていました。
Rails2系(および3.0)だと後述のroleが設定できないため、
User#nameだけ更新したい場合とUser#nameとUser#email両方を更新させたい場合の
2種類があるケースなど、同じモデルに複数種類の mass assignment 脆弱性対策をかけたくなります。
Rails4.0に含まれる strong_parameters について - willnet.in
Rails 3.1以上からはattr_accessibleattr_protectedに role という機能が導入されました。
class User < ActiveRecord::Base
  attr_accessible :name
  attr_accessible :name, :email, as: :name_and_email
end
as オプションで role の名前を指定して、
@user.update_attributes(params[:user], role: 'name_and_email')
のように role オプションで適用したいattr_accessible(もしくはattr_protected)を指定します。
role がない場合はデフォルトのもの(上記のケースはattr_accessible :name)が使用されます。

これにより大分きちんと書けるようになったのですが、
多くの role を定義する必要があるとやや煩雑になります。
Rails4.0に含まれる strong_parameters について - willnet.in
role の設定が煩雑になった結果(?)、
GitHub、Mass Assignment利用の脆弱性を突かれるという事例が発生したので
この煩雑な role 設定の管理をしなくてはいけない状況をどうにかするべく
Strong Parameters が導入されたようです。

Rails4 の Mass Assignment 脆弱性対策の Strong Parameters について

rails generate scaffold user name:string email:string
scaffold を使用すると、Strong Parameters の機能を使用したコードが生成されます。
class UsersController < ApplicationController
  ...
  # POST /users
  # POST /users.json
  def create
    @user = User.new(user_params)
    ...
  end
  ...
  private
  ...
    # Never trust parameters from the scary internet, only allow the white list through.
    def user_params
      params.require(:user).permit(:name, :email)
    end
end
このコードは「params が :user というキーを持ち、params[:user] は :name 及び :email というキーを持つハッシュであること」を検証します。

例えば、params[:user]{:name => 'taro', :email => 'taro@example.com'}のようなハッシュである場合に検証 OK となります。
» Rails4 の Strong Parameters でリクエストパラメータを検証する TECHSCORE BLOG

許可していないパラメータが渡された場合はデフォルトでは無視される

試しに user_params の内容を以下のように修正してみます。
# Never trust parameters from the scary internet, only allow the white list through.
    def user_params
      # 試に :email の指定を消す.
      # params.require(:user).permit(:name, :email)
      params.require(:user).permit(:name)
    end
この状態で再度ユーザ登録を行うと、リクエストパラメータとして名前(name)とメールアドレス(email)が渡されますが、メールアドレス(email)は無視されます。

ログを確認すると以下のようなメッセージが出力されていました。
Unpermitted parameters: email
» Rails4 の Strong Parameters でリクエストパラメータを検証する TECHSCORE BLOG

許可しないパラメータが渡された場合に例外を発生させる

許可しないパラメータが渡された場合の動作は config/application.rb で変更することができます。

試に例外を発生させるように変更してみます。
# デフォルトは :log で, 許可されていないパラメータは無視されたうえでログ出力されます.
config.action_controller.action_on_unpermitted_parameters = :raise
この状態で再びユーザ登録を行うと(リクエストパラメータに name と email が渡されると)、ActionController::UnpermittedParameters という例外が raise されました。
» Rails4 の Strong Parameters でリクエストパラメータを検証する TECHSCORE BLOG

ネストしたパラメータ

Strong Parameters のドキュメントを読むと、permit メソッドの引数を以下のように指定することで、
ネストしたパラメータに対応することができるようです。
params.permit(:name,
              {:emails => []},
              :friends => [:name,
                           {:family => [:name]}])
» Rails4 の Strong Parameters でリクエストパラメータを検証する TECHSCORE BLOG

全てのパラメータを許可する

開発中のときなど、全ての属性を許可したいケースがあると思いますが、
その時はparams[:user].permit!のようにします。
ただ、permit!が今のバージョン(0.1.4)だと再帰的に効かないという話しがあるので
(RailsCastsで言ってた。未確認)、うまくいかない場合は github 上の最新を使ってみてください。
Rails4.0に含まれる strong_parameters について - willnet.in

参考

Rails4.0に含まれる strong_parameters について - willnet.in
» Rails4 の Strong Parameters でリクエストパラメータを検証する TECHSCORE BLOG

参考というより引用元です。
どちらの記事も読み返したくなる記事内容で Chrome のタブを閉じることができなかったので
内容の9割以上が引用でしたが、記事にすることでタブを閉じることができそうです。
Rails やるときにまた見に行くと思います。
どちらもわかりやすい記事をありがとうございます。
2013/07/30

MVCモデルにおけるModelの関係性とRailsでのアソシエーションの設定

Rails を勉強中です。学んだことをちょっとずつまとめていきたいと思います。
誤りがあれば教えていただけると幸いです。

アソシエーションって何?

日本語訳すると、「つながり」とか「関係性」とか訳される。
MVCフレームワークを使うと出てくるアソシエーションは、モデル同士の関係性のこと。
すごく大雑把に言えば、テーブルの JOIN の繋ぎ方のこと。たぶん合ってる。

なぜアソシエーションが必要なのか?

設定しておくと Rails では JOIN を明示的に書かなくても SELECT できたり、
紐付いたデータを一緒に削除できたり、色々とフレームワークの支援を得られる。
何故アソシエーションなの?(Why Associations?) - Active Record Associations - 株式会社ウサギィwiki
Active Record Associations — Ruby on Rails Guides

MVC モデルにおける Model の関係性

  1. 1対1関連(has_one, belongs_to)
  2. 経由モデルありの1対1関連(has_one :through)
  3. 1対多関連(has_many, belongs_to)
  4. 中間テーブルに属性ありの多対多関連(has_many :through)
  5. 中間テーブルに属性なしの多対多関連(has_and_belongs_to_many)
  6. ポリモーフィック関連(has_many :as)
Rails での主なアソシエーションの種類は上記の6つ。
ちゃんと理解するために身近なサンプルを作ってみることにした。

1対1関連(has_one, belongs_to)

User - Blog
上記のような 1 User に 1 Blog というブログサービスを想定したアソシエーションの設定は以下のようになる。
class User < ActiveRecord::Base
    has_one :blog
end
class Blog < ActiveRecord::Base
    belongs_to :user
end
has_one アソシエーション - Active Record Associations - 株式会社ウサギィwiki
belongs_to アソシエーション - Active Record Associations - 株式会社ウサギィwiki
The belongs_to Association - Active Record Associations — Ruby on Rails Guides
The has_one Association - Active Record Associations — Ruby on Rails Guides

経由モデルありの1対1関連(has_one :through)

User - Blog - Setting
User から Blog を通して Setting にアクセスするような3つのモデルの直線的な関係性は以下のように設定する。
class User < ActiveRecord::Base
    has_one :blog
    has_one :setting, through: :blog
end
class Blog < ActiveRecord::Base
    belongs_to :user
    has_one :setting
end
class Setting < ActiveRecord::Base
    belongs_to :blog
end
has_one :through アソシエーション - Active Record Associations - 株式会社ウサギィwiki
The has_one :through Association - Active Record Associations — Ruby on Rails Guides

1対多関連(has_many, belongs_to)

Category - Article
1 カテゴリに複数の記事、1 記事に 1 カテゴリという関係性を定義したい場合は以下のように設定する。
class Category < ActiveRecord::Base
    has_many :article
end
class Article < ActiveRecord::Base
    belongs_to :category
end
has_many アソシエーション - Active Record Associations - 株式会社ウサギィwiki
The has_many Association - Active Record Associations — Ruby on Rails Guides

中間テーブルに属性ありの多対多関連(has_many :through)

Blog - Reader - User
中間テーブルが属性(理論的な意味でのカラムのこと)を持つ際の多対多の関連性は以下のように定義する。
class Blog < ActiveRecord::Base
    has_many :readers
    has_many :users, through: :readers
end
class Reader < ActiveRecord::Base
  belongs_to :user
  belongs_to :blog
end
class User < ActiveRecord::Base
    has_many :readers
    has_many :blogs, through: :readers
end
has_many :through アソシエーション - Active Record Associations - 株式会社ウサギィwiki
The has_many :through Association - Active Record Associations — Ruby on Rails Guides

中間テーブルに属性なしの多対多関連(has_and_belongs_to_many)(HABTM)

Article - Tag
中間テーブルが属性を持たず、2つのテーブルの関係性の情報しか持たない場合は以下のように定義する。
class Article < ActiveRecord::Base
    has_and_belongs_to_many :tags
end
class Tag < ActiveRecord::Base
    has_and_belongs_to_many :articles
end
has_and_belongs_to_many アソシエーションの規約
  • 中間テーブルを作成しなければならない。
  • 中間テーブルのテーブル名は参照先のテーブル名を辞書順に「_」で連結しなければならない。(※)
  • 中間テーブルの主キー列を無効化しなくてはならない。
  • 中間テーブルの外部キー列は「参照先のモデル名_id」の形式にしなければならない。
  • 中間テーブルのタイムスタンプ列を削除しなくてはならない。
※ 両方のモデルの has_and_belongs_to_many アソシエーションの指定の後に
join_table でテーブル名を指定すれば任意のテーブル名を指定することができる。
rails g migration CreateArticlesTags でマイグレーションファイルが生成されるので
上記の規約に従い、以下のように修正する。
class CreateArticlesTags < ActiveRecord::Migration
  def change
    create_table :articles_tags, :id => false do |t|
      t.references :article, index: true
      t.integer :article_id
      t.references :tag, index: true
      t.integer :tag_id
    end
  end
end
has_and_belongs_to_many アソシエーション - Active Record Associations - 株式会社ウサギィwiki
The has_and_belongs_to_many Association - Active Record Associations — Ruby on Rails Guides
[Rails]中間テーブルを使って他テーブルの情報を参照する - has_and_belongs_to_many (m:n) のケース
has_and_belongs_to_many アソシエーションのための結合テーブルの作成 - 株式会社ウサギィwiki
Creating Join Tables for has_and_belongs_to_many Associations — Ruby on Rails Guides

ポリモーフィック関連(has_many :as)

Blog - Article
 └ Picture ┘
あるモデルが1つ以上の他のモデルに属する場合、以下のように定義する。
class Blog < ActiveRecord::Base
    has_many :pictures, as: :imageable
end
class Article < ActiveRecord::Base
    has_many :pictures, as: :imageable
end
class Picture < ActiveRecord::Base
    belongs_to :imageable, polymorphic: true
end
polymorphic アソシエーション - Active Record Associations - 株式会社ウサギィwiki
Polymorphic Associations - Active Record Associations — Ruby on Rails Guides

参考

ruby/rails/RailsGuidesをゆっくり和訳してみたよ/Active Record Associations - 株式会社ウサギィwiki
Active Record Associations — Ruby on Rails Guides
2013/07/13

Mac OSX10.8でrbenvを使ってRuby1.9とRails4.0をインストールする

ついに僕も Ruby on Rails での開発デビューしてみることになったので
Ruby on Rails 環境構築のメモを残しておきます。

HomeBrew を使用するので MacPorts の人は読み替えてください。
また、僕は zsh を使っているので bash の人も読み替えてください。
HomeBrew や zsh をインストールしようという人は以下の事が参考になるかと思います。
MacにHomeBrewとzshを導入してみた | DevAchieve

rbenv と ruby-build のインストール

brew install rbenv

brew install ruby-build

vi .zshrc
# rbenv の初期化
eval "$(rbenv init -)"
source .zshrc
eval "$(rbenv init -)" で rbenv へのパスを通すのとコマンドの補完や引数の処理、rehash をしている。
echo "$(rbenv init -)" で処理内容を確認できる。

rehashとは、
rbenv -h で確認すると以下のように書かれている。
rehash: Rehash rbenv shims (run this after installing binaries)
gem とか入れたらやれってことでいいのだろうか。
gem を入れまくると重くなる?のか rehash が重くなることがあるらしい。
猫好きモバイルアプリケーション開発者記録 rbenv init が重い問題に対する対処法
gem を(アン)インストールしたら自動で rehash してくれる gem があるのでこれを入れておくと良いかも。
ryansouza/rbenv-rehash - github

依存パッケージのインストール

brew install readline

brew link readline

brew install openssl

brew link openssl

Ruby をインストールする

CONFIGURE_OPTS="--with-readline-dir=/usr/local --with-openssl-dir=/usr/local" rbenv install 1.9.3-p194
CONFIGURE_OPTS="--with-readline-dir=/usr/local --with-openssl-dir=/usr/local" rbenv install まで
入力して Tab で補完すればバージョンを指定できる。
とりあえず Ruby1.9 の最新版のパッチが当てられた(p の後の数字が大きい)バージョンをインストールした。
Ruby2.0 も候補に出たけど 2.0.0-dev しか表示されなかったのでインストールはやめておいた。
MacにRuby2.0とRails4をインストール - Qiita [キータ]

rehash して使用するバージョンを指定する

rbenv rehash
rbenv global 1.9.3-p194

バージョンを確認する

rbenv version
1.9.3-p194 (set by /Users/wada/.rbenv/version)
ruby -v
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin12.4.0]

Rails をインストールする

gem list -r --all rails
*** REMOTE GEMS ***

rails (4.0.0, 3.2.13, 3.2.12, 3.2.11, 3.2.10, 3.2.9, 3.2.8, 3.2.7, 3.2.6, 3.2.5, 3.2.4, 3.2.3, 3.2.2, 3.2.1, 3.2.0, 3.1.12, 3.1.11, 3.1.10, 3.1.9, 3.1.8, 3.1.7, 3.1.6, 3.1.5, 3.1.4, 3.1.3, 3.1.2, 3.1.1, 3.1.0, 3.0.20, 3.0.19, 3.0.18, 3.0.17, 3.0.16, 3.0.15, 3.0.14, 3.0.13, 3.0.12, 3.0.11, 3.0.10, 3.0.9, 3.0.8, 3.0.7, 3.0.6, 3.0.5, 3.0.4, 3.0.3, 3.0.2, 3.0.1, 3.0.0, 2.3.18, 2.3.17, 2.3.16, 2.3.15, 2.3.14, 2.3.12, 2.3.11, 2.3.10, 2.3.9, 2.3.8, 2.3.7, 2.3.6, 2.3.5, 2.3.4, 2.3.3, 2.3.2, 2.2.3, 2.2.2, 2.1.2, 2.1.1, 2.1.0, 2.0.5, 2.0.4, 2.0.2, 2.0.1, 2.0.0, 1.2.6, 1.2.5, 1.2.4, 1.2.3, 1.2.2, 1.2.1, 1.2.0, 1.1.6, 1.1.5, 1.1.4, 1.1.3, 1.1.2, 1.1.1, 1.1.0, 1.0.0, 0.14.4, 0.14.3, 0.14.2, 0.14.1, 0.13.1, 0.13.0, 0.12.1, 0.12.0, 0.11.1, 0.11.0, 0.10.1, 0.10.0, 0.9.5, 0.9.4.1, 0.9.4, 0.9.3, 0.9.2, 0.9.1, 0.9.0, 0.8.5, 0.8.0)

...etc
Rials のバージョンを確認する。他にも色々表示されたが省略。
最近、 Rails4.0 が公開された。
rbenv exec gem install rails
rbenv exec gem install rails -v 3.2.13 等でバージョンを指定してインストールできる。たぶん。
指定しないと最新の 4.0.0 がインストールされる。

インストールしたので rehash する

rbenv rehash

バージョンを確認する

rails -v
Rails 4.0.0

Rails プロジェクトを作成する

rails new proj
cd proj

開発を開始する

俺達の開発はまだまだこれからだ!

参考:
Ruby on Rails 3.2 を Mac OS X にインストールする手順をかなり丁寧に説明してみました - Rails 雑感 - Ruby on Rails with OIAX
【初心者向け】Mac OSX10.8(Mountain Lion)で Ruby on Railsを動かすための5ステップ « pplog.org
Rails開発環境の構築(rbenvでRuby導入からBundler、Rails導入まで) - Qiita [キータ]
MacにRubyをインストールする時のメモ - Qiita [キータ]

タグ(RSS)