Как организовать бизнес-логику и 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); });