-1

Hi I am new to web development and have chosen Ruby on Rails as an entry point in developing web apps.

I recently came across a site called Rappler which implements a mood meter. I have been searching for months for a gem or tutorial on how to implement a voting system with multiple choice but deactivates the other choices once one of the choices has been selected. I also would like to allow visitors to vote and would like to find out how I can limit their vote to 1 vote per article via IP address or session.

Tried to look at thumbs_up and act_as_votable gems but these gems don't seem to be the right fit for the problem I am trying to fix for my blog.

Thanks in advance for helping.

2 Answers 2

0

This is multiple questions in one which is usually a bad format for Stackoverflow. I can give you some hints. Start something and then come back with specific questions

I suggest you build this your own instead of using an existing solution. There is a lot to be learnt...

Deactivate other options

Just build a form with radio buttons. They make sure that you can only submit one value. If this is not what you like for design wise:

This could be done solely on the client via Javascript. Use a event handler, perhaps on the change or submit event.

Then you could write something into cookies to prevent the same user from voting again (this does not add real security as i could empty my cookies and vote again or use a script to trigger the vote action)

One vote per IP

This you can solve on the model level. Add a IP attribute. Make sure it is unique in combination with the foreign key to the rated blog post. Then use

vote = @post.votes.find_or_initialize_by(ip: request. remote_ip)

That being said: IP is not unique, depending on how your readers access the net they might share an IP. The only real way to prevent double voting is to require a login.

1
  • Thanks for taking the time to answer the question
    – Fide
    Commented Apr 26, 2016 at 11:58
0

Haven't looked recently regarding new gems that might feature what you want, but if you don't mind building your own, I suggest implementing it RESTful.

Start by adding a model

class SelectedMood < ActiveRecord::Base
  # has the following attributes
  # session_id:string:index
  # mood_id:integer

  validates :session_id, uniqueness: true
end

Then each of your mood will be a button (you may want transparent buttons) having the following:

<%= button_to selected_moods_path(selected_mood: {mood_id: CHANGE_MOOD_ID_HERE, session_id: session.id}), remote: true, method: :post do %>
  <%= image_tag 'mood1.png' %>
<% end %>

Then the buttons will be a POST to a create method of your SelectedMoodsController

class SelectedMoodsController < ApplicationController
  def create
    @selected_mood = SelectedMood.new(selected_mood_params)
    @selected_mood.save

    render js: "alert('Thanks for selecting a mood!');"
  end

  def selected_mood_params
    params.require(:selected_mood).permit(:session_id, :mood_id)
  end
end

I used save! above instead of the normal save intentionally.

The implementation above still is missing error-handling and reporting, but you should have an idea now on where to start.

You may or may not want a separate Mood model for all mood options.

As for the IP address, it is not very accurate to have uniqueness validation because if you're browsing through a phone over 3G, all of the phones connected will share the same IP, as it is the cellular tower's IP which has the one single public IP, and our phones just have different internal IP. For sessions, it is also still not very accurate because one can do multiple incognito browser sessions just to spam-click on a mood, because all of these incognito sessions have different sessions.

1
  • Thanks JayAr. Will try your recommendation. I will be using oauth as the blog I will implement this feature is for an intranet application. I will try using g+ profile for voters.
    – Fide
    Commented Apr 26, 2016 at 12:31

Not the answer you're looking for? Browse other questions tagged or ask your own question.