Rails: How to simplify ".select(:my_field).map(&:my_field)"? - ruby-on-rails

To get the invoice numbers of selected jobs I do:
Job.where(...).map(&:invoice_number)
Since the invoice numbers is all I need, I thought to add select(:invoice_number) (I assume the SQL query becomes more efficient this way):
Job.where(...).select(:invoice_number).map(&:invoice_number)
Is there a better way to do the same ? (the .select(:invoice_number).map(&:invoice_number) part seems inefficient to me)

You could always use select_values. Something akin to:
Job.connection.select_values(Job.where(...).select(:invoice_number).to_sql)
This avoids the instantiation of ActiveRecord objects.

I know that this question is rather old, but in case anybody else checks this out, this can be achieved with pluck (http://apidock.com/rails/ActiveRecord/Calculations/pluck). As per http://edgeguides.rubyonrails.org/active_record_querying.html#pluck "pluck makes it possible to replace code like: Client.select(:id).map(&:id) with Client.pluck(:id)"

Would love to be proven wrong, but.. I don't think it's possible
Since all the active record methods are chainable, a method that returned an array of strings would break this. If such a method existed then it wouldn't be in AR, I can't think of where else to look..

You can use GROUP_CONCAT.
invoice_numbers = Job.where(...).select('group_concat(invoice_number) as invoice_numbers').
first.invoice_numbers.split(',').map(&:to_i)
This approach is too long and is not very obvious, but it will run faster than
Job.where(...).select(:invoice_number).map(&:invoice_number)

Related

Independent ActiveRecord query inside ActiveRecord::Relation context

There is some ruby on rails code
class User < ActiveRecord::Base
def self.all_users_count
User.all
end
end
User.all_users_count
returns, for example, 100
User.limit(5).all_users_count
Now it return 5 because of ActiveRecord::Relation context, in despite of i wroute name of class User.all instead simple all
(.to_sql show that query always contains limit or where id or other things in other cases)
So, how can i make context-independent AR queries inside model methods? like User.all and others?
Thank you!
Ps. Or maybe my code has an error or something like this, and in fact User.all inside any methods and context always must returns correct rows count of this model table
This is very weird and unexpected (unfortunately I can't confirm that, because my computer crashed, and have no rails projects at hand).
I would expect
User.all
to create a new scope (or as you call it - context)
Try working around this with
User.unscoped.all
Edit:
I tried it out on my project and on clean rails repo, and the results are consistent.
And after thinking a bit - this is maybe not even an issue - I think your approach could be faulty.
In what scenario would you chain User.limit(2).all_users_count ?? I can't think of any. Because either you need all users count, and you call User.all_usert_count (or just User.count)
... or you need something else and you call User.limit(2).where(...) - there's no point in calling all_users_count in that chain, is it?
And, when you think of it, it makes sense. Imagine you had some different method like count_retired, what would you expect from such call:
User.limit(2).count_retired ?
The number of retired users not bigger than 2, or the number of all retired users in the system? I would expect the former.
So I think one of two possibilities here:
either you implemented it wrong and should do it in a different way (as described above in the edit section)
or you have some more complex issue, but you boiled your examples down to a point where they don't make much sense anymore (please follow up with another question if you please, and please, ping me in the comment with a link if you do, because it sounds interesting)

What is a efficient way to query for this information? [RoR]

Okay basically I'm trying to query the community_posts model and count the amount of posts where .community_topic_id is equal to community_topic which is a param. I was looking over the doc and I have a few ideas of how to do but, I want to make sure I'm doing it right as I have a few similar queries I'm writing for various other methods.
Hope this isn't too broad.. Not trying to ignite a "opinion war" I just want a way to do that wont turn out to be inefficient and force me to change my other queries.
Appreciate your help.
def topicreplycount(community_topic)
"Code for query"
end
CommunityPost.count(community_topic_id: community_topic)

Using Like in Rails SQL

I got a little problem using the LIKE sentence on rails i know that this next sentence works:
Brand.find(:all, :joins=>[:cars], :conditions=>["brandname LIKE ?","%ford%"])
But it's any way around that I could to something like this:
Brand.find(:all, :joins=>[:cars], :conditions=>["brandname LIKE '%ford%'"])
Its because i already have a function that returns all conditions on a single string, but i require to support search in strings and i don't really how to get it work.
Any help will be appreciated.
I'm not entirely certain that I understand what you're talking about. Are you trying to pass in a variable into the conditions?
I would re-write this query just a tad.
Brand.all.joins(:cars).where("brandname LIKE ?", "%#{some_variable}%")
Of course selecting all can be bad for performance if you get a lot of records so you may want to consider limiting that or paginating the results somehow.
I would recommend the guides. Using an array would be great in this instance
Brand.all.joins(:cars).where("brandname LIKE ?", "%#{params[:brand_search]}%")

Rails organizing code

i happen to be kinda picky when programming something big. I try to find the best way to do it it terms of speed and complexity. Since i've been learning Rails the previous 3 months, i try to find the best techniques for everything. I would like to ask you how you would go about writing some code like this :
#defender = User.find_by_id(user_id)
#attacker = current_user.clone
#attacker_starting_attribs = current_user
#defender_starting_attribs = #defender.clone
#defenderWeapon = #defender.getEquippedWeapon
#attackerWeapon = #attacker.getEquippedWeapon
#combat = Combatant.fight(#attacker, #defender)
This code is about the battle outcome between two persons in a browser game. The code works well, but i've some problems in terms of good coding. In fact, i know that my code is bad here, that's why i ask you what a better version would be. Let me explain what happens in this code.
#defender is given by user_id, so i guess that this part is needed. Now, in #attacker i'm cloning the current_user. The reason is that Rails works on objects and current_user will be changed inside Combatant.fight. I need both the new hp and the old hp and that is why i'm cloning the object. The defender and attacker starting attribs illustrate that concept. Now, i get the weapons in instance variables, so that i can get their information inside the final view.
However, the weapons are needed inside the fight function and i execute the same getEquippedWeapon twice again inside fight(). I was not so comfortable with something like fight(#attacker, #defender, #attacker_weapon, #defender_weapon), but i don't also like the idea of repetition. So, i would like an opinion on that.
#combat is a hash containing the result of the combat. Fight happens and i get that hash back in the view.
I'm not pleased with my coding on that stage and i want your opinion. How would you do it ? Is there maybe a design pattern for that ? Please tell me your opinion.
Thanx :)
I'm finding it difficult to completely understand what you're trying to do. I get the gist of it though (2 people fighting). I won't be able to provide an answer yet, but hopefully this gets the ball rolling:
From the code you provided, #attacker_starting_attribs and #defender_starting_attribs aren't being used.
As far as "good techniques", I try to stay as OO as possible. Instead of
Combatant.fight(#attacker, #defender), I would do #attacker.fight(#defender)
As a ruby convention, method names are underscored. In your case, .get_equipped_weapon instead of .getEquippedWeapon, or even better .equipped_weapon.
Anyways, I bet if you provided more code, you'd get more answers.

How to DRY up a ruby conditional structure needed for Rails

I'm finding I often have to use a structure to avoid a Rails error of undefined method 'name' for nil:NilClass.
The structure looks like this:
if country.state
country.state.name
end
It seems like a classic case of repeating oneself with country.state appearing twice in one simple block. Is there any way to DRY this up?
Rails adds a try method to object that mimics object#send but does not raise an exception if the object returns nil.
I think the syntax is
country.try(:state).name
Well not really. One option is to install the andand gem, but introducing a dependency for this may be a little much.
Other than using the slightly more concise syntax of:
country.state.name unless country.state.nil?
I don't think there's a DRY way to do this with the information given. I would argue that if you can't be sure whether country.state is nil or not, you may want to look at the code responsible for setting that value and determine whether that's a normal case or whether a validator upstream should be catching that.

Resources