Hi I want to know how can I write rspec for the following
def find_user(content)
user = User.find(content.to_i) ||
User.find(email: content) rescue
nil
end
I tried writing
It "user with user name" do
expect(User).to receive(:find).with(email: "test#a.com").and_return(user)
End
But I am gettig error saying
Argument Error
Block not Passed
Can someone please tell what am i missing
I may look first at your code here.
def find_user(content)
user = User.find(content.to_i) ||
User.find(email: content) rescue
nil
end
What is content? I looks like you're expecting either a user_id or an email address.
Doing this from the console:
irb(main):080:0> User.find("email#email.com".to_i)
=> ActiveRecord::RecordNotFound (Couldn't find User with 'id'=0)
So it seems as if having a generic find_user method may be contributing to some of the test writing confusion.
Many times, overly complex tests point to overly complex code.
Perhaps you need one method
find_user_by_email(email)
and another
find_user_by_id(id)
Also, refer to https://api.rubyonrails.org/v6.1.3.2/classes/ActiveRecord/FinderMethods.html#method-i-find_by
It will automatically return nil if nothing is found.
Start there, And then like the other commenters, then post your class, and the spec and we can go from there.
Sorry if it's an easy question, I am pretty new to Ruby.
When users sign up, or login I would like to keep statistics with Redis
def create
#user = User.new(user_params)
if #user.save
$redis.hincrby("2016MMDD", "new_users", 1)
render json: #user
end
end
If for any reason $redis.hincrby fails, is there a way to continue the execution of the code and render the user anyway?
Sure, just wrap the risky code in a begin/rescue/end block that captures the issue and continues execution.
http://rubylearning.com/satishtalim/ruby_exceptions.html. - see handling exceptions.
You might want to research what exceptions to look for, say if redis has gone away, rather than the base Exception catch
I see myself handling similar exceptions in a rather similar fashion repeatedly and would like to use aspects to keep this error handling code outside of the core business logic. A quick search online pulled up a couple of ruby gems (aquarium, aspector, etc) but I don't see a whole lot of downloads for those gems in rubygems. Given that, I want to believe there are probably other nicer ways to deal with this in Ruby.
get '/products/:id' do
begin
product = find_product params[:id]
rescue Mongoid::Errors::DocumentNotFound
status 404
end
end
get '/users/:id' do
begin
user = find_user params[:id]
rescue Mongoid::Errors::DocumentNotFound
status 404
end
end
In the above example, there are 2 Sinatra routes that look for a requested object by ID in MongoDB and throw a 404 if the object were not to be found. Clearly, the code is repetitive and I am looking to find a Ruby way to make it DRY.
You can see answer in this guide.
You code example:
error Mongoid::Errors::DocumentNotFound do
status 404
end
Assuming I have a WebCrawler class. There are several errors it can encounter. How should I propagate the errors upward?
Using exceptions:
class WebCrawler
class UrlBadFormatError < StandardError; end
class PageNotFoundError < StandardError; end
class UnauthorizedError < StandardError; end
def crawl(url)
if(! url =~ /some_format/)
raise UrlBadFormatError
response = get(url)
if(response.code == 404)
raise PageNotFoundError
if(response.code == 403)
raise UnauthorizedError
...
end
end
or constants:
class WebCrawler
URL_BAD_FORMAT = 1
PAGE_NOT_FOUND = 2
UNAUTHORZIED = 3
def crawl(url)
if(! url =~ /some_format/)
return URL_BAD_FORMAT
response = get(url)
if(response.code == 404)
return PAGE_NOT_FOUND
if(response.code == 403)
return UNAUTHORZIED
...
end
end
or symbols:
class WebCrawler
def crawl(url)
if(! url =~ /some_format/)
return :url_bad_format
response = get(url)
if(response.code == 404)
return :page_not_found
if(response.code == 403)
return :unauthorized
...
end
end
which is best? or it depends(on what?)
For something which indicates programmer error, such as the wrong type of argument passed to a method, definitely throw an exception. The exception will crash the program, drawing the programmer's attention to the fact that they are using your class incorrectly, so they can fix the problem. In this case, returning an error code wouldn't make sense, because the program will have to include code to check the return value, but after the program is debugged, such errors shouldn't ever happen.
In your WebCrawler class, is it expected that crawl will receive a bad URL as an argument sometimes? I think the answer is probably no. So raising an exception would be appropriate when a bad URL is passed.
When an exception is raised, the flow of execution suddenly "jumps" to the innermost handler. This can be a useful way to structure code when the exception is not expected to happen most of the time, because you can write the "main flow" of your method as simple, straight-line code without including a lot of details about what will happen when some rare error condition occurs. Those details can be separated from the "main flow" code, and put in an exception handler. When an error condition is expected to happen under normal conditions, though, it can be better to put the error handling code inline with the "main flow", to make it clearer what is going on. If the control flow of your program "jumps around" (as is the case when exceptions are used for normal flow control), that means the reader also has to "jump around" in the program text as they are figuring out how it works.
For the other two, I think it is expected that at least sometimes, the HTTP request will return an error code. To determine whether an exception or special return value is the best way to indicate such a condition, I would think about how often those conditions are going to happen under normal usage. Think also about how the client code will read either way. If you use exceptions, they will have to write something like:
urls.map do |url|
begin
crawl(url)
rescue PageNotFoundError
""
rescue UnauthorizedError
""
end
end
(By the way, I think this code example shows something: it might be a good idea if both of your custom exceptions inherit from a common superclass, so you can catch both of them with a single rescue clause if desired.) Or if you use error codes, it would look something like:
urls.map do |url|
response = crawl(url)
if [:page_not_found, :unauthorized].include? response
""
else
response
end
end
Which do you think reads better? It's really up to you. The one thing which you do not want to do is use integer constants for errors. Why use integers? When you print them in a debug trace, you'll have to go look at the list of constants to see what each one means. And using symbols is just as efficient computationally.
Why wouldn't you throw exceptions? They can encapsulate additional information besides just the type, are trivially rescued, and if you're using an IDE, are first-class citizens.
If it's an exception then by all means raises an exception! All three of those cases are, in my opinion, exceptions. While some may argue that 4xx status codes aren't exception-worthy since you may expect them to happen, they are still client errors.
You may also read about Ruby's throw/catch, which offer exception-like behavior for cases where "don't use exceptions for control flow" applies (though I don't think that's the case here).
You should raise errors. If you encounter a malformed URL, or if the page isn't found, or if you weren't authorized to access the page, it means you cannot continue crawling. Raising an error or exception returns from the method and lets the caller deal with the unusual situation.
It should also include information about the error, such as error codes, the URL which resulted in an error and any other relevant information. It can help in deciding how best to handle the error and can later be formatted into a helpful message for the user.
What you should not do, ever, is return numeric error codes. Ruby is not C. Just use symbols instead.
I am against the use of exceptions upon encountering 403s, 404s, malformed urls and similar common occurences on the web. Exceptions are meant for "internal" errors. In the World Wild Web, bad URLs are entirely unexceptional. There should be a method(s) for handling each different URL disease. I would personally return special values as symbols, or some "SpecialCase" objects recording what happened. There is also underused catch...throw statement.
I've got a function in my rails controller (I know, not the rails way, but I find it easier to write in the controller when I have something big like this and then move to the model).
I have an error in a array that I'm looping through, unfortunately, the error is being added somewhere in the loop. It is a big array with lots of properties, and I'm trying to figure out where the error is being caused.
I think I can isolate which object in the array is causing the error, but I can't get it to print.
Aparently ruby has an abort('message') function, but that returns an error in rails.
return render isn't working, it gives me an error that render and/or redirect is being called multiple times. How can I do a php type die in this situation?
This SO Post makes an excellent suggestion.
raise RuntimeError, 'Message goes here'
In the 'Message goes here' section you could even add in the array element:
array.each do |array_element|
<logic>
raise RuntimeError, "#{array_element.inspect}; Message goes here"
end