Throwing exception when object in array doesn't have expected property - ruby

I'm fairly new to ruby and I've written a scraper, that scrapes car websites. I have an array, which is supposed to have car, but seem to have some unexpected objects in the array because of the scraping. I do the following in my code:
car_manufacture = car_array.map{|c| c.manufacture}
Now sometimes I the objects in the car_array are not actually car objects and don't have a manufacture property. When this is the case I would like to throw an exception and log the object. I can't seem to figure out how to do this.
Here are somethings I've tried:
car_array.map{|c| c.manufacture}.each{|c| !c.manufacture raise RuntimeError, "Error: Unknown object"}
And it doesn't seem to be working. Ideally I would like to have the exception thrown and logged and just continue moving on. Essentially just ignoring the object in the array.

You could use partition to split those out and track what didn't have the information.
with, without = car_array.partition { |car| !!car.manufacture }
Now you have 2 arrays, with contains cars where manufacture had something, and without contains ones that didn't. Log or throw as you see fit.
You can now safely get the manufacture as well:
car_manufacture = with.map(&:manufacture)

Related

Having problems using ObservableCollection's .First() directive

I have a segment in my code, where I want to scan a list of items, to see if the user entered a new item. To accomplish this, I am using a ObservableCollection items, and executing it's .First directive, since it seems they took away my beloved .Find, from working with List.
This is how I used to be able to find said element, but it's throwing an exception now, can anyone please give this a look and let me know what I am doing wrong?
I would prefer to avoid performing the Foreach method od doing this, but unless I can find what's wrong here, I wont have an option...
Sources src = new Sources() { Entry = this.viewModel.MyCase.Source, RecordCategory = (int)RecordCatagory.Supplies };
//If there is no matching element found we need to create it.
if (this.viewModel.SourcesList.First(x => x.Entry.Equals(src.Entry)) == null)
{
this.viewModel.SourcesRepo.AddItem(src);
}
Okay, so I was being an idiot...
The exception "Sequence contains no matching elements" (don't ask why I didn't catch that sooner, not enough coffee, and was not expecting an exception) was telling me there were no elements found. More or less doing exactly what I wanted. But since I was hoping that it would return a null result and not throw an exception my logic was all wrong. I will change my if into a try, and catch this specific ...no matching elements.. exception.
Just as an afterthought, is there any way to have it behave like a List and return a null result?
Thanks again.

Ruby Sinatra Upload Form params Disturbed

Upon submitting a form in Sinatra, I'm coming up with the following error:
App 40327 output: 2018-06-28 02:59:17 - NoMethodError - undefined method `[]' for nil:NilClass:
App 40327 output: /Library/WebServer/Documents/blammo/routes/publish.rb:87:in `block in <class:MyApp>'
The form is a file upload form, and a single text field. Simple. The file goes through, as does the text field. They are both captured just fine.
I submit the params to a method, which is ultimately responsible for generating the error on the following line down the page:
fname = params[:s_single_file_upload][:filename]
The method in question returns fine with a boolean. I've rewritten it a couple of ways and flushed out anything that might trip something I'm
unfamiliar with.
So the params is messed up if this method mentioned above is being called. So fname can't be assigned. I expect the params to be intact
at this point in the code. Is there any destruction if the params are perused before this point? In another language, I've seen params destroyed
in one way or another for some reason, but I'm not sure about Ruby.
I'm not finding any nil:NilClass, but that's exactly what it's reporting. Here's the trigger of this method:
result = Alpha::rf_alpha_sniff(params)
And the module::method:
module Alpha
def self.rf_alpha_sniff(incoming)
qualifiers = %w(alpha bravo charlie delta echo foxtrot)
incoming.delete('captures')
incoming.delete('splat') # take out Mustermann's 'captures' and 'splat'
incoming.delete('s_single_file_upload') # non-perusal 'single_file_upload'
incoming.values.each do |item|
item = item.gsub(" ","_")
Dev::hq_log("item: #{ qualifiers.include?(item.downcase) }")
return true if qualifiers.include?(item.downcase)
end
return false
end
end
So the page progresses fine without this method. When the method is induced any way, the params seem to get screwed up, so the file is pretty much
gone.
How is this method interfering with the params so that it's unavailable later on down the script? I'm expecting it to be fully available everywhere.
Turns out, using incoming.delete was deleting items from the params hash, as it was a reference to the original, instead of using a copy.
So, I have to copy the params by using params.dup (duplicate) so they are not the same object.
Having a view of the params hash post-testing-method, showed me that objects were indeed deleted. Another one solved.

Ruby on Rails Exceptions

I am a junior rails developer and was advised to use Class.find(id) to query the database instead of Class.find_by_id(id) which I previously had. The reason I was told is because the former would raise an exception while the latter would return nil. I realize this happens but I am wondering what the high level conceptual logic is for doing it this way. Why do I want the exception? Is this a rails standard where I would always prefer a method that returns an exception as opposed to nil?
You typically want the exception because you're typically doing Foo.find(id) based on data input coming from the user, such as clicking on a link.
For example, you show the user a list of items. There are links like this:
http://example.com/items/100
http://example.com/items/101
http://example.com/items/102
The user clicks the first link, and expects to see item 100.
Your code does this:
Item.find(100)
You expect to find the item, because app created the item link. You'd be surprised if the item didn't exist.
(Corner case surprises are possible: perhaps the item was deleted, or perhaps a hacker is sending in missing ids, etc. Using exceptions helps you handle this as an exceptional circumstance.)
Exceptions are preferred to nil for this, because you want the code to fail immediately so you don't accidentally send the nil on to some other method.
Ruby nil objects can be confusing because they evaluate to falsey and also because nil.id == 4 because of how Ruby uses C. Error messages show up like "Warning: Object#id will be deprecated" or "undefined method for 4:Fixnum".
Nils are problematic as a return type in Ruby in general. There's a great (paid) screencast by Gary Bernhardt that explains why you want to avoid returning nil from methods, but in a nutshell: when a method returns nil, and that nil gets passed up through a chain of method calls and something goes wrong somewhere, it can be extremely difficult to figure out where the actual problem occurred.
Say, for example, you have something like this:
foo_model = MyModel.find_by_name('foo')
# some more lines of code
do_something(foo_model)
and a method:
def do_something(model)
# some stuff stuff
some_other_method(model)
end
Now, if MyModel.find_by_name('foo') returns nil, that nil will be carried along without any errors until it actually has to do something. Say, in some_other_method, you actually try to call something on model, say model.save, you will get an error:
undefined method 'save' for nil:NilClass (NoMethodError)
The trace will carry you back up the method calls, but it will not mention the line that was actually problematic, where you assign MyModel.find_by_name('foo') (which evaluates to nil) to foo_model.
You can imagine that in a real application, the code can be much more complex, and returning nil can make it much more difficult to figure out the source of an error.
An exception, in contrast, tells you immediately where the problem is, and the trace will go back to the line where it occurred. That's one reason (there are others, I imagine) why in general, returning nil is not a good idea.
Hope that helps.

Using NSError the right way with non BOOL returning functions

Looking at the Error Handling Programming Guide, I understand that in cases like the following I must never evaluate the NSError parameter theError unless the return value is NO
BOOL success = [myDoc writeToURL:[self docURL] ofType:#"html" error:&theError];
What happens in casses when the return value is not a success BOOL, and instead it is a collection object?
Take for example [NSIncrementalStore obtainPermanentIDsForObjects:error]. I must not evaluate an error using the error parameter. What should I look for? I imagine I could receive either a nil pointer or an empty array. In this case an empty array does not seem a good response, although in other functions an empty array might be a good one. I can read that if an error occurs, the error object will contain a description of what happened, but it is not so clear how can I find out that an error actually happened.
What is the normal Cocoa or Foundation way to indicate an error in cases like these?
For that method, you're expected to return an array of as many items as you had objects passed in. I'd say that if you don't do that (either the array is nil or empty), you're in an error condition, since you're violating what the documentation says will happen:
An array containing the object IDs for the objects in array.
The returned array must return the object IDs in the same order as the objects appear in array

Ruby Koans about_methods line 123 object loop

Each time I add in the correct code, it gives me the same error due to AboutMethods:0x00000101841a28 number changing each time. It's like its stuck and I don't know how to get out this loop. It worked once, then I went on to the next step, but then it triggered an error after that.
I must not be inputting the correct line of code given from the console?
def test_calling_private_methods_with_an_explicit_receiver
exception = assert_raise(NoMethodError) do
self.my_private_method
end
assert_match "private method `my_private_method' called for #<AboutMethods:0x000001008debf8>", exception.message
end
The AboutMethods:0x000001008debf8 changes each time, not sure how to approach this problem?
AboutMethods:0x... is the output of the inspect method, which usually (and in this case) includes the class name (AboutMethods) and the object id (0x...). The object id is related to the objects location in memory, so it will change every time.
In my experience, there is very little value to checking the string from an exception (it's brittle). However, if you feel the need, use a regex:
assert_match /private method `my_private_method' called for \#\<AboutMethods:.*/

Resources