How to limit the number of votes in 'acts_as_votable' gem - ruby

I'm currently using the rubygem acts_as_votable as the voting system in my project, but I want to limit the total votes of every user (which I used rubygem devise)
The target of the vote is a model called Pin:
class Pin < ActiveRecord::Base
acts_as_votable
end
Should I use a method and put it in the before_action: to make sure that the vote your making won't let your total votes exceed say like 10?
Updated: 8/18/2015
Now I popped up with a new question:
I created another model group, and declaim the relationship:
(group.rb)
has_many: pins
(pin.rb)
belongs_to: group
So, here comes up the question, if I want to limit the votes in every group, say like: 10 in group 1, 10 in group 2, 10 in group 3....
How can I accomplish it?

You can do something like this:
def upvote
#pin = Pin.find(params[:id])
# check for user's total votes
if current_user.find_voted_items.size < 10
#pin.vote_by :voter => current_user
else
..... #your code
flash[:notice] = "your total votes exceed"
redirect_to pins_path
end
end

Related

Take total price from all product for many users

i have issue
Model Driver has association like has_many: orders
class Driver < User
has_many :orders
end
and Order has belongs_to :user
class Order < ActiveRecord::Base
belongs_to :user
end
and Order has column like price
My problem is, i want to display all drivers by table
first column will be first_name, next last_name,
i want to display total price for each users. price will be counting by summing by all orders for user,
Problem is n+1, how i can display total price for each user, without sent separate request to the DB
Example of index page
first_name.
last_name
Price
Arian
Lain
2500
Brain
Kokun
4700
You can get a sum for grouped values using a single SQL query with SUM and GROUP BY. In Rails, this can look like this:
#sums = Order.group_by(:user_id).sum(:price)
# {1 => 2500, 2 => 4700, ...}
In your view, you can then fetch the sum for the respective user using the user's id as a key, e.g. with this (assuming you have the current driver / user in the driver variable):
<%= #sums[driver.id] %>

Rails 5: Insert/Update only if there's no filled specific field for that id

I have a Followups table with the fields: patient_id, death_date (and other fields..).
There could be multiple records for the same patient_id but there must be only one death_date for that patient_id.
A unique index won't work as the user could insert two different death_date.
Which is the best way to achieve this in Rails 5?
If possible, please make an example.
Thanks
You could do this with a callback on the Followup model:
Assuming a Patient has_many :followups
class Followup
belongs_to :patient
validate :check_for_existing_death_date
private
def check_for_existing_death_date
# This will grab the first one if any with a death date exist
# This also assumes that the patient_id and patient exist
followup = patient.followups.where("death_date IS NOT NULL").take
# if you want to raise an error...
if followup
errors.add(:death_date, 'There is already a death date for this patient')
return false
end
# If not, do something with the data
# if followup
# self.death_date = nil # or followup.death_date if you want it saved on followups as well
# end
end
end
I would think that the best way to do this would be to store the death_date on the Patient record, since death only happens once per patient.

How does one get a list of facebook campaign impressions and budget per campaign with ruby?

I have the following code that returns a list of names of all campaigns that I have in my Facebook business manager account using facebook-ruby-business-sdk.
require 'facebookbusiness'
FacebookAds.configure do |config|
config.access_token = '_____private_info______'
config.app_secret = '_____private_info______'
end
ad_account = FacebookAds::AdAccount.get('act______private_info______', 'name')
puts "Ad Account Name: #{ad_account.name}"
# Printing all campaign names
ad_account.campaigns(fields: 'name').each do |campaign|
puts campaign.name
end
The campaign object in the final loop is an instance of FacebookAds::Campaign.
Rather than just having a list of names, I also need budget and impressions for each campaign in the last month.
How do I need to change the code to get these results?
It looks to me as if you just need to select the fields and they'll be available in your loop:
ad_account.campaigns(fields: %w[name budget impressions]).each do |campaign|
puts [campaign.name, campaign.budget, campaign.impressions].join(', ')
end
Does that work for you? Let me know how you get on or if you have any questions.

How can I get all the responses by a particular user to posts on a particular topic

I have a user, a micropost and a response model.
The user has many microposts and has many responses.
Microposts have tags using the acts as taggable gem.
I need to find the number of responses a user has, to microposts that are tagged with a specific tag. To be clear, for example, how many responses has user 1 given to microposts on "exercise"
There is some basic ruby syntax and relationship logic I am missing. This is what I haev in my user model.
def user_responses_on_topic tag
microposts = self.microposts.tagged_with(tag, :on => :tags)
responses_count = 0
microposts.each do |micropost|
count = micropost.responses.where("user_id = :user_id", user_id: self.id).size
responses_count = responses_count + count
end
end
Its giving me a value but I know its wrong because when I add responses on a particular topic the users value doesn't increase.
I am sure there is a simple "ruby" way to get at this using
responses = user.microposts.responses
But I need to know how to get the tagged logic on microposts into this code
I have tightened it up a bit but still not luck. The individual components of this code work but I can't get the whole thing to work together
def user_responses_on_topic(interest)
microposts = Micropost.tagged_with(interest, :on => :tags, :any => true)
responses ||= 0
microposts.each do |micropost|
responses += micropost.responses.where("user_id = :user_id", user_id: self.id).size
end
end
EDIT:
This works
def user_responses_on_topic(interest)
microposts = Micropost.tagged_with(interest, :on => :tags, :any => true)
count = 0
microposts.each do |micropost|
responses = micropost.responses.size
count = count + responses
end
count
end
But there's got to be a better Rails way (this smells of PHP)
Any ideas?
If all of the components are working independently, it might be as simple as adding a line to the end of your method: responses. After the .each loop executes, it returns the original array (not the value you modified within the loop). Since you want to return the number stored in responses, you want that variable to be the last line of your method.
You should be able to do the count in a single query like this:
microposts.tagged_with(tag, on: :tags).joins(:responses).where(responses: {user_id: id}).count

Simplify multiple calls to ActiveRecord #find down to single line/SQL statement

I'm having a little brain block when it comes to condensing the use of two #find methods in ActiveRecord down to a single statement and SQL query.
I have a Sinatra route where the slug of both a parent and child record are supplied (the parent has many children). Atm I'm first finding the parent with a #find_by_slug call and then the child by #find_by_slug again on the matched parents association.
This results in two SQL queries that in my mind should be able to be condensed down to one easily... Only I can't work out how that's achieved with ActiveRecord.
Model, route and AR log below. Using ActiveRecord 3.2
Edit
I realised I need to clarify the exact outcome to require (I write this very late in the day). I only require the Episode but atm I'm getting the Show first in-order to get to the Episode. I only require the Episode and figured their must be a way to get at that object without adding the extra line and getting the Show first.
Model
class Show < ActiveRecord::Base
has_many :episodes
end
class Episode < ActiveRecord::Base
belongs_to :show
end
Sinatra route
get "/:show_slug/:episode_slug" do
#show = Show.find_by_slug show_slug
#episode = #show.episodes.find_by_slug episode_slug
render_template :"show/show"
end
ActiveRecord logs
Show Load (1.0ms) SELECT `shows`.* FROM `shows` WHERE `shows`.`slug` = 'the-show-slug' LIMIT 1
Episode Load (1.0ms) SELECT `show_episodes`.* FROM `show_episodes` WHERE `show_episodes`.`show_id` = 1 AND `show_episodes`.`slug` = 'episode-21' LIMIT 1
If you only need the #episode, you can maybe do
#episode = Episode.joins(:shows).where('shows.slug = ?', show_slug).where('episodes.slug = ?', episode_slug).first
If you also need #show, you've got to have two queries.

Resources