0

I am trying to create a simple data puller from the yahoo finance gem. I have a nested route setup for Security that has_many Price

The Price controller is as follows:

class PricesController < ApplicationController
  before_action :set_security
  before_action :set_price, only: [:show, :edit, :update, :destroy]

  def new
    @price = Price.new
  end

  private
  def set_price
    @price = Price.find_by_name(params[:id])
  end

  def price_params
    params.require(:price).permit(:date, :open, :high, :low, :close, :volume, :security_id)
  end

  def set_security
    @security = Security.find_by_ticker(params[:security_id])
  end
end

The nested route works fine to manually create the child Price record from a form. I'm trying to create a Price record for each result in the array that gets generated from the following code:

class Datapuller

  def self.download_historical
    yahoo_client = YahooFinance::Client.new
    data = yahoo_client.historical_quotes("FB")

    data.each do |i|
      @ticker = Security.find_by_ticker(data[0].symbol )
      price = @ticker.prices.new()
      price.security_id = @ticker
      price.date = data[0].date
      price.open = data[0].open
      price.high = data[0].high
      price.low = data[0].low
      price.close = data[0].close
     end
   end
 end

I'd like to call this method from a button link but for now I have the following code on the Security View:

<%= Datapuller.download_historical %>

This also give me the benefit to see the data that is getting loaded from the array.

With the above code I can create a child Price to a parent Security using a form and I can make the call from the yahoo finance gem. However, the array is not creating a Price record for each line in the array.

What am I missing in this?

Thanks!

Max Alcala
  • 781
  • 6
  • 17
M. Wood
  • 63
  • 7

1 Answers1

1

The main reason why you aren't getting anything saved in your array of @ticker.prices is because you're instantiating them via price = @ticker.prices.new() but you're never saving them. You need to call the following after you set all the attributes:

price.save

to get that record

  1. saved via Active Record and
  2. associated with your @ticker.

If you skim through the Active Record basics guide it will help a ton to understand the life cycle of a record (save, validate, delete, etc).

You also will probably want to look at making your views and routes more resourceful, which is the Rails default. If you use a resource :prices in your routes, Rails will use it's convention to help you along the way.

So for instance, you'd have a create method on your controller that would solely be in charge of calling your Datapuller.download_historical - and that way you can make a button that links to that route just by saying <%= link_to 'Create Price', prices_path, method: :create %> that would create your prices on click. There are more ways to further let Rails help you write less code but that's a start. If you want more reading, I think M. Hartl does a great job of explaining RESTful resources in his intro guide.

Max Alcala
  • 781
  • 6
  • 17