Ruby on Rails 3 でAjaxを扱うための基礎
方法
「:remote => true」によりlink,formをAjax化し、Ajax用のerbファイルを作成する。
- linkをAjax化
$ vi app/views/chapters/show.html.erb <%= link_to 'ツイート取得処理(Ajax化)', { :controller => 'chapters', :action => 'tweets' }, :remote => true %>
- Ajaxにより呼び出されるメソッドを修正
$ vi app/controllers/chapters_controller.rb # Ajax処理によるツイート取得のためのメソッド def tweets @tweets = Tweet.find_all_by_chapter_id(params[:id]) # ※ここでrenderで返却してしまうと、Ajax用のerbファイルが呼ばれなくなるので注意。 end
- Ajax用のerbファイル作成
- メソッド名.「html」.erbではなく、メソッド名.「js」.erbであるところがミソ。
$ vi app/views/chapters/tweets.js.erb $('#tweets').html( "<%= escape_javascript(@tweets.to_json) %>" );
- Ajaxで取得したデータを表示する領域をViewに作成
$ vi app/views/chapters/show.html.erb <div id='tweets'> </div>
参考サイト
- 特に無し
Ruby on Railsで独自のルーティングとメソッドを追加したい
やりたいこと
Ruby on Railsでresourcesを使用しない独自のルーティングと、それに対応するメソッドを追加したい。
方法
route.rbにおいてmemberブロックを使用してルーティング追加
- この例では各チャプター毎にツイートの一覧を返却する「tweets」ルーティングを追加
$ vi config/route.rb TestApplication::Application.routes.draw do resources :animes do resources :chapters do member do get 'tweets' end end end end
ルーティング確認
$ rake routes tweets_anime_chapter GET /animes/:anime_id/chapters/:id/tweets(.:format) chapters#tweets anime_chapters GET /animes/:anime_id/chapters(.:format) chapters#index POST /animes/:anime_id/chapters(.:format) chapters#create new_anime_chapter GET /animes/:anime_id/chapters/new(.:format) chapters#new edit_anime_chapter GET /animes/:anime_id/chapters/:id/edit(.:format) chapters#edit anime_chapter GET /animes/:anime_id/chapters/:id(.:format) chapters#show PUT /animes/:anime_id/chapters/:id(.:format) chapters#update DELETE /animes/:anime_id/chapters/:id(.:format) chapters#destroy animes GET /animes(.:format) animes#index POST /animes(.:format) animes#create new_anime GET /animes/new(.:format) animes#new edit_anime GET /animes/:id/edit(.:format) animes#edit anime GET /animes/:id(.:format) animes#show PUT /animes/:id(.:format) animes#update DELETE /animes/:id(.:format) animes#destroy
追加したルーティングに対応するメソッドを追加
- 上記で確認した通り、「tweet」ルーティングに対応するメソッドは「chapters#tweets」であるため、
Chapterコントローラーにtweetsメソッドを追加する。
$ vi app/controllers/chapters_controller.rb # GET /animes/1/chapters/1/tweets # GET /animes/1/chapters/1/tweets.json def tweets @chapter = Chapter.find(params[:id]) @tweets = @chapter.tweets respond_to do |format| format.html format.json { render json: @tweets } end end
参考サイト
- 特に無し
Ruby on Railsで親子関係にあるモデルのルーティング設定
やりたいこと
Ruby on Railsで親子関係にあるモデルのルーティングを設定したい。
方法
route.rbにおいてモデルを下記の様にネストさせる。
$ vi config/route.rb TestApplication::Application.routes.draw do resources :animes do resources :chapters end end
ルーティング確認
$ rake routes anime_chapters GET /animes/:anime_id/chapters(.:format) chapters#index POST /animes/:anime_id/chapters(.:format) chapters#create new_anime_chapter GET /animes/:anime_id/chapters/new(.:format) chapters#new edit_anime_chapter GET /animes/:anime_id/chapters/:id/edit(.:format) chapters#edit anime_chapter GET /animes/:anime_id/chapters/:id(.:format) chapters#show PUT /animes/:anime_id/chapters/:id(.:format) chapters#update DELETE /animes/:anime_id/chapters/:id(.:format) chapters#destroy animes GET /animes(.:format) animes#index POST /animes(.:format) animes#create new_anime GET /animes/new(.:format) animes#new edit_anime GET /animes/:id/edit(.:format) animes#edit anime GET /animes/:id(.:format) animes#show PUT /animes/:id(.:format) animes#update DELETE /animes/:id(.:format) animes#destroy
View修正
- アニメ詳細画面にて各話の一覧を表示し、ツイート件数を各話詳細画面へのリンクに設定
$ vi app/views/animes/show.html.erb 下記を追記。 <% @anime.chapters.each do |chapter| %> <tr> <td><%= chapter.chapter %></td> <td><%= chapter.title %></td> <td><%= chapter.start_time %></td> <td><%= chapter.end_time %></td> <td> <%= link_to chapter.tweets.count, anime_chapter_path(@anime, chapter) %></td> </tr> <% end %>
動作確認
- ヘルパーメソッドにより生成されたリンク先を確認
正常に各話詳細画面に遷移することを確認。
<%= link_to chapter.tweets.count, anime_chapter_path(@anime, chapter) %> ↓ <a href="/animes/3/chapters/3">0</a>
参考サイト
- Rails3のルーティングについて自分なりにまとめてみる
Ruby on Railsで子テーブルのデータをソートする方法
やりたいこと
Viewで@chapter.tweets的な感じで子テーブルのデータを一覧で表示する際にデータをソートしたい。
方法
親モデルのhas_manyにorder byを指定
$ vi app/models/chapter.rb class Chapter < ActiveRecord::Base has_many :tweets, :order => 'tweet_id DESC' belongs_to :anime attr_accessible :chapter, :end_time, :start_time, :title, :tweet_collect_end_flg, :tweet_collect_start_flg, :anime_id end
参考サイト
- railsでorder byしたいときのメモ
ActiveRecordをRails以外から使用する方法
やりたいこと
ActiveRecordをRails以外の普通のスクリプトとかから使いたい。
方法
スクリプトファイル内でRailsの設定系のファイルを読み込む。
#coding: utf-8 require 'active_record' require '/railsdir/config/boot' require '/railsdir/config/environment' config = YAML.load_file("/railsdir/config/database.yml") ActiveRecord::Base.establish_connection(config["development"]) p Anime.all
上記スクリプトを実行時にエラー発生
- エラー内容
WARN: Unresolved specs during Gem::Specification.reset: multi_json (~> 1.0) WARN: Clearing out unresolved specs. Please report a bug if this causes problems.
- gemの依存関係で怒られてるみたいなので、各パッケージの最新バージョン以外を削除。
$ sudo gem cleanup
参考サイト
- ActiveRecordを外部アプリケーション(rails以外)で使う
- [Rails] ActiveRecord を利用するバッチ
Ruby on Railsでアプリ全体にベーシック認証をかける方法
やりたいこと
Railsでアプリ全体にベーシック認証をかけたい。
方法
アプリ共通のコントローラーにベーシック認証の設定を追加
$ app/controllers/application_controller.rb class ApplicationController < ActionController::Base protect_from_forgery # 以下を追加 before_filter :auth private def auth authenticate_or_request_with_http_basic do |user,pass| user == 'user' && pass == 'pass' end end end
参考サイト
Ruby on RailsでDBにユニーク制約を付与する方法
やりたいこと
- RailsでDBにユニーク制約を付与したい。
方法
マイグレーションファイルを新規作成してユニークインデックスを追加
- ユニークインデックス追加用のマイグレーションファイルを作成
$ rails generate migration AddIndexAnimeIdAndChapterToChapters invoke active_record create db/migrate/20130429145932_add_index_anime_id_and_chapter_to_chapters.rb
- ユニークインデックス追加を設定
$ vi db/migrate/20130429145932_add_index_anime_id_and_chapter_to_chapters.rb class AddIndexAnimeIdAndChapterToChapters < ActiveRecord::Migration def change add_index :chapters, [:anime_id, :chapter], :unique => true end end
- マイグレーション実施
$ rake db:migrate == AddIndexAnimeIdAndChapterToChapters: migrating ============================ -- add_index(:chapters, [:anime_id, :chapter], {:unique=>true}) -> 0.0204s == AddIndexAnimeIdAndChapterToChapters: migrated (0.0207s) ===================
参考サイト
- Railsのユニーク制約の方法
- validates :uniquenessはuniquenessを保証しないのでDBにindexをつけましょう!
- Rails3 複数のカラムでユニーク
- rails3 generate migration add_columnとか