conditions without repeats - ruby-on-rails

Hi i'm using this for getting data:
Topic.find(:all, :include => ...,
:conditions => #core ? ["cores_topics.id = ? AND visible = 1 AND (distance < ? OR cores.id IN (?))",#core.id, #user_location[3].to_i, #user_friends] :
["visible = 1 AND (distance < ? OR cores.id IN (?))", #user_location[3].to_i, #user_friends],
...
how can i rewrite the conditions shorter?

how can i rewrite the conditions
shorter?
User smaller variable names.
OK, really. Read the docs for named_scope. Your code is crying out for them.

Related

Is there a cleaner way to get a hold of an ActiveRecord query interface?

I have this which works, but I thought there might be a specific method for it.
#deals = Deal.where("1=1")
if #dealFilter.min.to_i > 0
#deals = #deals.where("size >= ?", #dealFilter.min)
end
if ...
I tried Deal.select but it required parameters. I found Deal.none but that returns none always. I tried Deal.where but it gave undefined method ``where' for #<ActiveRecord::QueryMethods::WhereChain:0x0000001d2bfb20> when I tried to chain another where on.
I have many conditions chained together. If no conditions match, it should return Deal.all.
Reference: http://guides.rubyonrails.org/active_record_querying.html
You could make use of ActiveRecord scopes, and move the logic into your model. For example:
class Deal < ActiveRecord::Base
scope :filter_min, ->(min) {
where("size >= ?", min) if min.to_i > 0
}
scope :filter_max, ->(max) {
where("size <= ?", max) if max.to_i > 0
}
end
And then in your controller you can write:
Deal.filter_min(#dealFilter.min).filter_max(#dealFilter.max)

Batch search for named_scope

This is an existing code written by someone else and am trying to enhance it. I am a java developer working on Ruby on Rails, so kindly be considerate.
I have entities like this
User
Delivery entity,
Delivery
belongs_to :user
named_scope :for_abcs, :conditions => {'deliveries.xyz_type' => ['Xyz1', 'Xyz2']},
many such named-scopes are defined.
Now to fetch the deliveries its written like this
#deliveries = current_user.deliveries.send("for_abcs").with(:xyz, :sender, :receiver)
...
...
...
# few other conditions added to #deliveries
finally
#deliveries.sort(...)
This sort is taking huge sql and giving performance issues. I want to use find_each, but find_each is only for Active Entity in Ruby on Rails, How can I achieve this (if possible) without much code change)
Earlier I used to do
Delevery.find_each
wherever it is
Delivery.find
Now I cant do as it is an array, what is the workaround or right procedure to do that in Ruby on Rails.
EDIT :
What I tried :
deliveries_temp = []
#deliveries.find_each(:batch_size=>999) do |delivery_temp|
deliveries_temp.push(delivery_temp)
end
This gave me error
undefined method `find_each' for []:Array
type(#deliveries) returned ActiveRecord::NamedScope::Scope , rails version 2.3.18
find_each should work on anything that returns a Relation (which includes scopes).
#deliveries = current_user.deliveries.for_abcs(:xyz, :sender, :receiver).find_each
Update
It sounds like you're using Rails 2.3. find_each is a class method in 2.3, so you'll need a way to extract the conditions from your scope and pass them to find_each. I found an article that looks promising, so give this a try:
Delivery.find_each(current_user.deliveries.for_abcs.scope(:find))
Also, I'm still not sure what that #with is doing. Maybe it's supposed to be #includes?
After lot of research for a week and learning about named_scopes by checking its source code. I understood what the problem was. The #deliveries is an object of class ActiveRecord::NamedScope::Scope . This class do not have find_each method. So I wrote a new named_scope for limit and offset in Delivery model file as follows :
named_scope :limit_and_offset, lambda { |lim,off| { :limit => lim, :offset=>off } }
After this , I called it in a loop passing offset and limit , for ex. first loop has offset=0, limit=999 , second loop has offset=999, limit=999 . I will add all the results into an emptry array. This loop continues till the result size is less than the limit value . This is working exactly the way I wanted , in batches.
set = 1
total_deliveries = []
set_limit=999
original_condition = #deliveries
loop do
offset = (set-1) * set_limit
temp_condition = original_condition.limit_and_offset(set_limit,offset)
temp_deliveries = temp_condition.find(:all)
total_deliveries+= temp_deliveries
set += 1
break if temp_deliveries.size < set_limit
end
#deliveries = total_deliveries.sort do |a, b|

How do I add a LIKE condition to this Find array?

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

Rails find condition delete first 2 symbols from field

I have such AR code:
#types = Type.find(:all,
:conditions => { :TYP_MOD_ID => params[:models],
:TYP_PCON_START => params[:year] },
:order => "TYP_HP_FROM")
but how can i do that i see TYP_PCON_START without first 2 symbols and compare?
for example :TYP_PCON_START.to_s[4...6]
Also i need to compare not =, but >= > condition. How to do this?
Use where instead of find. Also i didn't understand what you mean by how can i do that i see TYP_PCON_START without first 2 symbols and compare?.
#types = Type.where("TYP_MOD_ID = ? AND substring(TYP_PCON_START FROM 4 to 6) >= ?",
params[:models], params[:year]).order("TYP_HP_FROM")

Simple IRB Question regarding Count

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'])

Resources