Как организовать бизнес-логику и js-логику для голосования в Rails?

В рельсах я хочу обрабатывать визуальные значки голосования и запись базы данных после нажатия на кнопку голосования. Похоже, что было бы неплохо иметь оба из них в одном официальном месте (чтобы они не синхронизировались), вместо того, чтобы дублировать логику потока управления для внешнего и внутреннего интерфейса в разных файлах.

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

Есть опрос, и есть разные варианты. Каждому варианту дается scope Я бы.

Следующий код обрабатывает интуитивное поведение при голосовании для опции, которая допускает только одну опцию.

метод модели, вызываемый контроллером

if current_user voted_for? @votable
  @votable.unvote_by current_user
  @votable.vote_by current_user, scope: params[:vote_type] unless current_user voted_for? @votable, scope: params[:vote_type]
else
  @votable.vote_by current_user, scope: params[:vote_type]
end

Теперь это хорошо для задней части, и мне нужен интерфейс.

файл актива javascript

// Detect if record was voted for by current user, obtain #id 
  // add class 'voted' to child with matching #id

$('#poll .option').on(click, ->

  if ($('this').first().class('voted') ) {
    $('this').first().removeClass('voted');
  } else if ( $('this').siblings('option').first().class('voted') ){
    $('this').siblings('option').first().removeClass('voted');        
  } else {
    $('this').first().addClass('voted');
  }

Будет ли это работать правильно с рельсами remote: true ссылка на сайт?

html.haml

#poll
  = link_to (content_tag :div, class: @voted), vote_path(:vote_type)
  = link_to "", vote_path(vote_type: "2"), class=

Использование API act_as_votable для условного задания класса в поле зрения. Используйте CSS для стилизации "проголосовал"

контроллер

def show
  # can be moved to model

  if current_user.voted_on? @votable
    @voted = 'voted'
  else
    @voted = ''
  end

конец

Я не использовал ajax-вызовы выше. Нужно ли мне? Приведенный выше javascript выглядит очень быстро, если я использую ajax. Это также не мешает многократному голосованию или визуальным голосам, не синхронизированным с тем, что фактически находится в базе данных.

Теперь вышеприведенное пока дублирует поток управления if / else в задней и передней частях. Но лучше ли объединить их в файл js.erb, где он делает оба?

Вот почему я подумал, что было бы лучше объединить вещи в один js.erb, который обрабатывает как спереди, так и сзади. Но это тоже не похоже на хороший дизайн. Возможно, есть способ использовать ajax, чтобы добавить больше проверок и повысить надежность? Во всяком случае, это все просто хорошо иметь. Пока это работает, это хорошо.

Кажется, наличие собственного файла js.erb не подходит для использования откликов с... Я запутался. о том, как продолжить.


Извините за несколько вопросов в этом вопросе. Я просто пытаюсь внедрить интуитивно понятную систему голосования, и мне не очень легко получать кусочки информации из разных источников.

Заранее спасибо.

1 ответ

Решение

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

Затем включите его в свою модель ActiveRecord:

class Record < ActiveRecord::Base
  acts_as_votable
end

Теперь вы сможете использовать множество вспомогательных методов, таких как:

@record = Record.create!(attributes)
@record.liked_by @user1
@record.downvote_from @user2
@record.vote_by :voter => @user4, :vote => 'bad'
@record.vote_by :voter => @user5, :vote => 'like'

Что касается вашего друга, вы можете отправлять некоторые запросы Ajax, например, link_to remote: true или form_for remote: true. Затем вы можете использовать RJS или даже делать это вручную на стороне клиента с помощью jQuery и изменять состояние div.

Я продемонстрирую здесь код:

В Контроллере у вас будет что-то вроде:

def vote
  @record = Record.find(params[:post_id])
  @record.liked_by current_user
end

Html

<%= link_to 'like', vote_path(@record), class: 'vote', remote: true %>

JS

$('.vote')
  .on('ajax:send', function () { $(this).addClass('loading'); })
  .on('ajax:complete', function () { $(this).removeClass('loading'); })
  .on('ajax:success', function (data) { $(this).html(data.count); });
Другие вопросы по тегам