I'm trying to learn Ruby, but have a previous Java background, and I thought the best way to learn Ruby is to re-implement an old side project.
The problem that I am facing is that I get the following error
ATMSystem.rb:4:in `show_start_menu': uninitialized constant ATMSystem::BankComputer (NameError)
I am using two classes, the first is the BankComputer class, and the second is ATMSystem.
class BankComputer
attr_accessor :bank_id, :customer_accounts
##card_number = 1000
def initialize(bank_id)
#bank_id = bank_id
end
def self.card_number
##card_number
end
def create_card_number
##card_number += 1
end
bc = BankComputer.new(100)
puts bc.bank_id
puts BankComputer.card_number
end
The second class:
include BankComputer.rb
class ATMSystem
def show_start_menu
bank_computer_1 = BankComputer.new(1)
end
system = ATMSystem.new()
system.show_start_menu
end
Both classes are in the same directory.
Why doesn't "include BankComputer.rb" work?
How do I import this class correctly?
I found the answer, all you have to do is
require './ClassName'
Related
Solved. I didn't have the initialization right, which gave the noMethodError. Then I was changing an array, but checking a variable that referred to a position in the array, and that variable had not been reassigned.
Edited to initialize bookPagesInfo, bookChaptersInfo, editPagesInfo, and editChapterInfo as suggested. Still gives the same NoMethod Error.
I have a book with page and chapter info, and want to be able to apply edits that change the number of pages, introPages, chapters, and povs.
class Book
attr_accessor :pages, :chapters, :bookPagesInfo, :bookChaptersInfo, :introPages, :povs
def initialize(bookPagesInfo, bookChaptersInfo)
#bookPagesInfo = bookPagesInfo
#bookChaptersInfo = bookChaptersInfo
#pages = bookPagesInfo[0]
#introPages = bookPagesInfo[1]
#chapters = bookChaptersInfo[0]
#povs = bookChaptersInfo[1]
end
def applyEdit(edit)
#pages += edit.new_pages
end
end
class Edit
attr_accessor :new_pages, :new_chapters, :editPagesInfo, :editChaptersInfo, :new_intro_pages, :new_povs
def initialize(editPagesInfo, editChaptersInfo)
#editPagesInfo = editPagesInfo
#editChaptersInfo = editChaptersInfo
#new_pages = editPagesInfo[0]
#new_intro_pages = editPagesInfo[1]
#new_chapters = editChaptersInfo[0]
#new_povs = editChaptersInfo[1]
end
end
The above code works for editing just number of pages. However, if I change my applyEdit method to iterate over the bookPagesInfo array, I can't get it to work. Running applyEdit below gives a nonfatal error.
def applyEdit(edit)
#bookPagesInfo.each_with_index do {|stat, idx| stat += edit.bookPagesInfo[idx]}
end
## gives undefined method `each_with_index' for nil:NilClass (NoMethodError), but
## my understanding is as long as bookPagesInfo was initialized as an array, it
## should be an array, not nilClass
I'm pretty new to classes (and this website, sorry for formatting). Thanks for the help.
You've got attr_accessors defined for :bookPagesInfo and :bookChaptersInfo, which will give you reader and writer methods, but it won't set #bookPagesInfo and #bookChaptersInfo for you in the initialize method - you need to do that yourself. So, when you try to read from the instance variable in applyEdit, you're reading nil.
Try adding
#bookPagesInfo = bookPagesInfo
#bookChaptersInfo = bookChaptersInfo
in Book#initialize.
Given I have defined the following modules in my features/support directory
apiworld.rb
module Api
class User
...
end
...
end
and also
webworld.rb
module Web
class User
...
end
...
end
in my env.rb file I have
env.rb
require File.expand_path(File.dirname(__FILE__)+'/webworld')
require File.expand_path(File.dirname(__FILE__)+'/apiworld')
if ENV['USE_API'] == 1
World(Api)
else
World(Web)
end
So if I try to use this construct in a step definition like
Given /^a user is created$/ do
#user = User.new
end
And run cucumber, my ruby interpreter will give me the this output
uninitialized constant User (NameError)
./features/step_definitions/user_steps.rb:17: [...]
How to make this work? Is there a way or am I thinking i the wrong direction. I am pretty new to ruby - so I don't really know what it can do and what it can not do.
You can't use World for this. World is for mixing methods into the self object in each stepdef.
Instead of this:
if ENV['USE_API'] == 1
World(Api)
else
World(Web)
end
Try this:
User = ENV['USE_API'] == 1 ? Api::User : Web::User
I have the HTTParty gem on my system and I can use it from within rails.
Now I want to use it standalone.
I am trying:
class Stuff
include HTTParty
def self.y
HTTParty.get('http://www.google.com')
end
end
Stuff.y
but I get
$ ruby test_httparty.rb
test_httparty.rb:2:in `<class:Stuff>': uninitialized constant Stuff::HTTParty (NameError)
from test_httparty.rb:1:in `<main>'
07:46:52 durrantm Castle2012 /home/durrantm/Dropnot/_/rails_apps/linker 73845718_get_method
$
You have to require 'httparty':
require 'httparty'
class Stuff
include HTTParty
# ...
end
Its all because of the include which exists with in the class
If you include a class with a module, that means you're "bringing in" the module's methods as instance methods.
If you need more clarity on include and require
I request you to refer to this wonderful SO Posting
What is the difference between include and require in Ruby?
Here is an example which I have taken from the same posting
module A
def say
puts "this is module A"
end
end
class B
include A
end
class C
extend A
end
B.say => undefined method 'say' for B:Class
B.new.say => this is module A
C.say => this is module A
C.new.say => undefined method 'say' for C:Class
I am receiving the following error when running my below ruby script:
s3parse.rb:12:in `block in <class:AccountLog>': undefined method `extract_account_id' for AccountLog:Class (NoMethodError)
I dont think it should be a class method, is there a reason its not taking my method into account?
class AccountLog
attr_accessor :bytes, :account_id, :date
def extract_account_id(line)
line.match(%r{accounts/(\d+)}).captures.join.to_i
end
s3log = File.open('vidcoder.txt').each do |line|
account_log = AccountLog.new
account_log.date = line.match(%r{\[[^:]*}).to_s.delete"[" #need to finish this regex to make it work
account_log.account_id = extract_account_id(line)
account_log.bytes = line.match(%r{^.*\s+HTTP.*\s+-\s+(\d+)\s+}).captures.join.to_i
puts "\n"
puts "The api request on #{account_log.date} was fromm account number #{account_log.account_id} and the bytes were #{account_log.bytes}"
end
end
def extract_account_id will define an instance method.
In the way you call it, you need a class method instead.
Define it like this:
def self.extract_account_id(line)
or, as you already have an AccountLog instance, use it to call extract_account_id:
account_log.account_id = account_log.extract_account_id(line)
Please note that with second way you do not need to alter method definition, just call extract_account_id via account_log instance.
And i guess you would want to put s3log = File... outside class definition.
Or use a constant instead: S3log = ...
Then you'll can access it as AccountLog::S3log
Is there any reason you don't think it should be a class method? You are using it in the context of a class method and that's why it it's saying no such method for class AccountLog.
If you name your method as self.extract_account_id(line) I'm sure it will work.
From what you are trying to do I think this is what you are looking for?
class AccountLog
attr_accessor :bytes, :account_id, :date
def self.extract_account_id(line)
line.match(%r{accounts/(\d+)}).captures.join.to_i
end
end
s3log = File.open('vidcoder.txt').each do |line|
account_log = AccountLog.new
account_log.date = line.match(%r{\[[^:]*}).to_s.delete"[" #need to finish this regex to make it work
account_log.account_id = extract_account_id(line)
account_log.bytes = line.match(%r{^.*\s+HTTP.*\s+-\s+(\d+)\s+}).captures.join.to_i
puts "\n"
puts "The api request on #{account_log.date} was fromm account number #{account_log.account_id} and the bytes were #{account_log.bytes}"
end
While you could take the class method approach, there seems to be a little more going on.
You should put the extraction logic in a method in itself rather than let it hangout in your class. Then outside of the class, have an instance of AccountLog where you can call on the methods for log and account id extraction. At that point you can do something with those values.
Class method or not is a detail we can explore after the class is a bit more clean I think.
I'm trying to do some monkey patching in ActiveShipping UPS class .
I need to add a class level method (starting with .self), so here it's what I'm trying to do:
module ActiveMerchant
module Shipping
class UPS < Carrier
def self.process_request(receiver, sender, packages, options = {})
# some code
end
def regular_method
"foobar"
end
end
end
end
Unfortunately when I'm trying to use it:
ActiveMerchant::Shipping::UPS.process_request(receiver etc)
I get an error:
NoMethodError: undefined method `process_request' for ActiveMerchant::Shipping::UPS:Class
from (irb):6
from C:/Ruby19/bin/irb.bat:19:in `<main>'
There is no class method named process_request in original class.
In original UPS class provided in gem there is one static method defined self.retry_safe = true
and I can use it without errors.
I can also use regular_method after creating instance of UPS class.
More details provided:
I'm working with Rails 2.3 ( :-( ) and Ruby 1.9.2. I have no influce on environment.
Monkey patched code is under plugins/my_plugin/lib/active_shipping/ext/carriers/ups.rb
In /active_shipping I have file named extensions.rb in which i have:
require 'active_shipping'
require_relative 'ext/carriers'
require_relative 'ext/carriers/ups'
It deals with loading everything properly (I suppose basing on regular_method beheaviour from first chunk of code in my question).
I try to invoke process_request in one of my Controllers. This part is little tricky, beacuse i'm using sth like this:
MyModel.courier_service.process_request(parameters)
where courier_service, in this case holds the ActiveMerchant::Shipping::UPS class.
I'm still a newbie in Ruby and don't know what sort of details i should provide.
Maybe you want to do it in another way
File patch_classes.rb:
module ActiveMerchantExpand
module Shipping
module ClassMethods
def self.process_request(receiver, sender, packages, options = {})
# some code
end
end
module InstanceMethods
def regular_method
"foobar"
end
end
def self.included(receiver)
receiver.extend ClassMethods
receiver.send :include, InstanceMethods
end
end
end
Then you have to load your class "ActiveMerchant::Shipping::UPS"
and after that you can attach your methods to your class via
Rails.configuration.to_prepare do
require_dependency [[file for ActiveMerchant::Shipping::UPS]]
require 'patch_classes' )
ActiveMerchant::Shipping::UPS.send(:include, ::ActiveMerchantExpand::Shipping)
end
This is from rails plugin writing, i hope this helps.
regards tingel2k
Do you explicitly require file with your monkey patch? If you just put it under your app or lib path without requiring, it wouldn't load because constant ActiveMerchant::Shipping::UPS is defined in gem and it doesn't trigger dependency resolution mechanism.