How does one create an object from a class within a gem? - ruby

Lets say you write a gem containing classes within a module. If one installs that gem and wishes to create an object instance from that class, how do they successfully do that in another rb document? Here is my gem class.
require "Sentencemate/version"
module Sentencemate
#Object used to emulate a single word in text.
class Word
def initialize(word)
#word = word
end
def append(str)
#word = #word << str
return #word
end
def get
return #word
end
def setword(str)
#word = str
end
def tag(str)
#tag = str
end
end
# Object used to emulate a sentence in text.
class Sentence
def initialize(statement)
#sentence = statement
statement = statement.chop
statement = statement.downcase
lst = statement.split(" ")
#words = []
for elem in lst
#words << Word.new(elem)
end
if #sentence[#sentence.length-1] == "?"
#question = true
else
#question = false
end
end
def addword(str)
#words << Word.new(str)
end
def addword_to_place(str, i)
#words.insert(i, Word.new(str))
end
def set_word(i, other)
#words[i].setword(other)
end
def [](i)
#words[i].get()
end
def length
#words.length
end
def addpunc(symbol)
#words[self.length-1].setword(#words[self.length-1].get << symbol)
end
def checkforword(str)
for elem in #words
if elem.get == str
return true
end
end
return false
end
end
end
in Rubymine, I will try the following in the Irb console:
/usr/bin/ruby -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) /usr/bin/irb --prompt simple
Switch to inspect mode.
>> require 'Sentencemate'
=> true
>> varfortesting = Sentence.new("The moon is red.")
NameError: uninitialized constant Sentence
from (irb):2
from /usr/bin/irb:12:in `<top (required)>'
from -e:1:in `load'
from -e:1:in `<main>'
What would be the proper way to be able to use the classes in the gem that I installed?

In your Sentence class
#words << Word.new(elem)
Word is resolved correctly because ruby looks in current namespace first (that being Sentencemate module).
Outside of that module, one has to use fully-qualified names, such as Sentencemate::Word. This is necessary to differentiate this Word from a dozen other Word classes user's app might have.

Related

Why instance variables can be modified through a field reader with the << operator?

Consider the following class.
class Test
attr_reader :word
def initialize(word)
#word = word
end
def append_word(token)
word << token
end
end
Consider a sample usage of the class.
2.4.0 :001 > t = Test.new('Hello')
=> #<Test:0x007f7f09902970 #word="Hello">
2.4.0 :002 > t.append_word(' world!')
=> "Hello world!"
2.4.0 :003 > t.word
=> "Hello world!"
2.4.0 :004 >
I am new to Ruby. I don't understand why I can use the append_word instance method to modify the instance variable #word of a Test instance. word in append_word seems to be a field reader. My understanding is that a field reader is for reading only. How can word << token in append_word modify the value of #word in a Test instance?
Your #word references an object in memory. This object happens to be a Hello! string. Your class does not allow to (easily) set a new object for your #word instance variable, but nothing currently stops you from modifying the object directly. If you wish for the object to not be modifiable, you could .freeze it:
class Test
attr_reader :word
def initialize(word)
#word = word.freeze
end
def append_word(token)
word << token
end
end
> Test.new("Hello").append_word("world!")
# FrozenError (can't modify frozen String)

How to have an object(class) be a parameter for another object(class) in Ruby

I am new to Ruby so I am not exactly sure what I am doing wrong or violating.
I have two classes in my example, Deliverable and Pillar.
A pillar object can contain one or more deliverables.
class Deliverable
def initialize (name, state, pillar)
#name = name
#state = state
#pillarNumber = pillar
end
def getName
#name
end
def state
#state
end
def pillarNumber
#pillarNumber
end
end
class Pillar
def initalize (name, mine)
#name = name
#mine = mine
end
def getName
#name
end
def getDeliverable
#mine
end
def getDeliverableName
#mine.getName
end
end
aDel = Deliverable.new("Deliverable", 0, 1)
puts "Deliverable Name: " + aDel.getName
aPil = Pillar.new("Pillar", aDel)
puts "Pillar Name: " + aPil.getName + "\n"
When I run this code I get this error:
pillar.rb:46:in `initialize': wrong number of arguments (2 for 0) (ArgumentError)
from pillar.rb:46:in `new'
from pillar.rb:46:in `<main>'
Any advise on what I am doing wrong?
You mispelled the name of the constructor for Pillar
# ā‡“ NOTE MISSED ā€œiā€ HERE
def initialize (name, mine)

Ruby - Can't convert string to IO error in simple program

I'm trying to make a simple DSL and the following code works in returning an array of the "Pizza" in the console.
class PizzaIngredients
def initialize
##fullOrder = []
end
#this takes in our toppings and creates the touple
def spread (topping)
##fullOrder << "Spread #{topping}"
end
def bake
##fullOrder
end
#this handles whatever is not a spread and is expected to take in a list in the format topping top1, top2, top3 and so on
def toppings (*toppingList)
array = []
toppingList.each {|topping| array << "topping #{topping}"}
array.each {|iter| ##fullOrder << iter}
end
end
# hadels if any methods are missing
def method_missing(name, *args, &block)
"#{name}"
end
#this is our entry into the dsl or manages it
module Pizza #smokestack
#this keeps a list of your order preserving the order in which the components where added
##order = []
def self.create(&block)
if block_given?
pizza = PizzaIngredients.new
##order << pizza.instance_eval(&block)
else
puts "making the pizza with no block"
end
end
end
def create (ingnore_param, &block)
Pizza.create(&block)
end
create pizza do
spread cheese
spread sauce
toppings oregano, green_pepper, onions, jalapenos
spread sauce
bake
end
However, when I try to run tests using Rake, I get the following errors:
C:/Ruby21-x64/bin/ruby.exe -w -I"lib" -I"C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/rake-10.4.2/lib" "C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/rake-10.4.2/lib/rake/rake_test_loader.rb" "test/PizzaBuilder_test.rb"
C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/test-unit-3.0.9/lib/test/unit/autorunner.rb:142:in `exist?': can't convert String to IO (String#to_io gives String) (TypeError)
from C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/test-unit-3.0.9/lib/test/unit/autorunner.rb:142:in `initialize'
from C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/test-unit-3.0.9/lib/test/unit/autorunner.rb:55:in `new'
from C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/test-unit-3.0.9/lib/test/unit/autorunner.rb:55:in `run'
from C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/test-unit-3.0.9/lib/test/unit.rb:502:in `block (2 levels) in <top (required)>'
rake aborted!
Command failed with status (1): [ruby -w -I"lib" -I"C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/rake-10.4.2/lib" "C:/Ruby21-x64/lib/ruby/gems/2.1.0/gems/rake-10.4.2/lib/rake/rake_test_loader.rb" "test/PizzaBuilder_test.rb" ]
This is PizzaBuilder_test.rb, I took out the tests to try and make it work but no luck.
require "test/unit"
require "./main/PizzaBuilder"
class TestMyApplication < Test::Unit::TestCase
def testCase
assert(true, "dummy case failed")
end
end
This is the Rakefile:
require 'rake'
require 'rake/testtask'
Rake::TestTask.new do |t|
t.libs = ["lib"]
t.warning = true
t.verbose = true
t.test_files = FileList['test/*_test.rb']
end
task default:[:test]
I think your problem is the way you're defining method_missing you're not defining it inside of a module or class, so it's being defined for the main Object.
It's not a great idea to override method_missing, especially as a catch all like you did. I would recommend rewriting your code to use strings instead of overwriting method_missing.
Also your create method seems unnecessary. If you remove that the code below should work fine:
class PizzaIngredients
def initialize
##fullOrder = []
end
#this takes in our toppings and creates the touple
def spread (topping)
##fullOrder << "Spread #{topping}"
end
def bake
##fullOrder
end
#this handles whatever is not a spread and is expected to take in a list in the format topping top1, top2, top3 and so on
def toppings (*toppingList)
array = []
toppingList.each {|topping| array << "topping #{topping}"}
array.each {|iter| ##fullOrder << iter}
end
end
#this is our entry into the dsl or manages it
module Pizza #smokestack
#this keeps a list of your order preserving the order in which the components where added
##order = []
def self.create(&block)
if block_given?
pizza = PizzaIngredients.new
##order << pizza.instance_eval(&block)
else
puts "making the pizza with no block"
end
end
end
Pizza.create do
spread 'cheese'
spread 'sauce'
toppings 'oregano', 'green pepper', 'onions', 'jalapenos'
spread 'sauce'
bake
end

run a ruby project on ruby mine

i am new to ruby programming. i wrote a little program to recursively count blobs in a two dimensional array. it contains two classes, cell and blobs. i am getting the following error and i dont know what it means or how to fix it.
attached is my code and the error.
Cell Class
class Cell
attr_accessor :data,:visited,:row,:col
def initialize(data, row, col)
#data = data
#visited = false
#row = row
#col = col
end
def to_s
self.data.to_s
end
end
Blob class
class Blobs
require ./Cell
#cells = Array.new(10){Array.new(10)}
def separate(percentage)
for i in 0..10
for i in 0..10
random = Random.rand(0,100)
if random < percentage
#cells[i][j] = Cell.new('x',i,j)
else
#cells[i][j] = Cell.new(nil, i, j)
end
end
end
end
def markBlob(currentCell)
if currentCell.visited
return
end
currentCell.visited = true
if currentCell.data.nil?
return
end
if currentCell.row >0
markBlob(#cells[currentCell.row-1][currentCell.col])
end
if currentCell.row <#cells.size-1
markBlob(#cells[currentCell.row+1][currentCell.col])
end
if currentCell.col>0
markBlob(#cells[currentCell.row][currentCell.col-1])
end
if currentCell.col<#cells.size-1
markBlob(#cells[currentCell.row][currentCell.col+1])
end
end
def countblobs
count = 0
for i in 0..10
for j in 0..10
cell = #cells[i][j]
if !cell.visited && cell.data.nil?
count++
markBlob(cell)
end
end
end
return count
end
def to_s
for i in 0..10
for j in 0..10
if #cells[i][j].data.nil?
puts '- '
else
puts #cells[i][j].data + ' '
end
end
puts "\n"
end
end
blob = Blobs.new
number = blob
puts number
end
this is the error i am getting:
C:\Ruby22\bin\ruby.exe -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) C:/Users/Nechama/RubymineProjects/blobs/blobs.rb
C:/Ruby22/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb:38:in `require': wrong number of arguments (0 for 1) (ArgumentError)
from C:/Users/Nechama/RubymineProjects/blobs/blobs.rb:3:in `<class:Blobs>'
from C:/Users/Nechama/RubymineProjects/blobs/blobs.rb:2:in `<top (required)>'
from -e:1:in `load'
from -e:1:in `<main>'
Process finished with exit code 1
require should get string as an argument.
Use require_relative to cell file
require_relative 'cell'
and put it above class Blobs.
More about Including Other Files In Ruby

NameError: uninitialized constant Song ...Programming Ruby

trying to pick up ruby through this programming ruby site and i'm stuck on this syntax
class SongList
def initialize
#songs = Array.new
end
def append(aSong)
#songs.push(aSong)
self
end
def deleteFirst
#songs.shift
end
def deleteLast
#songs.pop
end
end
When i go to add a song...
list = SongList.new
list.append(Song.new('title1', 'artist1', 1))
I get this error message:
NameError: uninitialized constant Song ...Programming Ruby
I saw that i need to require the variable Song, but I'm not sure where to do it within the SongList class....
You can use Ruby Struct class :
A Struct is a convenient way to bundle a number of attributes together, using accessor methods, without having to write an explicit class.
class SongList
def initialize
#songs = [] # use [] instead of Array.new
end
def append(aSong)
#songs.push(aSong)
self
end
def delete_first
#songs.shift
end
def delete_last
#songs.pop
end
end
Song = Struct.new(:song_name, :singer, :var)
list = SongList.new
list.append(Song.new('title1', 'artist1', 1))
# => #<SongList:0x9763870
# #songs=[#<struct Song song_name="title1", singer="artist1", var=1>]> var=1>]>

Resources