RSPEC 4 - book titles

a couple of questions here.

  1. can someone explain (&:downcase)? It makes sense in that you want to make sure all of the letters are lowercase going in to title_words, but when we’ve used the ampersand before it has been for procs, but the colon makes me think of symbols… just looking for some clarification on that syntax

  2. in the Classes section, it seemed like an initialize method was necessary, yet there is none in the solution… some clarification on that would be nice

  3. the instance variable @book is used in the specs, but is not defined anywhere in the solution. the method in the solution then returns the value of @title, but i’m curious as to why that needs to be an instance variable.

Thanks!

Update… I believe I understand the @book. Because the specs are going to be using setting multiple book titles throughout the testing process, it’s necessary/beneficial to have that variable declared/available in each test? In each test, a new Book object is created (the lower case titles) and stored in the @book instance variable

But now I’m getting myself even more twisted, because the attr_reader used in the solution is a getter shortcut, but then we use the @title instance method in a setter method (title=) … is there a reason we wouldn’t just use attr_accessor :title instead?

Is it because the getter method is straightforward and can be done by the shortcut attr_reader instead of typing;

def title
@title
end

but the setter method is going to be complex because it needs to put the title together in the appropriate way, and the shortcut attr_writer, which is the same as typing…
def title=(value)
@title = value
end
…wouldn’t suffice for the changes that we need to make?

1

(&:downcase) just calls downcase on every element so ["A", "b", "C"].map(&:downcase) would return ["a", "b", "c"]

The ampersand here actually does mean the same thing as it does when you’re working with procs: turn the following into a proc. The only reason this works though, is because of a special way Symbol implmenents to_proc.

For simplicity you can just think of it as a special shorthand syntax. You don’t really need to know how it works. You just need to know what it does.

2

I need more information. What do you mean by “the Classes section”? They all have to do with classes. Also, why do you feel an initialize method should be necessary?

3

Looks like you figured this one out. @book is defined in the spec file. It’s not trying to access a variable from the lib file, it’s just a new variable.

4

Yes, the setter method needs extra code so it has to be defined manually.

In the Classes chapter of the Alpha Curriculum, more specifically in the Classes 1 section, the material states that the class “must have a set of instructions for how an object should be constructed and how it should store information. These instructions are stored in a method called initialize.”

It seems to imply that the initialize method is necessary for setting up the initial state of the class

Ah, yes, that is misleading. The initialize method is optional. Ruby does do some initialization behind the scenes. Maybe that’s what it’s referring to.

I’m unable to solve the books problem in rspec4.
I have spent a lot of time on this.
Could anyone help me in this?

Thanks,
Nathasha

Hi @nathashas1 :slight_smile: If you’re still stuck on rspec4, it might be easier to help if you put up some of the code you’re working on along with some information about what you’ve tried and where you might be getting hung up on.

I did not know they had given solution as well. I went through the solution and figured what was going wrong with my solution

Thank you for asking.

Hi, I have several questions about the different types of variables in the book titles exercise. I’m not sure when and when not to put an ampersand before “title”. I’m also not quite sure what attr_accessor actually does. In the “classes 1” lesson it says it is shorthand for some piece of code but it was not clear exactly which piece of code it replaces. Also, in the solution, they define LOWER_WORDS outside of the title method, but I did that and it gives me an undefined local variable error when I try to use the variable in the title method.

BTW this is where I’m at so far:

class Book
small_words = [‘a’, ‘an’, ‘and’, ‘it’, ‘of’, ‘the’, ‘in’]

attr_accessor :title

attr_accessor :title is shorthand for below?

def title=(value)

@title = value

end

def title
words = @title.split.map(&:capitalize)

title_words = words.map.with_index do |word, idx|
  if idx != 0 && small_words.include?(word)
    word.downcase
  else
    word
  end
end

title_words.join(" ")

end
end

I take it that by ampersand you mean at sign? An ampersand is &. An at sign is @.

@title refers to the instance variable. title without the @ refers to the method. So it just depends on what you’re trying to do. If you have a title method that does somthing special besides just returning @title, then you will probably want to use that. If your title method just returns @title then it doesn’t really matter which one you use because they refer to the same thing.

attr_accessor :title is shorthand for

def title
  @title
end

def title=(value)
  @title = value
end

So it defines both a getter and a setter for title.

In ruby, any variable that starts with a capital letter is a constant. So LOWER_WORDS is a constant, but small_words is not. That’s why it doesn’t work. It needs to be a constant. When making a constant you CAN just capitalize the first letter like this SmallWords, but don’t. It’s conventional to name only classes and modules that way. For any other constant name it like this: SMALL_WORDS

Thank you! Yes, I did mean to say the at sign. Thank you for clarifying the constants. So, specifically, should @title only be used at the end of the method to return the instance variable? I put it in the first line of my method where I defined “words”, and it seemed to work fine, but I noticed the solution only used the at sign at the end when they are returning the instance variable, @title.
The other thing I’m still not clear on is why we still need to put attr_accessor. It seems like the piece that it replaces is still there. We are still doing:
def title=(title)
(method body)
@title = title_words.join(" ")
end
Without attr_accessor would we need those two methods that you said it replaces, in addition to this method?

Yeah, if you have reader and writer methods, the only time you need to use the @ version of the variable is inside those methods.

About attr methods:

attr_reader :title will define this method

def title
  @title
end

attr_writer :title will define this method

def title=(value)
  @title = value
end

attr_accessor :title will define both of the methods above.

Looking at the solution, I see they use attr_reader :title. Remember, attr_reader only defines one of those methods. The other method they defined manually:

def title=(title)
  title_words = title.split(" ").map(&:downcase)

  new_words = title_words.map.with_index do |word, i|
    if LOWER_WORDS.include?(word) && i != 0
      word
    else
      word.capitalize
    end
  end

  @title = new_words.join(" ")
end

So attr_accessor isn’t used because, you’re right, it wouldn’t be necessary. They use attr_reader to define the reader method, and they write their own writer method.

Thank you, that makes sense.