ラベル jquery の投稿を表示しています。 すべての投稿を表示
ラベル jquery の投稿を表示しています。 すべての投稿を表示

2011年9月18日日曜日

rails3.1時代のautocompleteは(一部駄目だし)

railsを始めて触った時は、圧倒的に簡単に利用できるautocomplete機能に驚かされたものです(あ~懐かしい。。)。
あるバージョンからautocompleteはplugin側に外れたのですが、rails3時代にはどのplugin(gem)が利用されているんでしょうか?
rails3.1からはjqueryが標準になったので、rails3 - jquery - autocompleteという切り口で探してみました。
すると、そのまんまなgemがありました。
https://github.com/crowdint/rails3-jquery-autocomplete

■インストール

Gemfileに
gem 'rails3-jquery-autocomplete'

でinstall
$ bundle install

次にコード生成して
rails generate autocomplete:install

# generatorのrails3.1対応はまだみたいなのでautocomplete-rails.jsは、public/assets/javascripts
# に手動コピーしましょう。

jsを読み込みましょう
javascript_include_tag "autocomplete-rails.js"

application.jsでjquery-uiを読み込む用にしましょう。
//= require jquery-ui

後defaultではcssがしょんぼりなので、public/assets/stylesheetsに
https://raw.github.com/crowdint/rails3-jquery-autocomplete-app/master/public/stylesheets/jquery-ui-1.8.2.custom.css
をおきましょう。

■利用方法
controllerに
class ProductsController < Admin::BaseController
  # モデル名、フィールド名
  autocomplete :brand, :name
end

routes.rbに
resources :products do
  get :autocomplete_brand_name, :on => :collection
end

最後にviewに
<%= form_for @product do |f| %>
  <%= f.autocomplete_field :brand_name, autocomplete_brand_name_products_path %>
<% end %>

ね、(そこそこ)簡単でしょう!

■いくつか残念な点

調べてみて感じた残念な点
  1. rails3.1対応はまだ
  2. rspec-request用のサポートが欲しい
  3. label/valueに適応されるmethodが同じ
  4. term以外の動的要素に対応できない
ぼやいててもしょうがないので、やれる事はやろう(続く)

2011/09/18 上記4に対応してみました。https://github.com/kennyj/rails3-jquery-autocomplete
gem 'rails3-jquery-autocomplete', :git => git://github.com/kennyj/rails3-jquery-autocomplete.git
で使えると思います。

2011/09/18 上記1にも対応してみました(rails3.1 branch) 上記に, :branch => 'rails3.1' を追加すると利用できるはずです。

2011/09/19 上記2はspec_helper.rbで、require 'steak/autocomplete' して、config.include Steak::Autocomplete, :type => :request すればrspec-requestsでも動きました。

2011年7月28日木曜日

backbone.jsがいつのまにかpjax対応していた

■概要

年初にbackbone.jsの調査をしていた頃は、ajaxで画面遷移を行うには、fragmentを利用する事しかできませんでした。

しかし0.5以降では、Backbone.Routerを利用する事によって、pjax(HTML5のpushStateを利用した話題のあれ)な画面遷移が出来るになっています。

pjaxについては、こちらをご参照ください。
またgithubのファイルブラウザはpjaxの良例として有名なのでチェックしてみて下さい。


■何処がpjaxなのか?

まずは下記手順を実施後、http://localhost:3000/を閲覧してみましょう。chrome等html5対応ブラウザで確認して下さい。


次にhelpをクリックしてみましょう。

注目すべきなのは、
①URLが変わっている
②画面下部のレンダリング日時が変わっていない。

次にaboutをクリックしてみましょう。helpの時と同じです。

ブラウザの「戻る」ボタンをクリックしてみましょう。
About => Help => Indexに遷移します。「進む」ボタンもいい感じに遷移します。

次にHelpが画面に表示されている状態で、「F5」を押下してみましょう。
レンダリング日時が変わったはずです。


■説明

ajaxは非同期に(高速に)画面の一部を書き換える技術ですが、ユーザーの利便性の観点から、ブラウザの戻る、進むを利用可能にする必要があります。これまでのajaxでは、#(フラグメント)を利用して実現する事が多かったのですが、あまり良い解決策では有りませんでした。

pjaxでは、HTML5のpushStateを利用する事により、ブラウザのURLを切り替えつつ、画面の一部のみ切り替える事ができます。無論、URLは通常のURLですので、「通常のHTTPリクエスト」として処理するように実装する事が可能です。下記のIndexControllerでは、Ajax通信かどうかでレイアウトの適用を変更しています。
これができたら何が嬉しいのか?!それは読者への宿題にしておきます(^.^;

ちなみに、IE(≒pushStateをサポートしていないブラウザ)でみたら fragment での遷移に自動的に切り替わってました。。

■体験手順

・まずは前回の記事を参考にプロジェクトを生成する。

$ ./gen.sh pjax

・移動して体験に必要なファイルを用意する

$ cd pjax

app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title>pjax2</title>
    <meta charset="utf-8"/>
    <%= stylesheet_link_tag :all %>
    <%= javascript_include_tag :defaults %>
    <%= javascript_include_tag :backbone %>
    <script><%= yield :javascripts %></script>
    <%= csrf_meta_tag %>
  </head>
  <body>
    <%= content_for?(:content) ? yield(:content) : yield %>
  </body>
</html>

app/views/layouts/index.html.erb

<%= content_for :javascripts do %>
$(function() {
  var Workspace = Backbone.Router.extend({
    routes: {
      "":      "index",
      "help":  "help",
      "about": "about"
    },
    index: function() {
      $("#app").load("/");
    },
    help: function() {
      $("#app").load("/help");
    },
    about: function() {
      $("#app").load("/about");
    }
  });
  var ws = new Workspace();
  Backbone.history.start({pushState: true});

  $("#indexButton").click(function() {
    ws.navigate("", true);
  });
  $("#helpButton").click(function() {
    ws.navigate("help", true);
  });
  $("#aboutButton").click(function() {
    ws.navigate("about", true);
  });
});
<% end %>

<%= content_for :content do %>
  <div id="app"></div>
  <hr/>
  <input type="button" name="index" value="index" id="indexButton" />
  <input type="button" name="help"  value="help"  id="helpButton" />
  <input type="button" name="about" value="about" id="aboutButton" />
  最終レンダリング日時:<%= I18n.l Time.now %>
<% end %>

<%= render :file => "layouts/application" %>

app/views/index/index.html.erb

<h1>Index</h1>

app/views/index/help.html.erb

<h1>help</h1>

app/views/index/about.html.erb

<h1>about</h1>

app/controllers/index_controller.rb

class IndexController < ApplicationController
  layout "index"
  def index
    render :layout => !request.xhr?
  end
  def help
    render :layout => !request.xhr?
  end
  def about
    render :layout => !request.xhr?
  end
end

config/routes.rb

最後に
root :to      => "index#index"
match "help"  => "index#help"
match "about" => "index#about"

public/index.html <= 削除

サーバ起動!
$ rails server

2011年1月26日水曜日

rails3とbackbone.jsの組み合わせで利用する2

■概要

前回に引き続き、backbone.jsを利用してjqueryでMVCの世界を、rails3と共に作っていこうと思います。
今回はデータのやり取りをする所までが目標です。

■モデル/コントローラ等を作成する

$ rails g scaffold post title:string body:text published:boolean
$ rake db:migrate
$ rake spec (とりあえずrspecが動くか確認しとく)
$ rake spec:rcov (ついでにrcovが動くか確認しとく)
$ rails s

ここで http://localhost:3000/posts でいつもの画面が表示されてればOK!

■json入出力用にコントローラを修正する

とりあえずjsonでやり取りできるように変更します。params.exceptはbackboneとのやり取りを考慮してます。

class PostsController < ApplicationController
  respond_to :json
  def index
    @posts = Post.all
    respond_with @posts
  end
  def show
    @post = Post.find(params[:id])
    respond_with @post
  end
  def create
    @post = Post.new(params.except(:action, :controller))
    respond_to do |format|
      if @post.save
        format.json { render :json => @post, :status => :created, :location => @post }
      else
        format.json { render :json => @post.errors, :status => :unprocessable_entity }
      end
    end
  end
  def update
    @post = Post.find(params[:id])
    respond_to do |format|
      if @post.update_attributes(params.except(:id, :action, :controller, :created_at, :updated_at))
        format.json { head :ok }
      else
        format.json { render :json => @post.errors, :status => :unprocessable_entity }
      end
    end
  end
  def destroy
    @post = Post.find(params[:id])
    @post.destroy
    respond_to do |format|
      format.json { head :ok }
    end
  end
end

■jsonのフォーマットを変更する

このままだと下記の用に"post"が付いてしまうので、backbone側の期待と異なります。

http://localhost:3000/posts.json
=> [{"post":{"body":"a","created_at":"2011-01-19T16:13:47Z","id":1,"published":false,"title":"aa","updated_at":"2011-01-19T16:13:47Z"}}]

http://localhost:3000/posts/1.json
=> {"post":{"body":"a","created_at":"2011-01-19T16:13:47Z","id":1,"published":false,"title":"aa","updated_at":"2011-01-19T16:13:47Z"}}


config/initializers/include_root_in_json.rbの様なファイルを作成し

ActiveRecord::Base.include_root_in_json = false

とすると下記の様な感じでgoodです!

http://localhost:3000/posts.json
=> [{"body":"a","created_at":"2011-01-19T16:13:47Z","id":1,"published":false,"title":"aa","updated_at":"2011-01-19T16:13:47Z"}]

http://localhost:3000/posts/1.json
=> {"body":"a","created_at":"2011-01-19T16:13:47Z","id":1,"published":false,"title":"aa","updated_at":"2011-01-19T16:13:47Z"}

■backbone用のcontorollerを作成

コントローラ/ビューを追加して必要な設定を追加します。

$ vim controllers/home_controller.rb

class HomeController < ApplicationController
  def index
  end
end

$ vim config/routes.rb
  root => "home#index"
$ rm public/index.html
$ mkdir views/home

■backbone.jsを使ってみる

$ vim views/home/index.html.erb



http://localhost:3000/ を開いて、画面に味気ないalertが表示されればOkay!!
railsのログとDB見てると少しは楽しいかも

次は画面を作っていきましょう!

2011年1月11日火曜日

rails3とbackbone.jsの組み合わせで利用する1

■概要
backendをrails3にして、backbone.jsを利用する為の手順を残しておきます。

■railsプロジェクトの作成
$ rails new demo -T -J -d mysql
demo プロジェクト名
-T testunitはいらない
-J prototype.jsはいらない
-d mysql データベースはmysql

■gemを追加
$ cd demo
$ vim Gemfile
下記を一番下に追加(本当はバージョンをつけた方が良い)
gem 'jquery-rails'
group :development, :test do
  gem 'rspec'
  gem 'rspec-rails'
  gem 'rcov'
end
$ bundle install

■コードジェネレート
$ rails g rspec:install
$ rails g jquery:install --ui

■まず使えるように編集
$ vim config/database.yml

$ vim app/views/layouts/application.html.erb
文字列エンコーディングを明確に指定する為に下記追加
<meta charset="utf-8"/>

$ vim config/application.rb
jquery-railsに、javascriptのdefaults設定はまかせる(コメントアウトする)
# config.action_view.javascript_expansions[:defaults] = %w()
これを有効にしたい

$ vim spec/spec_helper.rb

ruby1.9.2でrcovを正しく動作させる為に、下記を一番下に追加
# quick monkey patch for rcov
# http://codefluency.com/post/1023734493/a-bandaid-for-rcov-on-ruby-1-9
if defined?(Rcov)
  class Rcov::CodeCoverageAnalyzer
    def update_script_lines__
      if '1.9'.respond_to?(:force_encoding)
        SCRIPT_LINES__.each do |k,v|
          v.each { |src| src.force_encoding('utf-8') }
        end
      end
      @script_lines__ = @script_lines__.merge(SCRIPT_LINES__)
    end
  end
end

$ vim .rspec
spork等で動いてもいい様に下記を追加しておく
--drb

■backbone.jsの準備
$ cd public/javascripts
↓jsファイル取得。ここも本当はバージョンを明示すべきかな
$ wget http://documentcloud.github.com/underscore/underscore.js
$ wget http://documentcloud.github.com/underscore/underscore-min.js
$ wget http://documentcloud.github.com/backbone/backbone.js
$ wget http://documentcloud.github.com/backbone/backbone-min.js
$ cd ../..
$ vim app/views/layouts/application.html.erb
backbone.jsを読み込むようにする。下記をhead内に追加
<%= javascript_include_tag "underscore-min.js", "backbone-min.js" %>

■履歴管理開始
$ vim .gitignore (履歴管理しない最低限のものを追加)

.bundle
db/*.db
db/*.sqlite3
db/schema.rb
log/*.log
tmp/
coverage/
*.swp

$ git init
$ git add .
$ git commit -m "最初のコミット"

■DB作成
$ rake db:create:all
$ rake db:migrate

■起動
$ rails s

ここまでで準備完了!次は実際にデータの操作をしてみます

20110113 追記
http://d.hatena.ne.jp/nedate/20101004/1286183882を参考にrcovの設定も追加させてもらいました!