Skip to content

Commit

Permalink
Change API to retrieve a station from Gare object to Station object
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul B committed Apr 25, 2015
1 parent 018ad3a commit 27afaf4
Show file tree
Hide file tree
Showing 13 changed files with 81 additions and 79 deletions.
44 changes: 22 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
# Gares (en-mouvement)
# Gares - A gem to interact with French train Stations

[![Build Status](https://travis-ci.org/paulRbr/gares.svg)](https://travis-ci.org/paulRbr/gares) [![Gem Version](https://badge.fury.io/rb/gares.svg)](http://badge.fury.io/rb/gares) [![Coverage Status](https://coveralls.io/repos/paulRbr/gares/badge.svg)](https://coveralls.io/r/paulRbr/gares)

## Description

The Gares gem allows you to easy access publicly available data from gares-en-mouvement.com.
The Gares gem allows you to easily access publicly available data from gares-en-mouvement.com.

## Features

Gares currently features the following:

* Search for a gare
* Retrieve gare information
* Search for a station
* Retrieve station information

## Examples

### Gare:
### Station:

g = Gares::Gare.new("frlpd")
g = Gares::Station.new("frlpd")

g.name
#=> "Lyon Part Dieu"
Expand All @@ -38,49 +38,49 @@ Gares currently features the following:

g = Gares::Search.new("Aix")

g.gares.size
g.stations.size
#=> 7

# or

gares = Gares::Gare.search("lyon")
gare = gares.last
stations = Gares::Station.search("lyon")
station = stations.last

gare.name
station.name
#=> "Paris Gare de Lyon"

## Installation

gem install gares

Or, if you're using this in a project with Bundler:
Or if you want to use it in a project add this to your `Gemfile`:

gem gares
gem "gares"

## Running Tests

As this gem uses content from gare-en-mouvement.com, the test suite uses a set of
pre-defined fixute files in `spec/fixtures`. These fixtures are
copies of gares-en-mouvement page used in tests.
As this gem uses external content from gare-en-mouvement.com and sncf.com, the test suite uses a set of
pre-defined fixture files in `spec/fixtures`. These fixtures are
copies of gares-en-mouvement.com and sncf.com pages used in tests.

Run bundle install to install all dependencies, including fakeweb, which
will serve the fixture files instead of doing actual requests to gares-en-mouvement.com.
will serve the fixture files instead of doing actual requests to gares-en-mouvement.com or sncf.com.

$ bundle install

Next, simple run `rake` to run the entire test suite.

### Running against actual gare-en-mouvement data
### Running against real data

It's possible to run the test suite directly against gares-en-mouvement.com. This has
It's possible to run the test suite directly against gares-en-mouvement.com or sncf.com. This has
two disadvantages:

1. Tests will be slow
2. Running tests often will probably get you into trouble, see Disclaimer.

$ LIVE_TEST=true rake

If you want to run against actual gares-en-mouvement data, it's better to just update
If you want to run against actual data, it's better to just update
the fixture files once with up-to-date content:

$ rake fixtures:refresh
Expand All @@ -92,12 +92,12 @@ When you run the test suite now, it will use the updated fixture files.
Neither I, nor any developer who contributed to this project, accept any kind of
liability for your use of this library.

gares-en-mouvement does not permit use of its data by third parties without their consent.
gares-en-mouvement.com and sncf.com certainly does not permit use of its data by third parties without their consent.

Using this library for anything other than limited personal use may result
in an IP ban to the gares-en-mouvement website.
in an IP ban to the gares-en-mouvement.com or sncf.com website.

_This gem is not endorsed or affiliated with gares-en-mouvement.com, or SNCF, Inc._
_This gem is not endorsed or affiliated with gares-en-mouvement.com, nor SNCF, Inc._

## License

Expand Down
4 changes: 2 additions & 2 deletions lib/gares.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
require 'unidecoder'

require 'gares/base'
require 'gares/gare'
require 'gares/gare_list'
require 'gares/station'
require 'gares/station_list'
require 'gares/sales'
require 'gares/services'
require 'gares/search'
Expand Down
16 changes: 8 additions & 8 deletions lib/gares/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ class Base
GPS_COORD = 'Coordonnées GPS : '
NAME = 'En direct de '

# Initialize a new Gare object with it's gare-en-mouvemnt id (as a String)
# Initialize a new Station object with it's gare-en-mouvemnt id (as a String)
#
# gare = Gares::Gare.new("frabt")
# station = Gares::Station.new("frabt")
#
# Gares::Gare objects are lazy loading, meaning that no HTTP request
# will be performed when a new object is created. Only when you use an
# accessor that needs the remote data, a HTTP request is made (once).
# Gares::Station objects are lazy loaded, meaning that no HTTP request
# will be performed when a new object is created. An HTTP request is made (once)
# Only when you use an accessor that needs the remote data.
#
def initialize(slug, name = nil)
@slug = slug
Expand Down Expand Up @@ -76,7 +76,7 @@ def coordinates

# Returns a new Nokogiri document for parsing.
def document
@document ||= Nokogiri::HTML(Gares::Gare.find_by_slug(@slug))
@document ||= Nokogiri::HTML(Gares::Station.find_by_slug(@slug))
end

# Use HTTParty to fetch the raw HTML for this gare.
Expand All @@ -86,7 +86,7 @@ def self.find_by_slug(slug, page = :"votre-gare")

# Convenience method for search
def self.search(query)
Gares::Search.new(query).gares
Gares::Search.new(query).stations
end
end # Gare
end # Base
end # Gares
5 changes: 0 additions & 5 deletions lib/gares/gare.rb

This file was deleted.

12 changes: 0 additions & 12 deletions lib/gares/gare_list.rb

This file was deleted.

2 changes: 1 addition & 1 deletion lib/gares/sales.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def all
private

def document
@document ||= Nokogiri::HTML(Gares::Gare.find_by_slug(
@document ||= Nokogiri::HTML(Gares::Station.find_by_slug(
@slug, :"services-en-gare/vente/"))
end
end
Expand Down
27 changes: 15 additions & 12 deletions lib/gares/search.rb
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
module Gares
# Search Gares-en-mouvement for a gare name
class Search < GareList
# Search Gares-en-mouvement for a station name
class Search < StationList
attr_reader :query

# This is a file containing minimal information (name and slug) of all stations of gares-en-mouvement.com
GARES_LIST_URL = "https://www.kimonolabs.com/api/7jys32dy?apikey=lsOO4tNm78cH9JxqWg9gAk9l4nYaou9j&kimmodify=1"

# Initialize a new Gares search with the specified query
# Initialize a new Station search with the specified query
#
# search = Gares::Search.new("Aix")
#
# Gares::Search is lazy loading, meaning that unless you access the +gares+
# attribute, no query is made to gares-en-mouvement.com.
# Gares::Search is lazy loaded, meaning that unless you access the +stations+
# attribute, no remomte query is made.
#
def initialize(query)
@query = query
end

# Returns an array of Gares::Gare objects for easy search result yielded.
# Returns an array of Gares::Station objects in order to easily search result yielded.
# If the +query+ was an exact match, a single element array will be returned.
def gares
@gares ||= (exact_match? ? parse_gare : parse_gares)
def stations
@stations ||= (exact_match? ? parse_station : parse_stations)
end

private
Expand All @@ -29,16 +30,18 @@ def document
end

def result
@result ||= document.results.collection1.map(&:station).select { |gare| gare.name.to_ascii =~ /#{@query.split(" ").join(".*")}/i }
@result ||= document.results.collection1.map(&:station).select do |station|
station.name.to_ascii =~ /#{@query.split(" ").join(".*")}/i
end
end

def self.query
open(GARES_LIST_URL)
end

def parse_gare
gare = result.first
[Gares::Gare.new(gare.slug, gare.name)]
def parse_station
station = result.first
[Gares::Station.new(station.slug, station.name)]
end

def exact_match?
Expand Down
2 changes: 1 addition & 1 deletion lib/gares/services.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def all
private

def document
@document ||= Nokogiri::HTML(Gares::Gare.find_by_slug(
@document ||= Nokogiri::HTML(Gares::Station.find_by_slug(
@slug, :"services-en-gare/service/"))
end
end
Expand Down
5 changes: 5 additions & 0 deletions lib/gares/station.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module Gares
# Represents a station on gares-en-mouvement.com
class Station < Base
end # Station
end # Gares
12 changes: 12 additions & 0 deletions lib/gares/station_list.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Gares
class StationList

private

def parse_stations
result.compact.uniq.map do |station|
Gares::Station.new(station.slug, station.name)
end
end
end # StationList
end # Gares
11 changes: 5 additions & 6 deletions spec/gares/gare_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@
#
# http://www.gares-en-mouvement.com/fr/frlpd/votre-gare/
#

describe Gares::Gare do
describe Gares::Station do

describe 'valid gare' do

before(:each) do
# Get gare de Lyon Part-Dieu
@gare = Gares::Gare.new('frlpd')
@gare = Gares::Station.new('frlpd')
end

it 'should find the name' do
Expand Down Expand Up @@ -53,7 +52,7 @@
context 'a gare without wifi nor defibrillator' do
before(:each) do
# Get gare de Agde
@gare = Gares::Gare.new('frxag')
@gare = Gares::Station.new('frxag')
end

it { expect(@gare.wifi?).to be(false) }
Expand All @@ -63,7 +62,7 @@
context 'a gare with no sales services' do
before(:each) do
# Get gare de Agde
@gare = Gares::Gare.new('frxag')
@gare = Gares::Station.new('frxag')
end

it { expect(@gare.has_borne?).to be(false) }
Expand All @@ -73,7 +72,7 @@
describe 'with name that has utf-8 characters' do
# Belleville sur Sâone
before(:each) do
@gare = Gares::Gare.search('Saone').first
@gare = Gares::Station.search('Saone').first
end

it 'should give the proper name' do
Expand Down
2 changes: 1 addition & 1 deletion spec/gares/sales_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
describe Gares::Sales do

context 'with a valid gare' do
context 'with a valid station' do

subject(:sales) { Gares::Sales.new('frqxb') }

Expand Down
18 changes: 9 additions & 9 deletions spec/gares/search_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,45 +11,45 @@
end

it 'should find 5 results' do
expect(@search.gares.size).to eql(7)
expect(@search.stations.size).to eql(7)
end

it 'should return Gares::Gare objects only' do
expect(@search.gares).to all(be_an(Gares::Gare))
it 'should return Gares::Station objects only' do
expect(@search.stations).to all(be_an(Gares::Station))
end

it 'should not return gares with no name' do
@search.gares.each { |gare| expect(gare.name).to_not be_blank }
@search.stations.each { |gare| expect(gare.name).to_not be_blank }
end

it 'should return only the name of the result' do
expect(@search.gares.first.name).to eql('Aix en Provence')
expect(@search.stations.first.name).to eql('Aix en Provence')
end
end

context 'with an exact match' do
it 'should not raise an exception' do
expect do
@search = Gares::Search.new('Paris Austerlitz').gares
@search = Gares::Search.new('Paris Austerlitz').stations
end.not_to raise_error
end

it 'should return the gare slug correctly' do
@search = Gares::Search.new('Paris Austerlitz')
expect(@search.gares.first.slug).to eql('frpaz')
expect(@search.stations.first.slug).to eql('frpaz')
end
end

context 'with a fuzzy match' do
it 'should not raise an exception' do
expect do
@search = Gares::Search.new('CULMONT CHALINDREY').gares
@search = Gares::Search.new('CULMONT CHALINDREY').stations
end.not_to raise_error
end

it 'should return the gare slug correctly' do
@search = Gares::Search.new('CULMONT CHALINDREY')
expect(@search.gares.first.slug).to eql('frccy')
expect(@search.stations.first.slug).to eql('frccy')
end
end
end

0 comments on commit 27afaf4

Please sign in to comment.