Get array of attribute values, along with an attribute from a join - ruby-on-rails

I've gotten close, I believe. My current query is this
items = Item.select("items.icon, items.name, item_types.name AS type, items.level, items.rarity, items.vendor_value")
.joins(:item_type)
.where("item_types.name = '#{params[:item_type]}'")
This gets me an array of Item objects that at least respond to :type with the item_type.name.
What I am looking for is an array of arrays that look so:
[icon, name, item_type.name, level, rarity, vendor_value]
I've already had it working fairly easily, but it is important to me that this be done in one fell swoop via sql, instead of creating a map afterwards, because there are times where I need to respond with 40k+ items and need this to be as fast as possible.
Not sure how to go from the above to an array of attributes, without performing a map.
Thanks for your help!

The pluck method does precisely what you want. In your case, it would look like this:
items = Item.joins(:item_type)
.where("item_types.name = ?", params[:item_type])
.pluck("items.icon", "items.name", "item_types.name AS type",
"items.level", "items.rarity", "items.vendor_value")
I also changed the where call to use parameterization instead of string interpolation—interpolation isn't recommended, especially when you're getting a value from the user.
Further reading:
Official documentation for pluck
An in-depth explanation of how to use pluck

Related

Is there an efficient means of using ActiveRecord#Pluck for my situation?

I need to insert a lot of data into a new database. Like, a lot of data, so even nanoseconds count in the context of this query. I'm using activerecord-import to bulk-insert into Postgres, but that doesn't really matter for the scope of this question. Here's what I need:
I need an array that looks like this for each record in the existing DB:
[uuid, timestamp, value, unit, different_timestamp]
The issue is that the uuid is stored on the parent object that I'm looping through to get to this object, so #pluck works for each component aside from that. More annoying is that it is stored as an actual uuid, not a string, and needs to be stored as a uuid (not a string) in the new db as well. I'm not sure but I think using a SELECT inside of #pluck will return a string.
But perhaps the bigger issue is that I need to perform a conversion on the value of value before it is inserted again. It's a simple conversion, in effect just value / 28 or something, but I'm finding it hard to work that into #pluck without also tacking on #each_with_object or something (which slows this down considerably)
Here's the query as it is right now. It seems really silly to me to load the entire record based on the blockage outlined above. I hope there's an alternative.
Klass.find_each do |klass|
Data.where(token: klass.token).find_each do |data|
data << [
klass.uuid,
data.added_at,
data.value / conversion,
data.unit,
data.created_at
]
end
end
And no, the parent and Data are not associated right now and it's not an option, so I can't eager-load or just call Klass.data (they will be linked after this transition).
So ideally this is what I'm looking for:
Data.where(token: klass.token).pluck(:added_at, :value, :unit, :created_at)
But with the parameters outlined above.
I wonder if you can combine a SQL JOIN with pluck:
Klass
.joins('INNER JOIN datas ON datas.token = klasses.token')
.pluck('klasses.uuid', 'datas.added_at', "datas.value / #{conversion.to_f}", 'datas.unit', 'datas.created_at')

Lua - search for key inside of multiple tables

For my program, I have multiple tables inside of each other for organization and readability. These tables can look something like this
local buttons = {
loadingScreen = {
bLoadingEnter = function()
end
}, ...
}
What I want to do is find the first element named bLoadingEnter in the table. I dont know that the element named bLoadingEnter will be in loadingScreen. I've thought of getting all the keys in the table then check them. I couldn't get that to work. Any help would be appreciated!
If execution speed is in any way relevant, the answer is:
you don't
Looking up a key in a nested table takes a lot longer than looking it up in just a normal table. The next problem is that of uniqueness. Two or more nested tables can have the same key with different values, which may lead to odd bugs down the road. You'd either have to check for that when inserting (making your code even slower) or just hope things miraculously go well and nothing explodes later on.
I'd say just use a flat table. If your keys are well named (like bLoadingEnter) you'll be able to infer meaning from the name either way, no nesting required.
That being said, nested tables can be a good option, if most of the time you know what path to take, or when you have some sort of ordered structure like a binary search tree. Or if speed really isn't an important factor to consider.
Okay try
for _, item in ipairs(buttons) do
if item.bLoadingEnter ~= nil then
return item.bLoadingEnter
end
end

How can I replace a single Hash Value in Ruby by using its number

A fairly simple question, but I don't see it anywhere on SO, and I'm a Ruby noob.
In Ruby, if I have a hash, similar to this.
hashOne = {'dog' => 'canine', 'cat' => 'feline', 'me' => 'rubynooby'}
And let's assume that I want to replace the value a couple of different ways.
Method 1
Let's say I want to replace the value of me with rubypro. I've seen this done this way:
hashOne[:me] = "rubypro"
but I haven't seen a solution to replacing the value by which number it is, for example, let's assume that I always want to change the 3rd key (and assuming it starts on 1 and not 0)
Method 2 - These don't work
hashOne[3] = "rubypro"
or
hashOne.values[3] = "rubypro"
I haven't seen any examples of this, or a question about it on SO. Can someone point me in that direction?
The reason I was trying to work on this, is because I have a Hash, where I don't know what the key is, but I know what I want the value to be. It's weird, but that's where I'm at.
You can do hashOne[hashOne.keys[3]] = 'rubypro'. Also I remember reading that Hashes in ruby are ordered but I'm not entirely sure. (Be careful with using indices because they may not be ordered in other languages) I would ensure that the keys are always returned in the same order before trying to assign a key with an index.
If you really wanted to use an index, I'd recommend using an array because that's not the purpose of a key/value hash.
You can try this:
hashOne[hashOne.keys.unshift('')[3]] = "rubypro"

Select Rails objects that include value in array attribute

I have a Rails model called Box. Each Box object has a column :products, which is an array of strings that includes all the products that are being stored inside it at the time.
For each Box object, it is possible that the same value was stored in another Box.
Is there a query I can use to return all the Boxes that have value x stored in :products?
I know "where" works for finding objects with certain values, and with an array you might use "include?", but I'm having trouble working out a way to use either in this case, if it's at all possible.
There was an answer posted here before that worked well enough, but I looked around and found another query that was more succinct.
selected_boxes = Box.where("?=ANY(products)", x)
Where x is the value you are seeking in each object.
Scope!
scope :contains, ->(items) { where("products LIKE ?", "%#{items.to_yaml}%") } # items is an array of your potential strings
So you'd call this as Box.contains(%w(foo bar)) or Box.contains(['some thing'])
Passing the array should let you search for multiple items at a time...
You can name the scope anything you want, obviously
LIKE for mySQL... ILIKE for postgreSQL

List of Model's Field in Rails

I've been looking at the Rails documentation and can't find this.
Lets say I have a Model User with field strength.
How do I get a list of all strengths for every instance of the model object in an array?
list_of_str = [1, 2, 3, 4, etc..]
I know that you can call User.all and iterate through each of their strength fields and append them to a list but is there a more elegant way of doing this?
User.pluck 'strength'
New in rails 3.2 if my memory is correct
You can use
User.uniq.pluck 'strength'
If you need to avoid duplicates, and you can also combine this with scopes and conditions, for example
User.where(...).pluck 'strength'
If you're really after the distinct strengths then:
User.select('distinct strength').pluck(:strength)
will get them. If you don't care about duplicates then Frederick Cheung's plain pluck would be a good idea.
You can use the select method for that, it generates a query where only the values of the desired field are retrieved (which is faster than loading all model data from the database):
User.select(:strength)
This still returns an array of model-objects, so you have to use map to get an array of the values only:
User.select(:strength).map(&:strength)
The creation of the model object will be slower than just querying the database for the values, but using raw SQL should be avoided if performance is not critical in this place.
Edit: There is an even better way (pluck), see the accepted answer.

Resources