Ruby array delete if and get deleted object - arrays

So I have this situation where I need to delete something from an array conditionally, meaning that I want to go through the items in the array and do a test and delete the one that passes the test, and then I want to get that deleted item back. If I exclude the conditional aspect of this then Array#delete does what I want basically--returns the deleted item, but can't delete conditionally. On the other hand delete_if removes the item conditionally, but returns the remaining items back in an array.
For the purposes of this question assume the following class:
class Foo
def test?
#returns true or false
end
end
I can easily reproduce this behavior by doing:
index = my_array.index {|a| a.test?}
item_to_delete = my_array[index]
my_array.delete item_to_delete
But I was hoping to find something like:
deleted_item = my_array.delete_if_and_return_deleted {|a| a.test?}
I'm not thrilled about having to go through the array multiple times to get this done :/ first to find the target's index, second to get the target and third to remove the target. Ick.
Any thoughts or suggestions?

What you want is the partition method:
deleted_items, kept_items = my_array.partition {|a| a.test?}

Related

How to delete a piece of data from an array inside a Nested Collection?

I want to delete an item from an array that is inside a collection that is inside another collection (A nested collection) I have all the data that I need to achieve this, however I do not know how to write I have a slightly idea of how to (I'll be testing stuff on my own, but will leave the question here as well)
I'm using Material UI DataGrid to render my tables and to delete/edit them. I have a piece of information that is saved on my Local Storage in case I required it:
this is how my table looks:
When I select an ITEM and delete it is holding the ID of the item in the data:[Array]
those IDs are the IDs they hold in the data[array] -> :
finally I need to access this document, well I have the following
db.collection("usuarios").doc(user.uid).collection("pedidos").doc(id)
which brings the following:
which means I'm bringing the correct document, however I have no idea how to "update" or delete the array called data[], any ideas? What I want to achieve is that when I press the delete button it will update the array based on the Item selected so if it was Item ID: L-2627 then go through the array inside that collection, get the array called data and delete the item stored in the array.
Read the document into memory.
Modify the array by finding the item and removing it, again from memory.
Write the modified contents back to the document.
There is no shortcut or single operation for doing any this. The fact that the document is in a subcollection doesn't change anything. It's just how you have to modify arrays when you don't know the entire contents of the array item ahead of time.

How do I use the last value in an array as a path for .child() when retrieving a snapshot?

I'm new to Firebase and have a function that writes all of my event ID's to an array. I want to use the last value in that array (the last event ID) to lookup the children of that specific eventID.
I know how to get the last item in the array but how do I put that into my .child() path?
I tried the code below, but it doesn't seem to work. I'm guessing that because .child("(lastEvent)") isn't a valid path.
let lastEvent = eventIDArray.last
refHandle = ref.child("Bouts").child("\(lastEvent)")
How do I plug the lastEvent value in as my path? Or is that even possible? Again, total newbie- alternatives welcome.
Sorting and filtering data
you can use sorting and filtering function to get the item.
To get the last item you can write the query like this.**
let recentBoutsQuery = (ref?.child("Bouts").queryLimited(toLast: 1))!
This will return 1 entry from last of your database which the last entry.
You can learn more from the firebase documentation. Work with Lists of Data

ngAnimate to detect changes from $http-call with interval

I have an array with a few items in it. Every x seconds, I receive a new array with the latest data. I check if the data has changed, and if it has, I replace the old one with the new one:
if (currentList != responseFromHttpCall) {
currentList = responseFromHttpCall;
}
This messes up the classes provided by ng-animate, as it acts like I replaced all of the items -- well, I do actually, but I don't know how to not.
These changes can occur in the list:
There's one (or more) new item(s) in the list - not necessaryly at the end of the list though.
One (or more) items in the list might be gone (deleted).
One (or more) items might be changed.
Two (or more) items might have been swapped.
Can anyone help me in getting ng-animate to understand what classes to show? I made a small "illustation" of my problem, found here: http://plnkr.co/edit/TS401ra58dgJS18ydsG1?p=preview
Thanks a lot!
To achieve what you want, you will need to modify existing list on controller (vm.list) on every action. I have one solution that may work for your particular example.
you would need to compare 2 lists (loop through first) similar to:
vm.list.forEach((val, index)=>{
// some code to check against array that's coming from ajax call
});
in case of adding you would need to loop against other list (in your case newList):
newList.forEach((val, index)=>{
// some code to check array on controller
});
I'm not saying this is the best solution but it works and will work in your case. Keep in mind - to properly test you will need to click reset after each action since you are looking at same global original list which will persist same data throughout the app cycle since we don't change it - if you want to change it just add before end of each function:
original = angular.copy(vm.list);
You could also make this more generic and put everything on one function, but for example, here's plnkr:
http://plnkr.co/edit/sr5CHji6DbiiknlgFdNm?p=preview
Hope it helps.

Can't access text of an element in an array using PageObject and Watir

I have an array that I collected:
array= #browser.ul(:class => 'parent').links
I am then trying to access the text on a specific element in the array iterating over the array like this:
array.each_with_index do |i, index|
If I do something like:
array[index]
I get back the anchor element object. And if I do:
array[index].element
I will get back an HTML element object. But if I try to get anything element specific such as:
array[index].text
array[index].value
then I get an "unable to locate element" error.
I am using Watir, Page Object, and Ruby.
Here is the scope of the entire array iteration, it's fairly simple:
array= #browser.ul(:class => 'parent').links
array.each_with_index do |i, index|
if index == array.length-1
sleep 1
#browser.button(:text => 'Complete').when_present.click
else
sleep 1
#browser.button(:text => 'Complete').when_present.click
#browser.a(:text => 'Next').when_present.click
end
end
I am trying to add an elsif that checks for the text of a link, so that if it's on that particular page/link it does something specific while on that page.
For example, in pseudo-code:
If array element text = "Instructions", then dont click the complete button, just click next.
I suppose I would be open to solving this in any way that lets me identify the link it is currently on, so that I can perform a set action, but I figured grabbing the text of the current link would be easiest, hence the question.
How can I access the text or specific attributes of an element in this array?
Most probably the DOMs of your elements are changing after some interaction (like clicking 'Complete' button).
My suggestion is to find all the elements once again after each interaction.
Try something like that:
array = #browser.ul(:class => 'parent').links
index = 0
array.length.times do
sleep 1
if index == array.length-1
#browser.button(:text => 'Complete').when_present.click
array = #browser.ul(:class => 'parent').links #We are finding new array after possible change
elsif array[index].text == 'Instructions'
#browser.a(:text => 'Next').when_present.click
else
#browser.button(:text => 'Complete').when_present.click
#browser.a(:text => 'Next').when_present.click
end
array = #browser.ul(:class => 'parent').links #And once again
index = index+1
end
Attention: I can not guarantee that the code above will work because I've got no page to test it on to be sure. If it is not working - try to modify it using the idea
Iterating over a list of links and just pulling out information on them is fairly simple and should work reliably as long as the DOM is not changing. Once you start clicking things, or taking actions that cause some or all of the page to update, all bets are off as your collection may contain references to elements in the UI that have been deleted or replaced.
You also seem a bit confused over how the .each iterator works. The basic form of that method returns you each object in the collection in turn. The with_index version returns each object plus its index within the array. In most cases, unless you care what the index is, you would not use the with_index form.
For example, to walk your collection and output the text of each link, you could simply do
links_list = #browser.ul(:class => 'parent').links
links_list.each do |link|
puts "the link text is: #{link.text}"
end
If you wanted to indicate the index of each link, then you could do
links_list = #browser.ul(:class => 'parent').links
links_list.each_with_index do |link, index|
puts "the text for link number #{index} is: #{link.text}"
end
If you want to work your way through a list of links like that and do things with them that might cause page updates, then you are better off to use a tactic like that presented in the other answer where you create a loop based off the size of the list, but re-fetch the list inside the loop so that it will always be 'fresh' and not potentially contain references to objects that are no longer in the DOM.

Iterating through items in Capybara

I've got a page containing multiple elements of class .block. In Capybara, I want to be able to loop through and refer to each of the elements with this class before completing an action.
However, none of the code I've tried so far has worked. Here's what I've tried:
within('.block:nth-child(1)') do
find('.Button').click
end
page.find('.block').all.first.find('Button').click
page.find('.block').all[1].find('Button').click
Any ideas?
You want to use the all method (see http://rubydoc.info/github/jnicklas/capybara/Capybara/Node/Finders#all-instance_method).
An example of outputting the text of each element (ie iterating) with class 'block' would be:
page.all(:css, '.block').each do |el|
puts el.text
end
page.all returns an array of matching elements. So if you just want the second matching element, you can do:
page.all(:css, '.block')[1] #Note that it is 0-based index

Resources