在rails中,我想在点击投票按钮时处理视觉投票图标和数据库记录。看起来将这两个都放在一个权威位置(这样它们不会失去同步),而不是在不同文件中复制前端和后端的控制流逻辑似乎是个好主意。
有一些逻辑如下,我需要处理前端方面和后端方面。 他在轨道上做到这一点的最佳方法是什么?
有一项民意调查,有不同的选择。每个选项都有scope
个ID。
以下代码处理只允许一个选项的选项的直观投票行为。
控制器调用的模型方法
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=
使用acts_as_votable API在视图中有条件地设置类。使用CSS来设置'投票'
的样式控制器
def show
# can be moved to model
if current_user.voted_on? @votable
@voted = 'voted'
else
@voted = ''
end
我上面没有使用过ajax调用。我需要吗? 如果我使用ajax,上面的javascript似乎会很快变得非常混乱。 它也不会阻止多次投票,或者视觉投票与数据库中实际的投票不同步。
现在上面到目前为止重复了后端和前端的if / else控制流程。 但是将它们组合在一个js.erb文件中是否更好呢?
这就是为什么我认为将事物组合成一个处理正面和背面的js.erb可能会更好。但这似乎也不是好的设计。也许有一种方法可以使用ajax来进行更多验证并提高稳健性?无论如何,这都是不错的选择。只要它有效,那就很好。
似乎有一个自定义的js.erb文件不适合使用responds_with ...我很困惑。如何继续。
对于此问题中的多个问题,我们深表歉意。我只是想实现一个直观的投票系统,从不同来源获取信息并不容易。
提前致谢。
答案 0 :(得分:1)
这是一个非常通用的问题。对于后端来说,你可以使用一些宝石来做到这一点,因为它会让你的生活更轻松,例如 acts_as_votable gem for rails。
然后将其包含在您的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'
至于你的fronend,你可以发送一些类似于 link_to remote的Ajax请求: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); });