I have a class called Deal.
Deal has vote_scores.
I would like to see how many vote_scores are in Deal that are greater than 2.
My guess :
for vote_scores > 2 in Deal
count
end
Doesn't really work :D
Edit:
I tried everyone's ideas. But note that :
Deal.vote_scores
Doesn't work because vote_scores is not an attribute of Deal, but rather an attribute of one of its Deals. So if I did this :
Deal.find(1).vote_scores
would return a #.
vote_scores is instantiated within the haml here:
.deal_summary{:id => "deal_#{deal_view.id}"}
.score
= deal_view.vote_scores
in the model here:
def vote_scores
self.votes.inject(0){|sum, vote| sum + vote.value}
end
If you just want to know how many, the more efficient code will be:
Deal.count(:conditions => ["vote_scores > ?", 2])
This will be faster since the counting is done in sql rather than in ruby.
EDIT
Okay, we can try this:
Deal.find(:all).select {|e| e.vote_scores > 2}.count
This will return total number of deal object that has vote_scores > 2
Hopefully that is what you want to do.
Deal.find(:all, :conditions => ["vote_scores > ?", 2]).length
deal = Deal.first #or whatever... Deal.find(10)
deal.votes.count :conditions => ['value > ?', 2]
for all Votes
Vote.count(:conditions => ['value > ?', 2'])
Related
I'm trying to build a basic search where only the entire exact search term shows results. Currently it is showing results based on individual words.
Here's the code from the model:
def search
find(:all, :conditions => ['term' == "%#{search}%"])
end
Sorry in advance. I'm very new to rails!
Thank you.
Remove the % from "%#{search}%" so it's "#{search}".
% is a wildcard that matches every result containing the word. So "%tea%" for example would match tear, nestea, and steam, when that's not what you want.
This should yield an exact match:
def search
find(:all, :conditions => ['term' == "#{search}"])
end
Your code doesn't work for several reasons.
You do not pass any value to that method. Therefore search will always be nil.
The ['term' == "%#{search}%"] condition doesn't make much sense because - as I said before - search is undefined and therefore the condition will is the same as ['term' == "%%"]. The string term is not equal to %% therefore the whole condition is basically: [false].
Rails 5.0 uses a different syntax for queries. The syntax you used is very old and doesn't work anymore.
I would do something like this:
# in your model
scope :search, -> (q) {
q.present? ? where("column_name LIKE :query", query: "%#{q}%") :none
}
# in your controller
def set_index
#b = Best.search(params[:search]).order(:cached_weighted_score => :desc)
end
There is a dropdown menu which contains an array of AR objects.
Need to show the element if the amount in the cart more than 3000.
I do so
element_of_dropmenu.delete_if {|x| x.name == "free delivery" && basket_sum < 3000} # remove one element
The amount in the cart is not true for the DeliveryType. This is a different model
you can do so
if sum > 3000
element_of_dropmenu
else
element_of_dropmenu.drop(1)
end
I need to display all elements when the sum>30, and remove one element when sum<30
i use rails 3.2.6 and ruby 2.0.0 :)
I think the way to do it wrong and ugly.
Tell me how to correct the code in a better way.
Thanks.
I believe you can achieve the result with simple SQL or ActiveRecord methods. Sth like below snippet would solve your problem.
YourModel.where(["name = ? AND basket_sum < ? ", "freedelivery", 3000])
or,
YourModel.where("name = ?", "freedelivery").where("basket_sum < ?", 3000)
You can't call mutator methods on ActiveRecord from 4.1 onwards check release notes
Relation no longer has mutator methods like #map! and #delete_if. Convert to an Array by calling #to_a before using these methods.
You can make use of select
element_of_dropmenu.select {|x| x.name != "free delivery" && basket_sum > 3000}
Or as marmeladze suggested you can use where clause or better create a scope
scope :premium, -> { where("name = ? AND basket_sum > ?", "free delivery", 3000) }
And chain it with association
element_of_dropmenu.premium
Thanks in advance for your help. I'm following the example I found here (Rails Find when some params will be blank) and trying to put together a bunch of conditions for a search form. This is for a Rails 2.3 legacy application. The below works for me, but I'm not sure how to do anything other than "=". For example, how can I make the programs_offered_category condition be a LIKE statement? I tried doing
majorcategories = params[:majorcategories]
Above the conditions statement and adding
conditions['programs_offered_category LIKE ?', "%#{majorcategories}%"]
but I get "wrong number of arguments (2 for 1)". Also, how can I do greater than and less than signs in this setup? Thanks!
search_controller.rb
conditions = {}
conditions[:city] = params[:city] unless params[:city].blank?
conditions[:state] = params[:state] unless params[:state].blank?
conditions[:geo_region] = params[:geo_region] unless params[:geo_region].blank?
conditions[:size_category] = params[:size_category] unless params[:size_category].blank?
conditions[:programs_offered_category] = params[:majorcategories]
#location_matches = Masterlocation.find(:all, :conditions => conditions, :order => 'nickname ASC').paginate(:page => params[:page], :per_page => 20)
I would suggest to use regular expression as follow
conditions['programs_offered_category'].map {|k,v| (k =~ /majorcategories/) ? v : nil}
It will return array of results if there is more than one matches otherwise single value
Is there something in Active Record that ensures that your query does NOT return more than one record?
This is what the basic functionality would be (apologies--this isn't real code but just enough to give the idea of what I'm looking for):
Foo.where(:thing => 'this_should_be_uniq').single
def single(records)
if records.length > 1
raise # or maybe return nil or something like that
else
return records.first
end
end
Essentially, this would be a safeguard against accidentally assuming (incorrectly) that your query will always return a single record.
Thanks!
If i'm understanding your question correctly, you can use limit
Foo.where(:thing => 'this_should_be_uniq').limit(1)
you can do Foo.where(:thing => 'this_should_be_uniq').single or Foo.where(:thing => 'this_should_be_uniq').single or .limit(1)
Foo.where(:thing => 'this_should_be_uniq').first
Foo.where(:thing => 'this_should_be_uniq').last
Foo.where(:thing => 'this_should_be_uniq').limit(1)
I cannot find such method in ActiveRecord::FinderMethods.
As alternative solution, you can write it shorter using tap method in the case of raising the exception if more than two records exists:
Foo.where(:thing => 'this_should_be_uniq').tap { |r| raise "ERROR" if r.count > 1 }.first
Considering isolation from other operations, the following code is proper:
Foo.where(:thing => 'this_should_be_uniq').to_a.tap { |r| raise "ERROR" if r.size > 1 }[0]
You can also use ActiveRecord find
Foo.find_by_thing('this_should_be_uniq')
Foo.find(:first, :conditions => {:thing => 'this_should_be_uniq'})
You can also find with multiple attributes
Foo.find_by_attr1_and_attr2(attr1_value, attr2_value)
I'm using the find method as follows:
#records = Effort.find( :all,
:select => 'full_name, taskType, sum(hours)',
:group => 'full_name, taskType',
...
#records.each do |record|
The query works fine. What I am confused about is how to access the sum(hours) value. I've tried the following:
record.sum(hours) # undefined local variable hours
record.sum_hours # sum_hours undefined
record[2] # Gives empty string
record[3] # Same, just double checking where the index might start...
I'm a bit stuck how to access the value! If I add <%= debug #records %> to my view, I see debugging output such as this:
---
- !ruby/object:Effort
attributes:
full_name: admin
taskType: Pre-Sales
sum(hours): '16'
What exactly are you trying to achieve with this query? Are you trying to get the sum of all Effort's hours or group them by some other means?
The query below
#records = Effort.find( :all,
:select => 'full_name, taskType, sum(hours)',
...
Will only ever return 1 value, because you're selecting a sum(hours) in there, which results in SQL aggregating the results into the first row. This means you'll always get your first Effort row, with a sum(hours) field set to the total amount of hours spent on all efforts.
If you just want the sum of all Effort hours, you can do this:
Effort.sum(:hours)
If you're looking to sum hours based on some other criteria, please update your question.
EDIT
In this case you could do something like this,
#records = Effort.group(:full_name, :taskType).sum(:hours)
You'll end up with a hash that looks like this:
[full_name, taskType] => count
i.e.
['baking cookies', 'baking'] => 12
['baking cakes', 'baking'] => 2
...
You could iterate over it like:
#records.each do | (full_name, task_type), hours |
puts 'Full Name: #{full_name}, Task Type: #{task_type}, Total Hours: #{hours}'
end
While looking back at my post and the debug output, it suddenly occurred to me it is right there on the page:
record.attributes[ 'sum(hours)' ]
I suppose that stuff like record.full_name is really a convenience method for accessing the attributes array?
not sure if it works, but you might want to try this :
#sums = Effort.sum(:hours,
:group => [:project_task_id, :user_id],
:joins => [:project_task, :user])
it should give you an array of records. You should then normally be able to collect these:
#array = #sums.collect do |aggregate|
[aggregate.project_task.name, aggregate.user.name, aggregate.hours]
end