I'm trying to get all the feedbacks with a specific attribute. I am using this code:
def index
feedbacks = Feedback.all
if params[:tag]
#average_customer_rating = feedbacks.where('buyer_feedback_date is not null').rated(Feedback::FROM_BUYERS).average(:buyer_rating) || 0
#products = Product.includes(:images).tagged_with(params[:tag]).order('DESC').limit(22)
else
#products = Product.includes(:images).all
#average_customer_rating = feedbacks.where('buyer_feedback_date is not null').rated(Feedback::FROM_BUYERS).average(:buyer_rating) || 0
end
end
and Rails shows this error:
undefined method `where' for []:Array
Why can't I use where here and how do I fix it?
In Rails 3.x, all returns an array:
feedbacks = Feedback.all # <- an array
feedbacks.where(...) # <- fails
To get an ActiveRecord::Relation, you have to use scoped:
feedbacks = Feedback.scoped # <- an ActiveRecord::Relation
feedbacks.where(...) # <- works
See Working with scopes for more examples.
Note that this distinction is not needed in Rails 4 anymore – scoped was deprecated in favor of all which now returns an ActiveRecord::Relation.
Why can't I use where on an array?
Because Array class does not have instance method called where.
Since feedbacks.class is Array, you get an error.
You have two options:
Define feedbacks as instance of ActiveRecord::Relation and use where
Not using where but appropriate methods from Array class.
If Feedback is your ActiveRecord model, you could probably use Feedback.where('buyer_feedback_date is not null').
feedbacks = Feedback.all
Why would you query every entry in this table to get
feedbacks.where('buyer_feedback_date is not null').rated(Feedback::FROM_BUYERS).average(:buyer_rating) || 0
Try this =>
#average_customer_rating =Feedback.where('buyer_feedback_date is not null').rated(Feedback::FROM_BUYERS).average(:buyer_rating) || 0
else
#average_customer_rating = Feedback.where('buyer_feedback_date is not null').rated(Feedback::FROM_BUYERS).average(:buyer_rating) || 0
Should scope it to cust_feedback
Related
I've tried to put results from my vote model in a hash for further usage, but I don't know how to create a hash key from a variable in Ruby. See example below:
def create_hash_array(campaign_votes)
target_hash = Hash.new
campaign_votes.each_with_index do |cv,i|
target_hash[cv.content_id] = {} if i == 0
if target_hash[cv.content_id].member?(cv.vote_button_id)
target_hash[cv.content_id][cv.vote_button_id] = (target_hash[cv.content_id][cv.vote_button_id]).to_i + 1
else
target_hash[cv.content_id] = {cv.vote_button_id => nil}
end
end
target_hash
end
Usually I got an error:
undefined method `member?' for nil:NilClass
but it comes from unrecognized target_hash[cv.content_id], how can I make does variable to be recognized target_hash[cv.content_id] ??
I think your code can be boiled down to this:
def create_hash_array(campaign_votes)
target_hash = Hash.new { |h,k| h[k] = Hash.new(0) }
campaign_votes.each do |cv|
target_hash[cv.content_id][cv.vote_button_id] += 1
end
target_hash
end
There's multiple problems here, many to do with getting all tangled up in the process. You initialize the element of the target_hash structure only on the 0 index position, yet each campaign_vote could have different content_id values, meaning you're missing out on those.
This approach creates a single auto-generating Hash that will populate keys with counter hashes, that is hashes defaulting to 0. That means you can always navigate them and += 1 will work because of the default.
This approach is pretty common in Ruby, especially Hash.new(0), which is super handy for doing simple counters of arbitrary objects.
#click = Missing.select{|d| d.click < 10000}
find = #click.minimum(:id)
#data = Missing.where(id: find)
dataSize = #data.size
#renderData = #data[dataSize - 1]
render :json => #renderData
Errors:
undefined method `minimum' for #<Array:0x00000004acd678>
Error code : find = #click.minimum(:id)
I have no idea why it is wrong.
render :json = #click is working.
find = Missing.minimum(:id) is working.
#click = Missing.select{|d| d.click < 10000} is returning an array of active record instances. This is why minimum can not be called against an array.
If you want the first record in the #click set then use #click.first.id. If you want the smallest (min) id then use #click.map(&:id).min. Looking at your code i'm not sure what you are trying to achieve?
On a side note, i'd avoid calling Missing.select{|d| d.click < 10000} because that is doing a full table scan on your Missing model's table. As Ruby Racer says, better to query with active record.
#click is an array, not an association.
Why don't you use activerecord query to get your find?
find = Missing.where('click < 10000').minimum(:id)
I have a query that goes:
ModalType.where(id: modal['modal_id']).take.template
The problem is that i might run in cases where the query does not find any id: modal['modal_id'], then I get the error
undefined method `template' for nil:NilClass
How can I write something that would 'take' BUT only if where(id: modal_id) returns something (=is found) ?
With Ruby < 2.3:
object = ModalType.where(id: modal['modal_id']).take
if object
object.template
else
# I don't know. it's up to you
end
or
ModalType.where(id: modal['modal_id']).take.try(:template)
With Ruby >= 2.3 you can use safe navigation operator:
template = ModalType.where(id: modal['modal_id']).take&.template
I have this project I'm working on where I have a checklist. This checklist has an event_id, and then 2 fields for each task that much be done, one for the user_id that completed it, and one for the date. First what I do is grab all the checklists, which gives me an acitverecord::relation of all the checklists. Then I want to get only the completed checklists.
def index
#check_lists = CheckList.joins(:booking).joins(:contract)
#check_lists = #check_lists.complete if params[:status] == "complete"
#check_lists = #check_lists.incomplete if params[:status] == "incomplete"
end
My problem is once I call the #check_lists.complete, does it automatically give me the array in the scope in the model? Would I have to pass something in the method to get the array and run through it? Then once I have the activerecord::relation how do I run a loop through it?
scope :complete, { }
scope :complete, -> { where(complete: true) }
for example, would give you an ActiveRecord::Relation. This would be the same as CheckList.where(complete: true). You can convert this relation to an array of results using all.
CheckList.complete #=> ActiveRecord::Relation
CheckList.complete.all #=> Array
In Rails 4, all will return an ActiveRecord::Relation as well, so it will be necessary to use to_a to convert it to an array, but for now all will return an Array.
I am doing what I thought was something very simple - finding a user and incrementing an integer.
#user = User.where("created_at > ?", Time.now.midnight).select(:visit_count)
#user.visit_count += 1
#user.save(:validate=>false)
I get the following error:
undefined method `visit_count' for [#<ActiveLink visit_count: 1>]:ActiveRecord::Relation
This seems like a Rails 3 thing - where am I going wrong?
Your query always returns multiple results as an Array.
Just add .first to be sure that you only pick the first result.
#user = User.where("created_at > ?", Time.now.midnight).select(:visit_count).first
If you want to update many records at the same time, look at update_all method :
http://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-update_all