【问题标题】:How do I create a button that increments an attribute of a model and can be pressed once per browser?如何创建一个增加模型属性并且可以在每个浏览器中按下一次的按钮?
【发布时间】:2023-03-10 03:36:01
【问题描述】:

一个apartment_listing 有很多reviews,一个review 属于一个apartment_listing

在文件views/apartment_listings/show.html.erb 中,我显示了对该特定apartment_listing 的评论列表。这些评论是使用部分视图apartment_listings/_review.html.erb 生成的,如下所示:

<%= render :partial => "review", :collection => @apartment_listing.reviews %>

_review,我想要一个按钮,按下时:

  1. 评论的helpful_count 属性的增量。
  2. 使其无法在同一浏览器中再次按下 - 可能使用 cookie。

我觉得前者不应该太难弄清楚,但它让我打败了。我真的不知道从哪里开始第二个目标。


编辑:我设法用apartment_listings/_review.html.erb 中的代码更新了评论的helpful_count 属性:

<%= form_for review, :method => :put, :remote => true do |f| %>
  <%= f.hidden_field :helpful_count, value: (review.helpful_count + 1) %    > 
  <%= f.submit 'Helpful?' %>
<% end %>

但是,我不确定这是否是最好的方法,并且我希望能够在单击按钮后禁用它。

【问题讨论】:

    标签: ruby-on-rails ruby button cookies increment


    【解决方案1】:

    您用于更新helpful_count 的代码可能会出现问题。想象一下,两个用户在他们的网页上加载了一套公寓。其中一个标记它有帮助,下一个也标记它有帮助。由于他们最初加载页面时,helpful_count 是相同的,所以在他们俩都点击帮助后,计数只会增加一:它会更新两次为相同的值。

    确实,您想创建一个新操作,可能在公寓的评论资源下。该操作可以使用 ActiveRecord 的 increment 方法来更新 helpful_count(从技术上讲,increment! 中仍然存在竞争条件,您遇到的频率要少得多)http://apidock.com/rails/ActiveRecord/Persistence/increment%21

    对于后一个问题,Cookie 似乎是一个合理的解决方案。只需使用 jQuery 在表单上绑定提交,并在处理程序中创建 cookie。

    【讨论】:

    • 我绝对明白你在说什么。我想我这样做的主要障碍是我真的不确定如何创建一个可以在特定评论中调用 reviews_controller 中的方法的链接。
    • 你需要在 routes.rb 中新建一个路由来创建路径助手,然后执行:link_to path_helper_goes_here, :remote => true
    【解决方案2】:

    reviews 控制器中的代码是什么样的?更有经验的 RESTful 编码人员可能会更连贯地谈论这一点,但在我看来,增加 helpful_count 属性应该是发送到 reviews 控制器的操作。这样,您就可以创建一个异步执行操作的链接。

    比如在_review.html.erb里面:

    <% collection.each do |review| %>
    <%= link_to "Mark as Helpful", "/apartment_listing/#{@apartment_listing.id}/reviews/#{@review.id}/incHelpful?nonce=#{SecureRandom.rand(16)}", :remote => true, :method => :put %>
    # ... Do something cool with your review content ...
    <% end %> 
    

    在您的 ReviewController 类中:

    def incHelpful
      unless params[:nonce] == session[:nonce][params[:id]]
        @review = Review.find(params[:id])
        @review.helpful_count += 1
        @review.update_attributes(:helpful_count)
        session[:nonce][params[:id]] = params[:nonce]
      end
      render :nothing
      # Optionally return some javascript or JSON back to the browser on success/error
    end
    

    /config/routes.rb 内部:

    put "apartment_listing/:apart_id/reviews/:id/incHelpful" => "reviews#incHelpful"
    

    这里的主要思想是edit 资源的操作应使用PUT http 方法,并且该更改应由该资源的控制器处理。通过在 link_to 助手中设置 :remote =&gt; true 来使用 Rails 的内置 AJAX 功能。第二个概念是随机数,一个仅有效一次的随机值。一旦在用户会话中设置了此值,后续对incHelpful 的请求将不会执行任何操作。

    【讨论】:

    • 我喜欢你的代码,但它返回了一个 NoMethodError in Apartment_listings#show - private method rand' 调用 SecureRandom:Module`
    • 我用url safe_base64 替换了rand 并修复了这个错误,但现在我得到了一些非常奇怪的东西:未定义的方法`[]'对于 nil:NilClass
    • 抱歉,我在 Windows 机器上工作,所以无法验证代码。语法是SecureRandom.hex(16)
    • 就“no [] for nil:NilClass”而言,您必须在会话变量上设置一次 :nonce 键。我不是问如何做到这一点的最佳人选,因为我自己还在学习 Rails,session 商店对我来说有点神秘。我认为您可以在incHelpful 函数中为每个用户设置一次,如下所示:def incHelpful if session[:nonce].nil? session[:nonce] = {} end # ...
    • 伙计,这个错误不断出现。现在我得到了这个:wrong number of arguments (0 for 1) for incHelpful
    猜你喜欢
    • 2013-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-01
    • 1970-01-01
    • 2012-09-13
    相关资源
    最近更新 更多