Trying to learn ruby through rspec puzzles. Help with this one (class related)?

So, I am learning ruby outside of my job, which is not programming
related. Eventually want to move into programming though for a job,
because I do enjoy this stuff.

However, I am currently a little confused on the current puzzle I’m
working on and want to make sure I’m going down the right path.

Basically, I will give a snippet of the rspec puzzle that I’m working on
right now (obivously there is more, but doing this to save space and
because I feel if I can put down the correct path, I can try to figure
the rest out):

describe Name do

before do
@name = Name.new
end

describe ‘title’ do
it ‘should capitalize’ do
@name.title = “joe”
@name.title.should == “Joe”
end

it 'should capitalize every word' do
  @name.title = "stuart smith"
  @name.title.should == "Stuart Smith"
end

end

My solution so far has been this:

class Name
attr_accessor :title

def initialize(title=nil)
@title=title
end

def title
@title.capitalize
end

end

I have always been used to setting up classes like this. Where I first
make an initialize method and then “accessor” methods (I think that is
the name for these. The methods that actually do stuff for classes).

Am I on the correct path here, or am I setting up this class all wrong
for these tests? The above passes the first test. I feel I may need to
do a loop for the second test.

Can someone let me know if I am doing this all wrong? Or give me some
guidance on how to write good code for this situation?

Thanks for any help.

On Sun, Jan 19, 2014 at 8:23 PM, JD JD [email protected] wrote:

def initialize(title=nil)
@title=title
end

def title
@title.capitalize
end

Looks reasonable to me. (Except that capitalize will only do the
first word. For the second, you might indeed use a loop, or map, or
some other such construct. If you’re doing it in the context of
Rails, there’s another string method you can use that will do each
word.) What sprang to my mind was to set it that way in the setter
(i.e., @title = title.capitalize) and retrieve it as-is (i.e., after
it’s been capitalized by initialize), but depending on the use-case,
doing the casing on retrieval could be better…

-Dave

Well, I ultametely solved the puzzle by playing around with stuff. This
was the code I ended up with. But, is this what the class should look
like, or is this bad code? Again, it passes all the tests (again, I
will s). The goal of this program basically is that if you give it some
title, it turns it into the correct title following “title rules”. So,
first word has to be capitalized no matter what, and words contained in
the array_words list are suppose to always be lowercase. Is there
anything wrong with this code or how my class is structured? Its solves
the problem, but don’t want it if its bad structure for a class:

class Name
attr_accessor :title

def initialize(title=nil)
@title=title
end

def title
array_words=%w(and of in the a an)
@[email protected](/\w+/)
word_number=0
@title2.each do |title|
if array_words.include?(title) && word_number >= 1
title
word_number+=1
else
title.capitalize!
word_number+=1
end
end
@title2.join(" ")
end

end

Also, something else that confuses me a bit is the need for the @title2.
I noticed if if I just make them regular variables (aka, title2 without
the @) the code will not pass anymore.

I understand what the @ symbols are for. They are instance variables
(unless again using wrong termonology) for that class. I can understand
the point of them with the initialize method.

But, why is it necessary in the def name method?

Sorry, I guess I know how to make the code work by typing all that out,
but I guess I don’t understand the “why” behind what I did.

On Mon, Jan 20, 2014 at 3:35 AM, JD JD [email protected] wrote:

Sorry, I guess I know how to make the code work by typing all that out,
but I guess I don’t understand the “why” behind what I did.

You shouldn’t need to use instance variables if you only use them
within one method. So a local variable should work. Can you show the
code and the test that doesn’t pass?

Also, some little comments:

def title
array_words=%w(and of in the a an)

array_words is not a good name, stop_words or something like that

would be better

also to check for inclusion, a Set would be more efficient

@[email protected](/\w+/)
word_number=0
@title2.each do |title|

instead of word_number you could use each_with_index. It will

maintain the index for you

also, using title as the local variable of the block is confusing, I

would call it word, for example

  if array_words.include?(title) && word_number >= 1
    title
    word_number+=1
  else
    title.capitalize!
    word_number+=1
  end
end
@title2.join(" ")

end

Jesus.

Dear JD,

Perhaps you can get to something really simpler than that, like …

“Take the title and globally substitute each word matched with the
capitalized match”

@title = title.gsub(/\w+/) { |match| match.capitalize }

:wink:

Complete code to pass the test would be something like:

class Name

attr_reader :title

def title=(title)
@title = title.gsub(/\w+/) { |match| match.capitalize }
end
end

Abinoam Jr.

On Mon, Jan 20, 2014 at 6:12 AM, Jess Gabriel y Galn

@Jesus Gabriel y Galan: Sorry, I rain that code again. It looks like
@title2 is not necessary.

I will try to take a look at each_with_index as well.

@Abinoam Jr: Thanks or the reply. However, there were other tests.
Didn’t include it for space saving time. I appreciate the input though.