8

Pusherを使用してWebソケットを使用して更新をクライアントに直接プッシュするRailsアプリを構築しています。JavaScript の場合:

channel.bind('tweet-create', function(tweet){ //when a tweet is created, execute the following code:
  $('#timeline').append("<div class='tweet'><div class='tweeter'>"+tweet.username+"</div>"+tweet.status+"</div>");
});

これは、コードとプレゼンテーションの厄介な混合です。したがって、自然な解決策は、javascript テンプレートを使用することです。おそらくエコまたは口ひげ:

//store this somewhere convenient, perhaps in the view folder:
tweet_view = "<div class='tweet'><div class='tweeter'>{{tweet.username}}</div>{{tweet.status}}</div>"

channel.bind('tweet-create', function(tweet){ //when a tweet is created, execute the following code:
    $('#timeline').append(Mustache.to_html(tweet_view, tweet)); //much cleaner
});

これは良いことです。ただし、繰り返します。口ひげのテンプレートは、サーバーから HTML をレンダリングするために既に作成した ERB テンプレートと 99% 同一です。口ひげと ERB テンプレートの意図した出力/目的は 100% 同じです: ツイート オブジェクトをツイート html に変換します。

この繰り返しをなくす最善の方法は何ですか?

更新:私は自分の質問に答えましたが、他の人からの他のアイデア/解決策を見たいと思っています。

4

5 に答える 5

5

これを行う最も簡単な方法は、新しいツイートが作成されたときに AJAX を使用してページを更新することです。これには、2 つのファイルを作成する必要があります。1 つ目は標準の html.erb ファイルで、2 つ目は js.erb ファイルです。html.erb は、データベースから取得したすべてのツイートを反復して表示できる標準形式になります。js.erb ファイルは、作成時に新しいツイートを追加する単純な JavaScript になります。

$('#timeline').append("<div class='tweet'><div class='tweeter'><%= tweet.username %></div><%= tweet.status %></div>")

新しいツイートのフォームに次を追加する必要があります。

:remote => true

これにより、AJAXが有効になります。次に、作成アクションで、次のようなコードを追加する必要があります。

def create
...Processing logic...
  respond_to do |format|
    format.html { redirect_to tweets_path }
    format.js
  end
end

この例では、AJAX 対応のフォームでツイートを投稿すると、create.js.erb にあるコード (上記の $('#timeline').append コード) を実行して呼び出しに応答します。 . それ以外の場合は、送信したい場所にリダイレクトされます (この場合、ツイートの「インデックス」)。これは、あなたがやろうとしていることを達成するための最もドライで明確な方法です.

于 2011-03-01T18:36:29.223 に答える
3

これまでのところ、私が見つけた最良の解決策はIsotopeでした。

クライアントとサーバーの両方でレンダリングできる Javascript を使用してテンプレートを作成できます。

于 2011-02-28T01:49:26.203 に答える
3

すべてのツイートを Javascript でレンダリングします。サーバー上で HTML をレンダリングする代わりに、ページの先頭に初期データを JS として設定します。ページが読み込まれたら、JS でツイートをレンダリングします。

あなたの頭の中で:

%head
  :javascript
    window.existingTweets = [{'status' : 'my tweet', 'username' : 'glasner'}];

JS ファイル内:

$.fn.timeline = function() {
  this.extend({
    template: "<div class='tweet'><div class='tweeter'>{{tweet.username}}</div>{{tweet.status}}</div>",
    push: function(hash){
      // have to refer to timeline with global variable
      var tweet = Mustache.to_html(timeline.template, hash)     
      timeline.append(tweet);
    }
  });  

  window.timeline = this;

  channel.bind('tweet-create', this.push);  

  // I use Underscore, but you can loop through however you want
  _.each(existingTweets,function(hash) {
    timeline.push(hash);
  });

  return this
};  


$(document).ready(function() {
  $('#timeline').timeline();
});
于 2011-03-02T15:22:57.680 に答える
2

私はこれを試していませんが、これは可能な解決策として私に思い浮かびました:

ビューで、サンプル テンプレートを含む非表示の div を作成します (ここでは簡潔にするために HAML を使用しています)。

#tweet-prototype{:style => "display:none"}
    = render :partial => Tweet.prototype

ツイート パーシャルは、現在行っているようにツイートをレンダリングできます。

.tweet
    .tweeter
        = tweet.username
    .status
        = tweet.status

ツイートのプロトタイプを作成するときに、必要なフィールドを js-template 置換構文に設定すると、間違いなくこれが枯渇する可能性がありますが、例としてここに完全に含めています。

# tweet.rb
def self.prototype
    Tweet.new{:username => "${tweet.username}", :status => "${tweet.status}"}
end

クライアントでは、次のようにします。

var template = new Template($('#tweet-prototype').html());
template.evaluate(.. your tweet json..);

最後の部分は、テンプレートの作成方法によって異なりますが、そのようなものになります。

前に述べたように、私はこの手法を試したことはなく、ループや条件付き書式設定などをテンプレートで直接行うことはできませんが、創造性を働かせればそれを回避できると確信しています.

これは、Isotope を使用して実行しようとしているものとそれほどかけ離れたものではなく、多くの点で劣っていますが、間違いなくより単純なソリューションです。個人的に私は Haml が好きで、できるだけ多くのマークアップをそこに書き込もうとしているので、個人的にはこれがより良い解決策になるでしょう。

これが役立つことを願っています!

于 2011-03-01T18:56:04.703 に答える
1

javascriptとrailsの間で口ひげテンプレートを使用してテンプレートを共有できるようにするには、smt_rails:https ://github.com/railsware/smt_rails ( "Rails 3の共有口ひげテンプレート")とPoirot:https://githubがあります。 .com / olivernn/poirot

于 2012-06-21T13:15:27.847 に答える