0

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!

1
  • I can help you with this, but I need to know what exactly do you have in the variable? is it the name of the association that you will be creating the model for? Commented Jan 13, 2016 at 3:21

1 Answer 1

1

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(...)
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! The constantize method was the missing link I needed! I ended up changing things around just a bit, and it seems to be working. (I am now passing in "Metro" and using the code below) model_name = model.constantize model_name.create(coordinates: coordinates, name: station["properties"]["NAME"], address: station["properties"]["ADDRESS"], hood: hood[0])
Great to hear it helped :) Also: Welcome to Stack Overflow. :D As a newbie to the site, I don't know if you know or not, but if an answer solves your problem, you can/should "accept" it. To do that, hover over the left side of the answer and a 'tick' will appear... you probably can't click it right away, but eventually you will be able to. Sometimes it's difficult to decide between answers if you've received more than one good one...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.