When i import Time and HTTParty i got these warnings:
C:/Ruby27-x64/lib/ruby/2.7.0/time.rb:34: warning: already initialized constant Class::ZoneOffset
C:/Ruby27-x64/lib/ruby/2.7.0/Time.rb:34: warning: previous definition of ZoneOffset was here
C:/Ruby27-x64/lib/ruby/2.7.0/time.rb:137: warning: already initialized constant Class::LeapYearMonthDays
C:/Ruby27-x64/lib/ruby/2.7.0/Time.rb:137: warning: previous definition of LeapYearMonthDays was here
C:/Ruby27-x64/lib/ruby/2.7.0/time.rb:138: warning: already initialized constant Class::CommonYearMonthDays
C:/Ruby27-x64/lib/ruby/2.7.0/Time.rb:138: warning: previous definition of CommonYearMonthDays was here
C:/Ruby27-x64/lib/ruby/2.7.0/time.rb:475: warning: already initialized constant Class::MonthValue
C:/Ruby27-x64/lib/ruby/2.7.0/Time.rb:475: warning: previous definition of MonthValue was here
C:/Ruby27-x64/lib/ruby/2.7.0/time.rb:677: warning: already initialized constant Time::RFC2822_DAY_NAME
C:/Ruby27-x64/lib/ruby/2.7.0/Time.rb:677: warning: previous definition of RFC2822_DAY_NAME was here
C:/Ruby27-x64/lib/ruby/2.7.0/time.rb:681: warning: already initialized constant Time::RFC2822_MONTH_NAME
C:/Ruby27-x64/lib/ruby/2.7.0/Time.rb:681: warning: previous definition of RFC2822_MONTH_NAME was here
This is literally all the code:
require 'HTTParty'
require 'Time'
Somebody knows how i fix this?
There is no Time library in Ruby. There is, however, a time library.
It looks like you are using a case-insensitive file system, so when you require 'Time', the Operating System will "lie" to Ruby and tell it that Time.rb actually exists, even though there is really only a time.rb. (The OS will say the same thing about TIME.RB or tImE.rB or TiMe.Rb or …)
Therefore, Ruby will load Time.rb (which is really time.rb). However, internally, the time library will of course use require 'time' everywhere. Now, Ruby detects when a file has already been loaded and will just ignore it, BUT Time.rb and time.rb are two different file names, so Ruby will naturally load them both.
Since they are the same file, though, everything in time.rb will get executed twice, which means that you will get a warning for every single constant definition and every single method definition in that file.
The solution is simple: use require 'time' because that's the name of the library's entry file.
The alternative would be to use a case-sensitive file system, in which case you would simply get a LoadError exception telling you that there is no file named Time.rb.
Related
I am confused about the difference between load 'file.rb' and require 'Module'. At Learn Ruby the Hard Way, the example of how to use a module is set up with two files (mystuff.rb and apple.rb):
mystuff.rb
module MyStuff
def MyStuff.apple()
puts "I AM APPLES!"
end
end
apple.rb
require 'mystuff'
MyStuff.apple()
However, when I run apple.rb, either in the Sublime Text console, or with ruby apple.rb, I get a Load Error. I have also tried require 'MyStuff', and require 'mystuff.rb', but I still get the Load Error.
So, I switched the first line of apple.rb to load 'mystuff.rb', which allows it to run. However, if I edit 'mystuff.rb' to be a definition of class MyStuff as opposed to a module MyStuff, there is no difference.
For reference, the Load Error is:
/Users/David/.rvm/rubies/ruby-2.0.0-p353/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in require': cannot load such file -- mystuff (LoadError)`
I've peeked into kernel_require.rb and looked at the require definition, but since I'm a Ruby Nuby (indeed, a programming newbie), it was a little overwhelming. Since Learn Ruby the Hard Way hasn't been updated since 2012-10-05, there've probably been some syntax changes for modules. Yes?
require searches a pre-defined list of directories, as discussed in What are the paths that "require" looks up by default?. It's failing because it can't find the mystuff.rb in any of those directories.
load, on the other hand, will look for files in the current directory.
As for:
However, if I edit 'mystuff.rb' to be a definition of class MyStuff as
opposed to a module MyStuff, there is no difference.
I'm not sure I understand what you mean by "no difference". If you mean that the require and load continue to fail and succeed, respectively, that makes sense, as the require failure is independent of the content of the file contents and the code you're testing behaves the same independent of whether Mystuff is a class or a vanilla module.
You can solve this easily by changing
require 'mystuff'
to
require_relative './mystuff'
I'm trying to run an example app from github. their app runs fine. which means that my setup is wrong, but I don't know what it is. this is my first time trying ruby.
what I did:
1- downloaded the code from github
2- made a gemfile:
source "https://rubygems.org"
ruby "2.0.0"
gem "sinatra", "1.4.4"
gem "haml", "4.0.3"
gem "sass", "3.2.12"
3- ran bundle install
4- when I run my .rb file (on heroku or on my computer), I get this error everytime:
/Library/Ruby/Gems/2.0.0/gems/sinatra-1.4.4/lib/sinatra/base.rb:1760:in `set_encoding': can't convert String to Hash (String#to_hash gives Symbol) (TypeError)
from /Library/Ruby/Gems/2.0.0/gems/sinatra-1.4.4/lib/sinatra/base.rb:1760:in `block in detect_rack_handler'
from /Library/Ruby/Gems/2.0.0/gems/sinatra-1.4.4/lib/sinatra/base.rb:1758:in `each'
from /Library/Ruby/Gems/2.0.0/gems/sinatra-1.4.4/lib/sinatra/base.rb:1758:in `detect_rack_handler'
from /Library/Ruby/Gems/2.0.0/gems/sinatra-1.4.4/lib/sinatra/base.rb:1420:in `run!'
from /Library/Ruby/Gems/2.0.0/gems/sinatra-1.4.4/lib/sinatra/main.rb:25:in `block in <module:Sinatra>'
--> I should signal that the github repo I'm trying to run is old (hasn't been touched since 2010)
It seems that this is an error in the used gem "sinatra".
Try to change the gemfile like this (without giving explicit version number), so that the application installs the latest version of the gems.
source "https://rubygems.org"
ruby "2.0.0"
gem "sinatra"
gem "haml"
gem "sass"
Probably there is a newer version of the sinatra gem.
Ok. so it turns out it wasn't my setup. (I tried using gems and ruby versions from 2009 and it didn't make the error go away either.)
I narrowed it down by gradually commenting things out in the script (since ruby wouldn't give me a line in my own files, only in sinatra files, I thought at first it wasn't due to my code).
--> it was a single line of code that, now that I commented it out in my script, made the error disappear forever with seemingly no negative side effects. (see code below).
If someone can briefly comment on that method (is it some kind of sinatra framework callback, for error handling a call to a nonexistent method? I assume this since it's never called in my files!) and why it could cause the error described in the question, I will pick their answer, otherwise I will pick this (my) answer. (just write anything you know or can find about this method and I'll pick your answer, Thanks).
def method_missing(methId)
method_name=methId.id2name.intern
if #lists.respond_to? method_name
#lists.send(method_name).pick
else
# method_name # line that caused the error in the sinatra source files.
end
end
================================================
so here's my own quick research on method_missing ... trying to learn ruby a bit here:
some info about method_missing:
http://www.alfajango.com/blog/method_missing-a-rubyists-beautiful-mistress/#/when-to-use-method-missing
http://rubylearning.com/blog/2010/10/07/do-you-know-rubys-chainsaw-method/
second link is a great intro.
basically method_missing is, yes, a kind of error handler for calling nonexistent methods. it's a ruby language thing (it calls method_missing when it can't find the method). so it's not tied to a framework, just to ruby.
besides simple error handling, one common usage for it is to be able define actions according to the (non-existent) method name (make up actions based on the nonexistent method name!), for example in the case where you have a great number of methods that do very repetitive things and you can deduce/base their behavior on their name.
a way to limit your pool of "methods you're going to make up behavior for, on the spot" is to have an if with a regular expression match (or in our case a match in a predefined list of items). if it's not matched, then you can for example throw an exception yourself or just return to see what happens next in the calling code.
so here in our code:
if the method name doesnt exist, they check if it exists in a list and act accordingly (they return a list, picked among #lists).
but if it is not found in #lists … they return that very method name, a string, that we didnt have a match for.
...but now the question is: --> how is the calling code dealing with that return value? (obviously not well, it seems to expect a hash or an array, not a method name string) a safe way to deal with "not finding a match for your nonexistent method" is to call super, to resume normal execution of the calling code (according to first link).
so one question remains: was it a good idea to return the method name? would returning the method name ever work? or was it really wrong, and super (or nothing) should be put in its place?
… my temporary conclusion is that --> you shouldn't return a list sometimes and a string some other times. so it would be a plain mistake, that surprisingly never caused problems or was never found in the original repo...
I have a conditional bit of code that only can be loaded under certain conditions. It's platform specific code.
module MyGem
module MyPlatformSpecificThing
#stuff
end
end
My current attempt at lazily requiring this is performed like:
module MyGem
class AClass
def DoSomething
if thing_is_true
require 'my_platform_specific_thing.rb'
MyGem::MyPlatformSpecificThing.init
#more stuff
end
#even more stuff
end
end
This seemed like a solid enough plan, unfortunately it is not working. This code results in an error:
uninitialized constant MyGem::MyPlatformSpecificThing (NameError)
The stack trace indicates the source of the error is the call to init within the DoSomething method.
I am not entirely sure why Ruby is giving me fits here. What am I doing wrong, and how should I be doing this?
edit:
For specifics, I'm referring to the Platform class located here. The above should help narrow down the details of what I'm referring to, but in case anyone wanted/needed to see the specific classes/modules I'm work with.
You've almost got it right. Remember that the require method loads relative to the load path. As you're making a gem you've added the gem lib directory to the load path. Change the require to:
require 'my_gem/bcm2835'
Or for PiPiper:
require 'pi_piper/bcm2835'
This should load only when a driver hasn't been set.
Your pseudo-code is bit incomplete and confusing, but I think this may be the problem. If I am mistaken, seeing your real code as complete as necessary could help.
Check this response as a reference.
Your example shows:
MyGem::MyPlatformSpecificThing.init
However, that format should have Module::Class.method. Your sample shows Module::Module.method.
The error message
uninitialized constant
is very specific in that it is recognizing the call as a constant, not a class.
The error you've specified...
uninitialized constant MyGem::MyPlatformSpecificThing (NameError)
... will only occur if the inner module (PiPiper::Bcm2835) is never actually defined; if the problem was with the actual call to the module function (init), you'd get a different error.
I notice you've commented out the require on line 10, platform.rb:
#require 'bcm2835.rb'
... and required the file elsewhere. Let me guess, this is solving your problem, no?
Taking another look, in its original form the require statement should have failed, unless you've already added the pi_piper directory to $LOAD_PATH. Try changing the lazy require to this:
require './bcm2835.rb'
But note that this will not work either if you change the working directory (Dir.chdir) at any point prior to executing this line.
I've been looking at the Ruby Standard Library Documentation for 1.9.3. I'm wondering how I can find out which libraries I need to explicitly require.
For example, I have been told I need to explicitly require the json library, but not rubygems, although they both appear in the standard library list.
Is there another place I can look for information about the requirements, or even a pry/irb command I can run to see what is already 'required'?
Every library has to be required/loaded, if you want to use it.
Performance-wise, require is smart and will not load libraries if they're already loaded.
However, if you want to check if a library is required you should see the top-level namespace it defines and check if this is defined in your current scope. For example open an IRB session and do:
defined? JSON # => nil (it's not loaded)
require 'json' # => true (load it)
defined? JSON # => "constant" (it's loaded)
require 'json' # => false (it's already loaded, so it's not loaded it again)
It usually doesn't hurt to require things anyway. If they've already been loaded, in general terms, the require statement has no effect.
Some core library components are either loaded automatically or autoloaded by referencing their top-level symbol. This list varies from one version of Ruby to another.
I understand the subtle differences between require, load and autoload in Ruby, but my question is, how do you know which one to use?
Other than being able to "wrap" a load in an anonymous module, require seems to be preferred.
But then autoload allows you to lazy load files -- which sounds fantastic but I'm not sure practically what you gain over require
Is one method preferred over the other? Is there a situation where one method stands out?
Generally, you should use require. load will re-load the code every time, so if you do it from several modules, you will be doing a lot of extra work. The lazyness of autoload sounds nice in theory, but many Ruby modules do things like monkey-patching other classes, which means that the behavior of unrelated parts of your program may depend on whether a given class has been used yet or not.
If you want to make your own automatic reloader that loads your code every time it changes or every time someone hits a URL (for development purposes so you don't have to restart your server every time), then using load for that is reasonable.
mylibrary.rb
puts "I was loaded!"
class MyLibrary
end
Try in irb
irb(main):001:0> require 'mylibrary'
I was loaded!
=> true
irb(main):001:0> autoload :MyLibrary, 'mylibrary'
=> nil
irb(main):002:0> MyLibrary.new
I was loaded!
=> #<MyLibrary:0x0b1jef>
See the difference.
here's what you gain with autoload over require:
autoload is primarily for speeding up the initialization phase of your Ruby program or Rails application. By not loading the resources until they are needed, it can speed up things quite a bit.
Another advantage is that you may not need to load some parts of the code, if the user doesn't use certain features -- thereby improving load time and reducing the memory footprint.
Apart from what others have already told you, future of autoload is uncertain. It was scheduled to be deprecated in Ruby 2.0, but the deprecation wasn't made in time for the 2.0 feature freeze. It is now expected that autoload will be deprecated in Ruby 2.1, but that is not even certain anymore.
Here're the use cases for each method.
load to pick up any changes you made to a file while the program is running.
autoload to speed up the initialization of your library by lazily loading the modules.
require when you want to use external gems.
require_relative for local files relative to the current working directory.
Source: Understanding the load, autoload, require, and require_relative methods in Ruby