Как оставаться сухим при использовании шаблонов Javascript и ERB (Rails) - PullRequest
8 голосов
/ 25 февраля 2011

Я создаю приложение Rails, которое использует Pusher для использования веб-сокетов для отправки обновлений непосредственно клиенту. В 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
});

Это хорошо, и все, кроме того, что я повторяюсь . Шаблон усов на 99% идентичен шаблонам ERB, которые я уже написал для рендеринга HTML с сервера. Предполагаемый результат / назначение шаблонов усов и ERB на 100% одинаковы: превратить объект твита в html твита.

Каков наилучший способ устранить это повторение?

ОБНОВЛЕНИЕ: Несмотря на то, что я ответил на свой вопрос, я действительно хочу увидеть другие идеи / решения от других людей - отсюда и награду!

Ответы [ 5 ]

5 голосов
/ 01 марта 2011

По моему мнению, самый простой способ сделать это - использовать AJAX для обновления страницы при создании нового твита. Для этого потребуется создать два файла, первый из которых будет стандартным файлом html.erb, а второй - файлом 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'). сверху). В противном случае он будет перенаправлен туда, куда вы хотите его отправить (в данном случае «Индекс» для твитов). Это, по моему мнению, самый СУЩЕСТВЕННЫЙ и самый ясный способ достичь того, что вы пытаетесь сделать.

3 голосов
/ 02 марта 2011

Я бы сделал все твиты с помощью 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();
});
3 голосов
/ 28 февраля 2011

На данный момент лучшее решение, которое я нашел, было Изотоп .

Позволяет писать шаблоны с использованием Javascript, которые могут быть обработаны как клиентом, так и сервером.

2 голосов
/ 01 марта 2011

Я не пробовал это, но это просто пришло мне в голову как возможное решение:

На ваш взгляд создайте скрытый div, который содержит пример шаблона (я использую HAML здесь для краткости):

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

Ваш частичный твит может отображать твит, как вы делаете сейчас.

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

При создании прототипа твита вы устанавливаете нужные поля в синтаксис замены js-шаблона,может определенно высушить это, но я включаю его здесь полностью для примера.

# 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..);

Последняя частьбудет зависеть от того, как вы будете создавать шаблоны, но это будет что-то вроде этого.

Как уже говорилось ранее, я не пробовал эту технику, и она не позволит вам делать такие вещи, как циклыили условное форматирование непосредственно в шаблоне, но я уверен, что вы можете обойти это с некоторой креативностью.

Это не так уж далеко от того, что вы хотите сделать с помощью изотопа, и во многих случаяхпути уступают, но этобезусловно, более простое решение.Лично мне нравится хамл, и я стараюсь писать как можно больше моих оценок, так что это будет лучшим решением для меня лично.

Надеюсь, это поможет!

1 голос
/ 21 июня 2012

Чтобы иметь возможность поделиться шаблоном между javascript и rails с шаблоном усов, есть smt_rails: https://github.com/railsware/smt_rails ("Шаблоны с общими усами для rails 3"), а также Пуаро: https://github.com/olivernn/poirot.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...