I'm doing a Ruby training on Codewars and I'm stuck on something.
I have to do this :
list([ {name: 'Bart'}, {name: 'Lisa'}, {name: 'Maggie'} ])
# returns 'Bart, Lisa & Maggie'
So I tried this code:
def list names
names.map(&:values).flatten.to_sentence(last_word_connector: ' &')
end
But unfortunately, I have this error :
main.rb:4:in `list': undefined method `to_sentence' for ["Bart", "Lisa", "Maggie", "Homer", "Marge"]:Array (NoMethodError)
Did you mean? to_set
from main.rb:6:in `<main>'
I've been searching for hours and I don't understand why 'to_sentence' doesn't work...
Thanks.
Array#to_sentence is an ActiveSupport method. ActiveSupport is a Ruby gem that adds a lot of useful utility methods to existing classes. You'll need to install and require the gem to make sure it's loaded
gem install activesupport
Then, at the top of your file,
require 'active_support/all'
If you're writing a Rails project, then you get ActiveSupport for free. But if you're writing standard Ruby, you have to require it.
Related
I'm confused with the difference between Object#singleton_method and Object#singleton_methods.
I thought that the result in Object#singleton_methods is the true set of !!Object#singleton_method(:name), but it seems to be different.
Here is the example script:
require "active_support/deprecation"
# [:debug=, :debug]
ActiveSupport::Deprecation.singleton_methods(false).grep(/debug/)
# [:debug=, :debug]
ActiveSupport::Deprecation.singleton_methods.grep(/debug/)
begin
ActiveSupport::Deprecation.singleton_method(:debug) # exception
rescue => e
puts e.backtrace
raise
end
Gemfile is
# frozen_string_literal: true
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
# gem "rails"
gem 'activesupport', '5.1.6'
The result is this:
% bundle install
Fetching gem metadata from https://rubygems.org/..............
Resolving dependencies...
Using concurrent-ruby 1.0.5
Using i18n 1.0.0
Using minitest 5.11.3
Using thread_safe 0.3.6
Using tzinfo 1.2.5
Using activesupport 5.1.6
Using bundler 1.16.1
Bundle complete! 1 Gemfile dependency, 7 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
% bundle exec ruby test.rb
test.rb:8:in `singleton_method'
test.rb:8:in `<main>'
Traceback (most recent call last):
1: from test.rb:8:in `<main>'
test.rb:8:in `singleton_method': undefined singleton method `debug' for `ActiveSupport::Deprecation' (NameError)
I expected that ActiveSupport::Deprecation.singleton_method(:debug) would return #<Method: ActiveSupport::Deprecation.debug>, but raise exception.
I don't understand why. Of course, I know the basic usage in singleton_method and singleton_methods:
# everything is OK!
class Sample; end
class << Sample
def test_method; end
end
# These two expressions behave as I expect.
## [:test_method]
Sample.singleton_methods(false).grep(/test_method/)
## #<Method: Sample.test_method>
Sample.singleton_method(:test_method)
Thanks.
Update: It looks like this is a bug in Ruby. Vasiliy Ermolovich has created an issue along with a patch to address it. The fix has already been merged so this will be resolved in an upcoming update.
This isn't a full answer to your question I'm afraid, but after a bit of digging I've been able to make a minimal example that demonstrates the same thing without the dependency on Active Support. I thought this might still be useful to you for your investigations, or might help someone else who can come along with a complete explanation.
It appears that the unexpected behaviour of singleton_method comes from use of Module.prepend which ActiveSupport::Deprecation uses here.
The same error can be seen with this small example:
module Empty; end
class MyClass
singleton_class.prepend(Empty)
def self.my_method
puts "my method called"
end
end
p MyClass.singleton_methods(:false)
m = MyClass.singleton_method(:my_method)
m.call
Running this gives:
❯ ruby example.rb
[:my_method]
Traceback (most recent call last):
1: from example.rb:11:in `<main>'
example.rb:11:in `singleton_method': undefined singleton method `my_method' for
`MyClass' (NameError)
With the call to prepend removed this runs as you would expect:
❯ ruby example.rb
[:my_method]
my method called
I have the following:
input = gets.chomp
basket = input.strip.split(',')
basket.delete_if(&:blank?)
which should allow you to do: cat, dog,,
from there we can split that up, strip it clean and split it on , and then check for empty elements and remove them.
but this code gives me an error: delete_if: undefined method 'blank?' for "cat":String (NoMethodError) which does not make any sense to me. I thought that the whole purpose of blank? or empty? was to say remove this element if this is true.
ActiveSupport that comes with Rails adds the blank? method to String and many other classes. Since this method is not part of Ruby core, you need to have Rails or the ActiveSupport gem installed. If that gem is installed than you can require ActiveSupport's core extensions like this:
> 'foo'.blank?
# => NoMethodError: undefined method `blank?' for "foo":String
> require 'active_support/core_ext'
# => true
> 'foo'.blank?
# => false
require 'active_support'
require 'active_support/core_ext'
import "active_support" first
blank? is a method augmented to the String class from rails. It's not part of the ruby String class by default.
I'm trying to understand how method invocation works in Ruby objects. Ruby docs list a bunch of methods to execute on ruby objects. When I try one of them
puts RUBY_VERSION
puts Time.new(2008,6,21, 13,30,0, "+09:00").utc.seconds_since_midnight
I get the following output
1.9.3
bin/musor.rb:14:in `<main>': undefined method `seconds_since_midnight' for 2008-06-21 13:30:00 +0900:Time (NoMethodError)
What's wrong with the call I make?
seconds_since_midnight is Time extension added by rails. If you want to use it, you will need to add require 'activesupport/core_ext' and install activesupport gem first.
If I require ap, irb returns true (I assume telling me that the awesomeprint gem has been successfully loaded). However if I issue the command ap f where f is a hash, I get:
NoMethodError: undefined method `ap' for main:Object
from (irb):5
from /usr/local/bin/irb:12:in `<main>'
Thoughts?
Here is my $LOAD_PATH:
"/usr/local/lib/ruby/gems/1.9.1/gems/multi_json-1.1.0/lib", "/usr/local/lib/ruby/gems/1.9.1/gems/multi_xml-0.4.1/lib", "/usr/local/lib/ruby/gems/1.9.1/gems/httparty-0.8.1/lib", "/usr/local/lib/ruby/gems/1.9.1/gems/ap-0.1.1/lib", "/usr/local/lib/ruby/gems/1.9.1/gems/psych-1.2.2/lib", "/usr/local/lib/ruby/gems/1.9.1/gems/crack-0.3.1/lib", "/usr/local/lib/ruby/site_ruby/1.9.1", "/usr/local/lib/ruby/site_ruby/1.9.1/x86_64-darwin11.3.0", "/usr/local/lib/ruby/site_ruby", "/usr/local/lib/ruby/vendor_ruby/1.9.1", "/usr/local/lib/ruby/vendor_ruby/1.9.1/x86_64-darwin11.3.0", "/usr/local/lib/ruby/vendor_ruby", "/usr/local/lib/ruby/1.9.1", "/usr/local/lib/ruby/1.9.1/x86_64-darwin11.3.0"
It seems ap is the 4th one.
The gem you want is called awesome_print, so sudo gem install awesome_print should fix it. May want to remove the other gem 'ap' which seems to be some http and xml related gem.
My code:
require 'rubygems'
require 'basecamp'
basecamp = Basecamp.establish_connection!('example.basecamphq.com', 'example', '123456', true)
projects = Basecamp::Project.find(:all)
projects.inspect
It gives:
/Users/kir/.rvm/gems/ruby-1.8.7-p352#project/gems/activeresource-3.1.0/lib/active_resource/base.rb:922:in `instantiate_collection': undefined method `collect!' for #<Hash:0x105faa450> (NoMethodError)
from /Users/kir/.rvm/gems/ruby-1.8.7-p352#project/gems/activeresource-3.1.0/lib/active_resource/base.rb:894:in `find_every'
from /Users/kir/.rvm/gems/ruby-1.8.7-p352#project/gems/activeresource-3.1.0/lib/active_resource/base.rb:806:in `find'
from bs.rb:4
What's wrong with my code?
There were some problems with the basecamp wrapper gem and rails >= 3.1.x. The "undefined method `collect!'" error was one of them. I pushed some fixes and bumped the gem version to 0.0.7 which should solve that and other problems.