Alexis Johnson
Alexis Johnson

Reputation: 13

Using Variables for Model Names in Active Record

I am writing a seed file that will make several API calls via HTTParty in order to populate the database. I am pulling the same information for several different models and I would like to be able to use a single method for all of them. However, I cannot figure out how to reference the model name through a variable. Specifically I am having difficulties because each of these must belong to another model. I have tried the following:

def create_assets(subject, model, geokit_hoods)
  response = HTTParty.get("https://raw.githubusercontent.com/benbalter/dc-maps/master/maps/#{subject}.geojson")
  parsed = JSON.parse(response)
  collection = parsed["features"]
  collection.each do |station|
    coordinates = station["geometry"]["coordinates"].reverse
    point = Geokit::LatLng.new(coordinates[0], coordinates[1])
    geokit_hoods.each do |hood|
      if hood[1].contains?(point)
        hood[0][model].create(coordinates: coordinates, name: station["properties"]["NAME"], address: station["properties"]["ADDRESS"])
        break
      end
    end
  end
end

Which I called via the following:

create_assets("metro-stations-district", "metros", geokit_hoods)

hood[0] refers to an existing neighborhood model, and hood[1] is the polygon associated with that neighborhood. The code works when referring to hood[0].metros.create(...), but I am looking for a way to make this method useful across many models.

Any ideas would be appreciated!

Upvotes: 0

Views: 1534

Answers (1)

Taryn East
Taryn East

Reputation: 27747

For now I'm going to assume that what you have in the variable is a String that is the name of the class in table-name format. eg in your example you have metros in the variable... from that I assume you have a Metro class which you are trying to create.

If so... you first need to convert your lowercase table-name style variable ("metros") into a class name-style eg "Metro" Note: this is title cased and singular (rather than plural).

Rails has a method to do this to strings for exactly the purpose you want: classify eg you could use it thus:

model_name = hood[0][model] # 'metros'
model_name.classify # 'Metro'

Note that it's still just a string, and you can't call create on a string.. so how do you make it the real class? constantize

Use this to turn the string into the actual model-class you're trying to find... which you can then call create on eg:

model_name = hood[0][model] # 'metros'
the_klass = model_name.classify.constantize # Metro
your_instance = the_klass.create(...)

Upvotes: 1

Related Questions