0

The Goal:

Build a Person object for each row, with first_name, last_name, and email attributes. This list of people should be encapsulated in a class that can do stuff like return unique by different attributes, ie: people.unique_by_first_name. Also the people object should be Enumberable.

Attempt #3:

#!/usr/bin/env ruby

class Person
  attr_accessor :first_name, :last_name, :email

  def self.unique_by_first_name(people_array)
    people_array.uniq{ |x| x.first_name } # see result below
  end

  def self.import_data
    people_array = Array.new

    file = DATA.read
    file.each_line do |line|

      person = Person.new
      fields = line.split(',')

      fields.each_with_index do |field, i|
        if field.include? '@'
          person.email = field.to_s.strip
          fields.delete_at(i)
        elsif field.empty?
          fields.delete_at(i)
        else
          person.first_name = fields[0].to_s.strip
          person.last_name = fields[1].to_s.strip
        end
      end

      people_array.push(person)
    end

    Person.unique_by_first_name(people_array)
  end
end

Person.import_data

__END__
John,Smith,john@foo.com
james@data.net,James
Phillip,Jones,phil@msn.com
,Irene,Smith
Robert,Chorley,rob@foo.com,
emma@hotmail.com,Emma,
David,Smith
james@game.net,James,Bond
james@game.net,James,Bond

Result:

[#<Person:0x007fd30228fdc0 @email="john@foo.com", @first_name="John", @last_name="Smith">,
 #<Person:0x007fd30228f870 @email="james@data.net">,
 #<Person:0x007fd30228f438 @email="phil@msn.com", @first_name="Phillip", @last_name="Jones">,
 #<Person:0x007fd30228ea60 @first_name="Irene", @last_name="Smith">,
 #<Person:0x007fd30228e420 @email="rob@foo.com", @first_name="Robert", @last_name="Chorley">,
 #<Person:0x007fd3022879e0 @email="emma@hotmail.com", @first_name="Emma", @last_name="">,
 #<Person:0x007fd302286680 @first_name="David", @last_name="Smith">,
 #<Person:0x007fd302285e38 @email="james@game.net", @first_name="James", @last_name="Bond">]

Any Ideas for Improvement?

The code above produces the following results ^. Do you guys have any recommendations on how to improve this logic?

slavakurilyak
  • 101
  • 1
  • 10

1 Answers1

1

In order for you to access those attributes on the Person class you need to add:

attr_reader :first_name, :last_name, :email to the top of your class

Like this:

class Person
  attr_reader :first_name, :last_name, :email

  def initialize(first_name, last_name, email)
    first_name = first_name
    last_name = last_name
    email = email
  end

Now you can call your x.first_name on an object because you're explicitly allowing your program to read it. Here's a really famous SO answer on the subject.

Community
  • 1
  • 1
Anthony
  • 15,435
  • 4
  • 39
  • 69
  • Thanks, I updated the person object to include attr_accessor. However, my logic could still use some help to finish the task goal. – slavakurilyak Sep 24 '14 at 00:13
  • I'm unsure what you're looking for? You want me to print the results of unique_by_first_name to the console? – Anthony Sep 24 '14 at 00:42
  • I've updated the logic to properly pass in varying data into the `unique_by_first_name` method. Any suggestions on how to make the code cleaner? – slavakurilyak Sep 24 '14 at 01:08
  • My solution worked and gave you what you needed for the error in the original question. Code reviews are done at http://codereview.stackexchange.com/ . Please accept my answer. – Anthony Sep 24 '14 at 01:11