How do I find matches in two arrays in IRB? - ruby-on-rails

For some reason I can't figure this out. But basically I want to compare to models and see if they have any matching emails. Here's my attempt, but this doesn't for some reason work at all.
>> CardReferral.all.select{|cf|cf.email == CardSignup.all.collect{|cs|cs.email}}
Where I can somehow return the object..

CardReferral.all.map(&:email) & CardSignup.all.map(&:email)
from the rdoc
array & other_array
Set Intersection—Returns a new array containing elements common to the two arrays, with no duplicates.
[ 1, 1, 3, 5 ] & [ 1, 2, 3 ] #=> [ 1, 3 ]

Related

In Ruby on Rails is there a better way than using eval() to accses this jsonb dynamically?

I've got some jsonb in a database and I want to write to an attribute dynamically, I know the path to the attribute but it could be any depth and any attribute name.
I know the path to the attribute, however the only way I've found of writing this dynamiaclly is with eval().
eval("self.some_json_column['an_array'][10]['a_different_array'][5]['color'] = 'blue'")
self.save
So I know the depth and the array index, but it could be any depth or index. I can build the string and pass it into eval()
However I know that eval() is a last case scenario and was wonderign if it's possible to build the path and write (in this case that color json attribute) dynamically without using eval()
Thanks.
You can reduce your way through the Hash that is returned by self.some_json_column
*path, target = ['an_array',10,'a_different_array',5,'color']
node = path.reduce(self.some_json_colum, &:[])
node[target] = 'blue' if node
This has no error handling if any part of the path is incorrect
You could also look into dig depending on ruby version like so
node = self.some_json_column.dig(*path)
node[target] = 'blue' if node
This will return nil if any part of the path does not match
Example:
h = {
'an_array' => [0,1,2,3,4,5,6,7,8,9,
{'a_different_array' => [1,2,3,4,5, {'color' => 'orange'}]}
]
}
*path,target = ['an_array',10,'a_different_array',5,'color']
h.dig(*path)[target] = 'blue'
h
#=> {"an_array"=>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
# {"a_different_array"=>[0, 1, 2, 3, 4,
# {"color"=>"blue"}
# ]}
# ]}

Sending array of nulls in json request - Rails 5

I need to send request to my Rails API with key like: ids: [null, 1, 2, null, 3]. Unfortunately Rails cuts all the nulls from this array so the params[:ids] returns [1, 2, 3]. I need those nulls in the array.
How can I prevent Rails from removing them? I can send empty string instead of null, but it's not very elegant.
In rails 5, intends to not have the same sql injection vulnerabilities and so have removed the deep_munge method that would change an empty array value to nil but have left in the configuration option which produces behavior best described by looking at the tests.
for more info
https://apidock.com/rails/v3.2.8/ActionDispatch/Request/deep_munge
https://til.hashrocket.com/posts/e1bed09363-deepmunge-i-hardly-knew-ye
In application.rb add below line
config.action_dispatch.perform_deep_munge = false
and restart the application
use json structure instead of array
replace
ids: [null, 1, 2, null, 3]
with
ids: {"0": null, "1": 1, "2": 2, "3": null, "4": 3}
And in controller access it like
params[:ids].values
[nil, 1, 2, nil, 3]
In different environment null value is interpreted differently.
I think that the best practice is to replace these entries according the result you want to achieve:
ids.map! { |id| id == null ? nullValue : id }.flatten!
Where nullValue is what you're expecting to have in the array.

Rail postgres array contains (<#) dont include nil

I have a Matchups table that includes a field that is equipment_id and stores an array
I am trying to search the Matchups table to get any records that have an array where it contains specific equipment ids. For example:
So I am running:
search_equipment_ids = [1, 2, 3, 4, 5]
Matchup.where("equipment_id <# ARRAY[?]", search_equipment_ids)
The following are a few examples of arrays that are stored in the table in equipment_id and what the above query would result in
[1, 2] = True
[3, 5] = True
[1, 2, 3] = True
[1, 2, nil, 3] = False
How can get the search to ignore that there might be a nil included in the array. I am going to make a change to how the array is stored so from here on out there will be no nil values...but in the mean time I need to take these into account.
I am using: https://www.postgresql.org/docs/9.5/static/functions-array.html as a reference.
I dont want to use the && operator because the Matchups table is huge it will return to many results if just comparing if one equipment id is present. I want to only return if all the equipment_ids are contained (excluding any nils).
Thank you!
How about removing the nil values from the array? That's easy:
Matchup.where(..., equipment_ids.compact)

How can I delete certain indeces defined in an array from an other array in ruby

I have a method that iterates over an array, does a bunch of stuff under certain conditions and depending on these conditions I would ALSO like to delete some of the elements. In order to keep track of the indexes I like to delete I converted the each in to an each_with_index loop and store the index of the elements that I like to delete in an array index_array. How can I delete exactly the items on those indexes in my original array? Looping over the index_array and using delete_at would change the original index. Please see below description of the scenario:
> my_array = [0,1,2,3,4,5,6,7]
> delete_these_indexes = [1,2,5]
the desired result is:
> my_array => [0,3,4,6,7,8]
How about this?
my_array = [0, 1, 2, 3, 4, 5, 6, 7]
delete_these_indices = [1, 2, 5]
delete_these_indices.sort.reverse_each {|i| my_array.delete_at(i) }
p my_array
# => [0, 3, 4, 6, 7, 8]
It's important to delete from the end of the array, since deleting an item will change the indices of all subsequent items, ergo sort.reverse_each. If you know the array is already sorted, you can just do reverse_each.
If you don't care bout modifying the delete_these_indices array, you can be somewhat more terse:
delete_these_indices.sort!
my_array.delete_at(i) while (i = delete_these_indices.pop)
Again, you can skip sort! if you know delete_these_indices is already sorted.
keep_these_indexes = my_array.each_index.to_a - delete_these_indexes
#=> [0, 3, 4, 6, 7]
If you wish to modify my_array (which appears to be the case):
my_array.replace(my_array.values_at(*keep_these_indexes))
#=> [0, 3, 4, 6, 7]
If not:
new_array = my_array.values_at(*keep_these_indexes)
See Array#values_at.
delete_these_indexes.each_with_index do |val, i|
my_array.delete_at(val - i)
end
deletes at the desired index taking into account how many have previously been deleted and adjusting for that
https://repl.it/CeHZ
Probably not the best answer, but you can do this as well:
delete_at_indices.each {|ind| my_array[ind] = nil }
my_array.delete(nil)
Takes a first pass to conceptually invalidate the data at the specified indices, then the call to .delete will blow out any values that match what's passed in.
This solution assumes that you can define a value that isn't valid for your array. Using nil will be problematic if you're treating this as a sparsely populated array (where nil is a valid value)
Technically you're iterating through each array once, but that Gentleman's Agreement on what your deletable value might make some people uncomfortable

Removing a "subset" from an array in Ruby

I want to remove some elements from an array contained in another array.
The way to do this in Java is:
myArray.removeAll(anotherArray)
This code removes the elements contained in anotherArray from myArray.
Is there something like removing the elements contained in myArray INTERSECTION anotherArray from myArray?
Yes, this is what the - operator (really Array#- method) is for:
a = [1, 2]
b = [2]
a - b
# => [1]
Use "Array Difference"
There's more than one way to do this in Ruby, but the most common is to call the array difference method Array#-. The documentation for this method says:
Returns a new array that is a copy of the original array, removing any items that also appear in other_ary. The order is preserved from the original array.
It compares elements using their hash and eql? methods for efficiency.
[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]
If you need set-like behavior, see the library class Set.
The minus sign looks like an operator, but is actually a method call on the first Array object. Obviously, you could also look at Set#difference if you're working with Set objects rather than an Array.

Resources