Provides Ruby wrapping of the Yahoo Fantasy Sports API.
I make no guarantees about this code working or without some poor Ruby choices.
This was my first attempt at a Ruby library (at Ruby at all to be honest) and may:
- Not work at all - although that would be a failure of the adventure
- Come no where close to best practices with regards to designing Ruby libraries
- Need a lot of love in order to get to a realistic Ruby place
If you come across this repo and you see anyting that I could have done better. Please don't hesitate to shoot me a note or a pull request (with some whys and whats of the changes) so that I can continue my Ruby journey on the right path!!
At this point in time the name
yahoo-fantasy
may change. I guess the ruby part is a little superfluous, but it was the name of the folder I needed so I rolled with it.
Add this line to your application's Gemfile:
gem 'yahoo-fantasy'
Add to your gemspec
:
spec.add_dependency "yahoo_fantasy_ruby"
Then install dependencies:
$ bundle install
Install the gem directly:
$ gem install yahoo-fantasy
The library provides/allows for a number of different usage methods - or at least that was the goal. You can pull and use as much or as little of as needed.
At this point in time the client
and resources
are tied to an OAuth2::AccessToken
(or atleast some object that responds to the #request
method).
The YahooFantasy::Client
, an extension of the OAuth2::Client
providing sensible defaults and Response
parsing is meant to be used. Obviously this can be skipped if you're using your own custom client
or access_token#request
during processing.
# Create a new access token using the
# This can be created and maintained at the server level
client = YahooFantasy::Client.new(ENV['yf_client_id], ENV['yf_client_secret'], redirect_uri: ENV['webroot_url])
# The access token is created at the request level
# Once you've gotten your user from the session/re-login
access_token = OAuth2::AccessToken.from_hash(client,
access_token: token.token,
refresh_token: token.refresh_token,
expiry_time: token.expiry_time)
I chose to use the OAuth2::Client
and OAuth2::AccessToken
instead of creating and maintaining my own connection
(Faraday or other) as the library and classes were already well designed and provided the backing I needed without much change. There are other libraries out there that only required setting of access_token
to work, but I felt it important to be able to:
- make calls
- handle refreshes
- etc
within the same client
that the users were making for requests.
One interesting thing with Yahoo tokens is that the refresh token doesn't update (from what I've seen). For example the same
access_token
andrefresh_token
can be used to refresh and work. You don't need to save the new tokens to the database (although you probably should) you don't need to.
Once you've got your access_token
you supply the users token to the resources:
The YahooFantasy::Resource::Base
class provides access to the access_token
:
# With the access_token above
YahooFantasy::Resource::Base.access_token = access_token
The
access_token
is stored at theThread[]
level so you need to ensure that it's removed after the request (server based). One of the next steps is providing theRails
specific classes to assist with this.
Once the access token is provided, requests can be made through the .api
method:
fantasy_content = YahooFantasy::Resource::Base.api(:get, '/users;use_login=1/games/leagues)
fantasy_content.games.each do |game|
puts "#{game.code.upcase}" # => NFL
game.leagues.each do |league|
puts "- #{league.name} (#{league.league_key})" # => - League Name (404.l.12345)
end
end
The Base
resource also has methods:
.get(key, options, &block)
to get a single resource.all(filters, options, &block)
to get a collection of resources
Which will attempt to create the appropriate resource url from the provided arguments (need some love and handling) and will return a YahooFantasy::Resource::FantasyContent
or what is returned from the ->(fantasy_content) {}
block provided.
This is where it would make more sense to provide
YahooFantasy::Api::Resource
andYahooFantasy::Api::Collection
as mentioned elsewhere in here.
The YahooFantasy::Resource::Game::Game
resource provides some consistent and common access to the API.
Ya, I get the name
Game::Game
isn't optimal. I've been playing around with the idea ofGame::Meta
(which is how Yahoo references it) orApi::Game
. I'll leave that for future Ken once I start actually using it.
Also available at
YahooFantasy::Games
shortcut.
Game Resource details can be found on the Yahoo developer portal.
For the most part the only the game_key
is required when making a request, but there are subresources available:
Filters
Filter | Filter Parameter values | Usage |
---|---|---|
out | Game subresources | Game.get('406', out: %w[game_weeks]) |
Example(s)
# Get game 406 meta data
game = YahooFantasy::Resource::Game::Game.get('406')
The teams subresource is not currently available
The leagues subresource is available. BUT it's only available in terms of the logged in user. At this point there is no way to request a subresource with further filters. Although I do plan on getting this working once I get more comfortable with Ruby.
Games collection provides access to multiple games using a set of specified filters.
Filters
Collection filters are available on top of resource filters.
Filter | Filter Parameter values | Usage |
---|---|---|
game_keys | Games.all(filters: { game_keys: ['406'] }) |
|
is_available | 1 or 0 |
Games.all(filters: { is_available: 1 }) |
game_types | full,pickem-team,pickem-group,pickem-team-list |
Games.all(filters: { game_types: ['pickem-team'] }) |
game_codes | Any valid game code(s) | Games.all(filters: { game_codes: ['nfl'] }) |
seasons | Any valid season(s) | Games.all(filters: { seasons: [2020] }) |
The decision to use XML over JSON was made due to how Yahoo serializes data. Although people tend to dislike XML due to its verboseness (I know there's a war on verbosity these days in development) the structure makes sense:
<games>
<leagues>
<scoreboard></scoreboard>
</leagues>
</games>
where JSON is serialized as an array (0 based with the meta data):
games: [
0: {
// this is meta
},
1: {
// this is the first sub resource
// standings
},
2: {
// this is the second sub resource
// scoreboard
}
]
which I just find annoying, and although it seems like the indices are based on the alphabetical name of the subresource, I still don't want to deal with it.
Will definitely accept a pull request for the JSON representers allowing configuration between both XML or JSON
Development is done within a development container that can easily be used within vscode (and possibly/eventually) (Github Codespaces)[https://github.com/features/codespaces]:
Should make a
docker-compose
file at some point, but that's future Ken's problem
The devcontainer
post install script is configured to run bin/setup
(described below).
Note that when you first set this up, you may need to restart some of the plugins (solargraph, ruby test explorer, etc). This is due to
bundle install
requiringgemspec
requiringYahooFantasy::VERSION
, but copying those files to the Image seems to go against the point of docker. Not a huge deal, just remember to restart them using the command palette.
After checking out the repo, run bin/setup
to install dependencies. Then, run rake spec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/kenjdavidson/yahoo_fantasy-ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
The gem is available as open source under the terms of the MIT License.
Everyone interacting in the YahooFantasy project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.