Posts Tagged ‘Rails’

    はてなブックマーク - rails3.2でdeviseのインストール手順を間違えたら面倒だった話
    このエントリーをはてなブックマークに追加

    この前Rails3.1がリリースされたと思ったら、もうRails3.2です。
    バージョンが上がると、重宝して使っていたgemやプラグインが対応に追いつくのかが不安なんですが、その内のひとつ「devise」に関してのちょっとしたエントリーです。

    deviseとは

    github.com/plataformatec/devise

    deviseはシステムのログイン管理を担ってくれるRubyのパッケージです。
    ログイン認証が必要なシステムに対して、ユーザー登録・パスワードの暗号化・パスワードリセットなどの処理を担ってくれるので便利です。

    そのdeviseを使用したプロジェクトを作ります。
    Railsは3.2です。

    rails new sample

    で、プロジェクト作成。データベースも作成しておきます。

    Gemfileに、deviseに関する行を追加。

    gem 'devise'

    その後、本来は

    rails generate devise:install

    とすべきところを、

    rails generate devise user

    と、いきなりモデルの作成をしました。
    すると、

    /home/user/.rvm/gems/ruby-1.9.2-p180@rails32/gems/execjs-1.3.0/lib/execjs/runtimes.rb:50:in `autodetect': Could not find a JavaScript runtime. See https://github.com/sstephenson/execjs for a list of available runtimes. (ExecJS::RuntimeUnavailable)

    本編とは関係ないエラーが出てしまいました。
    JavaScriptのランタイムが無いと。
    Gemfileから

    # gem 'therubyracer'

    のコメントアウトを外します。

    で、再度

    rails generate devise user

    を実行。
    すると、必要なファイルが作成されます。
    そして、アプリを起動すると。。

    /home/user/.rvm/gems/ruby-1.9.2-p180@rails32/gems/devise-2.0.1/lib/devise/rails/routes.rb:406:in `raise_no_devise_method_error!':User does not respond to 'devise' method. This usually means you haven't loaded your ORM file or it's being loaded too late. To fix it, be sure to require 'devise/orm/YOUR_ORM' inside 'config/initializers/devise.rb' or before your application definition in 'config/application.rb' (RuntimeError)

    何か怒られました。
    ここで、「ああ、『rails generate devise:install』をしてなかった。。」と、インストールコマンドを実行。

    rails generate devise:install

    すると、

    /home/yama/.rvm/gems/ruby-1.9.2-p180@rails32/gems/devise-2.0.1/lib/devise/rails/routes.rb:406:in `raise_no_devise_method_error!': User does not respond to 'devise' method. This usually means you haven't loaded your ORM file or it's being loaded too late. To fix it, be sure to require 'devise/orm/YOUR_ORM' inside 'config/initializers/devise.rb' or before your application definition in 'config/application.rb' (RuntimeError)

    同じエラーです。どつぼにはまりかけです。

    エラーをよく読むと、
    config/initializers/devise.rb か、
    config/application.rb に、
    require 'devise/orm/YOUR_ORM' を書いてね、と言われているようです。
    どのO/Rマッパーを使うのかがわからないと起動できないみたいですね。
    なので、
    config/application.rb に

    require 'devise/orm/active_record'

    を記述後、インストールコマンドを実行。
    無事、必要なファイルが生成され、deviseを使えるようになりました。

    何事も順序どおりに、端折っちゃだめよというお話でした。

      はてなブックマーク - rails と jquery treeview でディレクトリツリーをらくらく実装する
      このエントリーをはてなブックマークに追加

      ども、Fusic 河野です。
      だいぶ久しぶりですね。

      今度の rubykaigi2011 に参加させて頂くこととなりました!
      会場で見かけたら、ぜひお気軽にお声をかけてくださいませ。

      [rubykaigi2011]
      rubykaigi.org/2011/

      それと、もう一つ告知です。
      来る7月28日(木)、福岡で活動している Androidの会福岡支部九州GTUG
      HTML5+α福岡iDevQ、そして、AppleKnight の4つのコミュニティが
      福岡県Ruby・コンテンツ産業振興センターに集結し、同時に勉強会、懇親会を行います。

      ご興味のある方は、ぜひともご参加ください!!
      参加登録は下記のリンク先より facebook にて参加表明をお願いいたします。

      [futuresync]
      futuresync.jp/

      さて、わたくし、前回の記事でも書きましたが、主に ruby on rails を
      やっており、ZENPRE の iPhone アプリを担当させていただいてます。

      今回とあるお客様の rails 案件にて、ツリービューを作る必要がありました。
      一から作ろうかと思っていたところ、jquery ui の treeview を見つけ、
      使ってみたので、簡単なサンプルとともにご紹介をします。

      いやー、それにしてもコレ凄く便利です!!

      まずは、バージョン確認です。

      $ ruby -v
      ruby 1.9.2p0 (2010-08-18 revision 29036) [i686-linux]
       
      $ rails -v
      Rails 3.0.9

      rails のプロジェクトを作成します。

      $ rails new treeview_test
      $ cd treeview_test/
      $ rm public/index.html

      prototype.js を削除ります。
      サヨナラ〜、お元気で〜♪

      $ vim Gemfile
       
      gem 'jquery-rails'
       
      $ rails g jquery:install

      ツリービューを表示するためのコントローラを作成します。

      $ rails g controller Treeviews index
      $ vim routes.rb
       
        root :to => "treeviews#index"

      そして、本日の主役のご登場!
      jquery treeview を下記よりダウンロードします。
      bassistance.de/jquery-plugins/jquery-plugin-treeview/

      js や css、jpg などを rails の各ディレクトリにコピーします。
      画像は、images に “treeview” というディレクトリを
      作成し、そこにコピーしています。
      そして、jquery.treeview.css に記載されている画像のパスを
      ちょっと変更します。

       images/xxxx → ../images/treeview/

      treeview を取り込みます。

      $ vim app/views/layouts/application.html.erb
       
      <!DOCTYPE html>
      <html>
      <head>
        <title>TreeviewTest</title>
        <%= stylesheet_link_tag :all %>
        <%= javascript_include_tag :defaults %>
        <%= javascript_include_tag 'jquery.treeview' %>
        <%= javascript_include_tag 'jquery.treeview.edit' %>
        <%= javascript_include_tag 'jquery.treeview.async' %>
        <%= csrf_meta_tag %>
      </head>
      <body>
       
      <%= yield %>
       
      </body>
      </html>

      ツリービューを表示するため view を書き換えます。

      $ vim app/views/treeviews/index.html.erb
       
      <script type="text/javascript">
      $(document).ready(function(){
        $("#example").treeview({});
      });
      </script>
       
      <ul id="example" class="filetree">
      	<li><span class="folder">Folder 1</span>
      		<ul>
      			<li><span class="file">Item 1.1</span></li>
      		</ul>
      	</li>
      	<li><span class="folder">Folder 2</span>
      		<ul>
      			<li><span class="folder">Subfolder 2.1</span>
      				<ul>
      					<li><span class="file">File 2.1.1</span></li>
      					<li><span class="file">File 2.1.2</span></li>
      				</ul>
      			</li>
      			<li><span class="file">File 2.2</span></li>
      		</ul>
      	</li>
      	<li class="closed"><span class="folder">Folder 3 (closed at start)</span>
      		<ul>
      			<li><span class="file">File 3.1</span></li>
      		</ul>
      	</li>
      	<li><span class="file">File 4</span></li>
      </ul>

      完成です!!
      いやー、ほんとめちゃくちゃ簡単ですね!!
      まー、これだけだと寂しいのとせっかくの rails も意味がないので
      rails にディレクトリ一覧を返す関数を作成し、ajax 使って
      ディレクトリ階層を動的に表示できるように変更します。
      おー!rails っぽいですね!

      routes にパスを追加します。

      $ vim config/routes</code>
       
        match '/treeviews/get_dir_list' => 'treeviews#get_dir_list'

      さっきの view を書き換えます。

      $ vim app/views/treeviews/index.html.erb
       
      <script type="text/javascript">
      $(document).ready(function(){
        $("#example").treeview({});
        $("#example2").treeview({
      		url: "<%= treeviews_get_dir_list_path %>"
        });
      });
      </script>
       
      <h4>通常のツリービュー表示</h4>
       
      <ul id="example" class="filetree">
      	<li><span class="folder">Folder 1</span>
      		<ul>
      			<li><span class="file">Item 1.1</span></li>
      		</ul>
      	</li>
      	<li><span class="folder">Folder 2</span>
      		<ul>
      			<li><span class="folder">Subfolder 2.1</span>
      				<ul>
      					<li><span class="file">File 2.1.1</span></li>
      					<li><span class="file">File 2.1.2</span></li>
      				</ul>
      			</li>
      			<li><span class="file">File 2.2</span></li>
      		</ul>
      	</li>
      	<li class="closed"><span class="folder">Folder 3 (closed at start)</span>
      		<ul>
      			<li><span class="file">File 3.1</span></li>
      		</ul>
      	</li>
      	<li><span class="file">File 4</span></li>
      </ul>
       
       
      <h4>sync させたツリービュー表示</h4>
      <ul id="example2" class="filetree"></ul>

      treeview の url に先ほど routes に追加したパスを記載します。

      controller もゴニョゴニョと追加します。

      $ vim app/controllers/treeviews_controller.rb
      class TreeviewsController < ApplicationController
       
        def index
        end
       
        def get_dir_list
          root_flg = (params["root"] == "source") ? true : false
          path = "./"
          path = params["root"] unless root_flg
          arry = []
          d = dir_list(path, arry)
          render :json => arry || [], :layout => false
        end
       
      protected
        def dir_list(path, arry=[], root_flg=false)
          Dir.glob("#{path}/*").map do |d|
            classes = "file"
            classes = "folder" if FileTest.directory?(d)
            hasChildren = (FileTest.directory?(d)) ? true : false
          	h = {"id" => d, "text" => File.basename(d), "path" => File.dirname(d), "expanded" => false, "classes" => classes, "hasChildren" => hasChildren, "children" => []}
            arry << h
          end
          arry
        end
       
      end

      dir_list() の関数でディレクトリ情報の hash を作成し、view 側に json で返します。
      返された json を treeview 側が解析してツリービューを表示します。
      返す hash の id のところがミソでして、ここにパスを記載していると
      treeview にてディレクトリを選択された場合、params["root"] に選択された
      ところのパスが渡されます。
      一番上のルートの場合には、params["root"] には、”source” という文字が渡ってきます。

      今回もいつもの如くソースは github にあげてます。
      また、サンプルをここに置いてますので実際の動作を確認できます。
      今回始めて dotcloud を使ってみました。
      これまためちゃくちゃ便利ですねー!
      dotcloud で rails を動かす方法とかは、また次回にでも、デモ。

      それでは、良い rails ライフを〜。

      [ソース]
      github.com/sora0513/TreeViewTest

      [デモ]
      8befe980.dotcloud.com/

        はてなブックマーク - [Rails] TZInfoで、アクセス元のタイムゾーンに合わせる
        このエントリーをはてなブックマークに追加

        前略、ヤマモトです。

        みなさんはウェブサービスを立ち上げる際、タイムゾーンは意識されているでしょうか。
        日本国内のみのサービスであれば、時間帯は1つなので特に意識する必要はないと思いますが、
        これが全世界で利用して欲しいサービスであれば話が変わります。

        日本時間で「午後1時から午後2時まで限定公開」というプレミアコンテンツを予告し、全世界に公開したとしても、日本時間であると注釈しない限り、ユーザーはその地域の時間だと捉えるでしょう。
        「見てみたらまだ始まってなかった」ならまだいいでしょうが、日本は、全世界でも先の時間を行ってますから、ほとんどの地域の人からしたら「見てみたら終わってた」状態ですね。

        話は逸れますが、アメリカのような複数のタイムゾーンがある国では、ウェブサービスの時間の処理はどう行っているんでしょうか。
        いや、ウェブサービスに限らず、例えばテレビ番組は、ニューヨークでは午後7時から放送でも、サンフランシスコでは午後4時からとなるので、
        この場合の宣伝の仕方はどうしているんでしょうね。
        恐らく時間帯の注釈があるんでしょうが、アメリカに知り合いはいないのでちょっと謎です。
        YouTubeやFacebookといった全世界向けウェブサービスを見てみましたが、
        アメリカのプロキシ経由でアクセスしたり、言語設定を「英語」にしてアクセスしたりしても、とくに時間に変化はなさそうでした。

        かといって、タイムゾーンを考慮しない実装はできません。
        というのは、自社サービスであるZENPREの話ですが、これにはプレゼンテーションの開始時間と終了時間という概念があり、
        その間でしかリアルタイムな配信はされません。
        つまり、その地域に合った時間を表示しないと、世界中の人が見ることはできません。

        1番の解決策は、ユーザーにタイムゾーンを設定してもらうことでしょう。
        初めてアクセスがあった場合、必ずタイムゾーンの設定をしてもらう。
        あとはcookieにでも保存しておいて次回以降は、そのタイムゾーンを使う。
        ですが、その機構を作るための期間が取れず、また、果たしてそれが最適解だろうかというのもあったため、実装を見送りました。

        さて、かなり前置きが長くなってしまいましたが、
        ユーザーのタイムゾーンを取得するにあたって、自動で取得するため「TZInfo」というRubyのライブラリを使用することにしました。

        TZInfo – Ruby Timezone Library

        TZInfoは、国コードから該当するタイムゾーンを表示してくれます。
        例えば日本の場合、

        tz = TZInfo::Country.get("JP")
        tz.zone_identifiers # "Asia/Tokyo"

        となります。
        国コードの取得は

        Locale.get.country

        でできます。
        これを、application_controller.rbあたりで

        Time.zone = tz.zone_identifiers[0]

        とすれば、タイムゾーンが動的に設定できます。
        ※tz.zone_identifiersは配列

        ただし、これがタイムゾーンが複数ある地域になると問題です。

        tz = TZInfo::Country.get("US")
        tz.zone_identifiers
        ⇒America/New_York America/Detroit America/Kentucky/Louisville America/Kentucky/Monticello America/Indiana/Indianapolis ... America/AdakPacific/Honolulu

        となり、候補が複数取得できます。
        ここから、その地域を特定するのは不可能かと思います。
        現状では、「複数取得されたら、1番目のタイムゾーンを選択する」ことにしました。
        さらに、時間表示の部分には全て、現在適用されているタイムゾーンを表示することで、時間誤認のリスクを減らしています。

        現在のタイムゾーンを表示するメソッド

        Time.zone.now.zone"JST"
        ※日本の場合

        以上が、タイムゾーンを自動で取得する方法です。
        Railsは、DBへ時刻を格納するとき、どの地域であろうとも標準時間でセットしてくれるので、
        このようなカスタマイズも容易です。

        ただし、これが最適解ではないので、何からしらの別の方法が見つかればと思います。