Search code examples
ruby-on-railsrubyjsoninstance-variablesattr-accessor

JSON data to instance variable in Ruby


This is my ruby code / JSON File. Three functions required, I have implemented the first two but am having trouble with the third one. I have only recently started learning ruby - any simplified explanations/answers are much appreciated

class Company
  attr_accessor :jobs
  jobs = Array.new 

  ## TODO: Implement this method to load the given JSON file into Ruby built-in data
  ## structures (hashes and arrays).
  def self.load_json(filepath)
    require 'json'
    file = File.read(filepath)
    data_hash = JSON.parse(file)
  end

  ## TODO: This method should update the `jobs` property to an array of instances of
  ## class `Job`
  def initialize(filepath)
    # Load the json file and loop over the jobs to create an array of instance of `Job`
    # Assign the `jobs` instance variable.
    load_json(filepath)
    data_hash.each { |jobs|
    array_of_jobs.insert(jobs['name'])
    }
  end

  ## TODO: Impelement this method to return applicants from all jobs with a
  ## tag matching this keyword
  def find_applicants(keyword)
    # Use the `jobs` instance variable.

  end
end

Below is the JSON file code I am supposed to retrieve the information from.

{
  "jobs": [
    {
      "id": 1,
      "title": "Software Developer",
      "applicants": [
        {
          "id": 1,
          "name": "Rich Hickey",
          "tags": ["clojure", "java", "immutability", "datomic", "transducers"]
        },
        {
          "id": 2,
          "name": "Guido van Rossum",
          "tags": ["python", "google", "bdfl", "drop-box"]
        }
      ]
    },
    {
      "id": 2,
      "title": "Software Architect",
      "applicants": [
        {
          "id": 42,
          "name": "Rob Pike",
          "tags": ["plan-9", "TUPE", "go", "google", "sawzall"]
        },
        {
          "id": 2,
          "name": "Guido van Rossum",
          "tags": ["python", "google", "bdfl", "drop-box"]
        },
        {
          "id": 1337,
          "name": "Jeffrey Dean",
          "tags": ["spanner", "BigTable", "MapReduce", "deep learning", "massive clusters"]
        }
      ]
    }
  ]
}

Solution

  • Code provided by you will not compile and approach used is not very convenient. Steps you may follow to implement it:

    First implement your models. May look like:

    class Applicant
      attr_accessor :id, :name, :tags
    
      def initialize(id, name=nil, tags=nil)
        @id = id
        @name = name
        @tags = tags
      end
    end
    
    class Job
      attr_accessor :id, :title, :applicants
    
      def initialize(id, title=nil, applicants=nil)
        @id = id
        @title = title
        @applicants = applicants
      end
    end
    

    Then define your Company class that works with jobs

    class Company
      attr_accessor :jobs
    
      def initialize(jobs)
        @jobs = jobs
      end
    
      def find_applicants(keyword)
        # Now you can iterate through jobs, 
        # job's applicants and finally applicant's tags
        # like this
        applicants = []
        @jobs.each do |job|
          job.applicants.each do |applicant|
            applicant.tags.each do |tag|
              if keyword.eql? tag
                 # ...
              end
            end
          end
        end
        applicants
      end
    end
    

    And then you can load data from Json file and construct proper objects:

    require 'json'
    
    class DataLoader
      def load(filepath)
        hash = JSON.parse(filepath)
        construct(hash)
      end
    
      private
    
      def validate(hash)
        # validate your data here
      end
    
      def construct(hash)
        validate(hash)
        jobs = []
        hash['jobs'].each do |job|
          applicants = []
          job['applicants'].each do |applicant|
            applicants << Applicant.new(applicant['id'], applicant['name'], applicant['tags'])
          end
          jobs << Job.new(job['id'], job['title'], applicants)
        end
        jobs
      end
    end
    

    And all together will look like:

    tag = 'google'
    
    data = DataLoader.new.load(File.read('data.json'))
    company = Company.new(data)
    applicants = company.find_applicants(tag)
    
    puts "Applicants that have '#{tag}' in taglist"
    applicants.each do |applicant|
      puts "  #{applicant.id}: #{applicant.name}"
    end
    
    #Applicants that have google in taglist
    #  2: Guido van Rossum
    #  42: Rob Pike