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.

···

--
Posted via http://www.ruby-forum.com/.

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

···

On Sun, Jan 19, 2014 at 8:23 PM, JD JD <lists@ruby-forum.com> wrote:

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

  def title
    @title.capitalize
  end

--
Dave Aronson, the T. Rex of Codosaurus LLC (codosaur.us),
freelance software developer, and creator of these sites:
PullRequestRoulette.com, blog.codosaur.us, & Dare2XL.com.

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)
    @title2=@title.scan(/\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

···

--
Posted via http://www.ruby-forum.com/.

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.

···

--
Posted via http://www.ruby-forum.com/.

@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.

···

--
Posted via http://www.ruby-forum.com/.

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

    @title2=@title.scan(/\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.

···

On Mon, Jan 20, 2014 at 3:35 AM, JD JD <lists@ruby-forum.com> wrote:

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.

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, Jesús Gabriel y Galán <jgabrielygalan@gmail.com> wrote:

On Mon, Jan 20, 2014 at 3:35 AM, JD JD <lists@ruby-forum.com> wrote:

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.

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

    @title2=@title.scan(/\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.