I am creating a rails app that checks whether a user follows an artist on spotify. I have the following code to check if this is the case.
def personalise(acts)
acts_with_rank = acts.collect{|act|{:value => rank(act), :label => act.name}}
end
def rank(act)
spotify_user = RSpotify::User.new(request.env['omniauth.auth'])
artist = RSpotify::Artist.search(act.name).first
binding.remote_pry
if spotify_user.follows?(artist)
10
else
0
end
end
The problem is, every act ends up with 10 as its value in the hash, regardless of whether or not the user is actually following the artist. I am using remote-pry to check whether or not true or false is returned for each iteration of the if statement, and although it is correctly returning true or false depending on whether or not the user is following the artist, something else seems to make the if statements return 0. Any help would be appreciated on this as I'm sure I'm just looking at this for too long and can't see something stupid that I've done!
Just figured out what was going wrong
spotify_user.follows?(artist)
returns an array of booleans, to access the boolean of interest here, the simple fix was:
if spotify_user.follows?(artist)[0]
10
else
0
end
Related
i think i used the right terminology for what i need, i currently have a database call in my home_controller that is returning a call to my database with all the entries in that table specified, Freelancer.
There is an attribute on these records that has either a true or false value, which is "featured".
I need a way to call a sort method, or some other way, on that object with the true being first and then the false being afterwards, i tried using this code
def index
#freelancers = Freelancer.all
p 'below im outputting featured freelancer i hope'
#freelancers.sort_by { |row| [row.featured ? 0 : 1, row.id]}
p #freelancers
end
But unfortunately this did not work, can anyone advise me on a way to get this to work? Id rather have the sorted object returned as is, rather then assigning it to a new one. Just for future features of adding pagy and a filter by cost.
Use order method
def index
#freelancers = Freelancer.order(featured: :desc)
end
I have a complicated scope where I'm grabbing a checklist. In this checklist there are a bunch of tasks under difference categories. I only want the completed checklists, but some of the checklists will be complete without every category being finished. So I need to be able to check if each column is needed before checking if the column has anything in it. Here's my example.
scope :complete, lambda {|check_lists| check_lists.map do |check_list|
not_complete = false
if check_list.event.booking.video_for_event?
if check_list.raw_footage_user_id.blank? && check_list.raw_footage_check.blank? then not_complete = true end
end
if check_list.event.booking.eblast_not_blank?
# more checking...
end
if check_list.event.booking.on_site_not_blank?
# more checking...
end
if not_complete then reject end
end } #If videos, verify video items. if eblasts, verify eblast items, etc...
So basically I need to know how to finish it off by removing non_complete objects from the array being mapped out.
If I understand clearly you want only the completed checklists
Basically you must return the checklist when it's true and nil when it's not, then eliminate the nils in resulting array with compact... which is the work of select
checklists.map do |checklist|
# ....
checklist unless not_completed
end.compact
or more concisely :
checklists.select do |checklist|
# ....
!not_completed
end
I am checking to see if a value in a related table exists quite often in my view, in this case, expenses have approvals. If they have not been submitted, then there is no record of them in the approvals table.
I am ending up with some really awkward code
<% if !expense_item.expense_approval || expense_item.expense_approval.approval_status == 0 %>
Is there a way to do an if statement on a value, without having to check if it exists first? Or some default way to set it nil?
You could do the following in your ExpenseItem model:
delegate :approval_status, :to => :expense_approval, :allow_nil => true
This should allow you to simply do the following:
if expense_item.approval_status == 0
The try method above certainly works, but I like delegation better because I don't have to have .try(...) all over my code.
you can use try method which will return nil if method passed doesn't exist. so you could do something like:
expense_item.expense_approval.try(:approval_status) == 0
In my rails3.1 application, I'm trying to apply the following logic in one of my order model.
def digital?
line_items.map { |line_item| return false unless line_item.variant_id = '102586070' }
end
I've created a separate variant called prepaid_voucher which has id = 102586070. Despite this, the result is false...
Order has many line_items
LineItem belongs to order and variant
Variant has many line_items
Is this the best way to perform such a task and how can I fix?
First of all I think you want a double == here line_item.variant_id = '102586070', then I rather go for something like that (If I understand what you want)
def digital?
line_items.select{|line_item| line_item.variant_id == '102586070'}.any?
end
But it's hard to understand what you really want, what is the expected behavior if the id is not found?
def follows(follower, followed)
follow = Follows.where("follower = ? AND followed = ?", follower, followed)
if follow
true
else
false
end
end
Here is my view code:
<% if current_user.id == #user.id%>
<p>This is you!</p>
<% else %>
<% if follows(current_user.id, #user.id)%>
<p>You already follow <%= #user.username %>
<% else %>
<p><%= link_to "Follow!", follow_path(#user.id) %></p>
<% end %>
<% end %>
I want to check if a user follows another, so wrote this. It takes in two user ids, and queries the Database, and should return true when a match is found and false otherwise. But it always return true. Why is this?
Let's start with some style and design issues and end with the actual answer:
Models are singular by convention. Doing otherwise will only cause you more work. In this case, I would suggest Following as a suitable name, as in "a user has many followings".
Foreign keys should end with _id. Doing otherwise will only cause you more work. So follower_id and followed_id.
Methods that are intended to be used for their true/false nature ("query methods") should end with a ?, so follows? instead of follows,
Your if statement is redundant and can be safely removed once the condition does the right thing. In ruby, in the context of conditionals, we care more about whether things evaluate to true/false than whether they are literally true or false. This means that anything other than nil or false will be "truthy".
The fact that your method depends entirely on information known to User objects indicates that it would be better to hang it off of those objects, for instance current_user.follows? other_user.
You are duplicating behavior that would already be provided to you by using associations.
Finally, taking all of these things into consideration, the answer:
class User < ActiveRecord::Base
has_many :followings, :class_name => 'Following', :foreign_key => 'followed_id'
has_many :followers, :through => 'followings'
def follows?(other)
other.followed_by? self
end
def followed_by?(other)
followers.include? other
end
end
NB: The use of the followed_by? method here is a use of double dispatch that prevents the (minor) Law of Demeter violation of one user knowing directly about the state of another user's followers. Rather, the first user object asks the second user object a direct question ("Are you followed by me?") and bases the result off of the answer. (It is also likely to be a useful method in and of itself.)
The reason it always returns true is that, even when no records are found, where() is returning an empty array. An empty array is "true". In other news, the structure:
if (condition)
true
else
false
end
Can be replaced by:
condition
follow is actually an instance of ActiveRecord::Relation rather than the result set of your query. To work out find out if any rows would be returned by the query use follow.count. Eg.
if follow.count > 0
true
else
false
end
You can use present?. Your code should be
if follow.present?
true
else
false
end
#rein Heinrichs answer is superb. He gives you the best Rails way to solve it. But i would like to explain why what you wrote does not work, and how you should fix that.
Follows.where(...)
returns an array, the easy way to verify this yourself is to run that line in the rails console (type rails c in the console).
An array, even an empty one, is not nil and will always evaluate to true.
So to return a boolean depending on the fact whether or not any followers are found, just check for the amount of items inside the result of the where (use size > 0 or present?)
So your follows function could then have been rewritten as:
def follows(follower, followed)
Follows.where("follower = ? AND followed = ?", follower, followed).present?
end
and this is actually quite readable as well. Hope this helps.