MX-Banxico 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +3 -0
- data/.travis.yml +12 -0
- data/.yardopts +9 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +36 -0
- data/Guardfile +26 -0
- data/LICENSE.txt +22 -0
- data/MX-Banxico.gemspec +29 -0
- data/README.md +140 -0
- data/REFERENCIAS.md +6 -0
- data/Rakefile +26 -0
- data/lib/MX/Banxico.rb +12 -0
- data/lib/MX/Banxico/historico.rb +4 -0
- data/lib/MX/Banxico/historico/tipo_de_cambio.rb +296 -0
- data/lib/MX/Banxico/series.rb +346 -0
- data/lib/MX/Banxico/tipo_de_cambio.rb +159 -0
- data/lib/MX/Banxico/version.rb +14 -0
- data/lib/MX/Banxico/web_services.rb +4 -0
- data/lib/MX/Banxico/web_services/tipo_de_cambio.rb +83 -0
- data/lib/MX/Banxico/web_services/web_service.rb +99 -0
- data/spec/MX/Banxico/historico/tipo_de_cambio_spec.rb +525 -0
- data/spec/MX/Banxico/series_spec.rb +475 -0
- data/spec/MX/Banxico/tipo_de_cambio_spec.rb +688 -0
- data/spec/MX/Banxico/web_services/tipo_de_cambio_spec.rb +152 -0
- data/spec/MX/Banxico/web_services/web_service_spec.rb +108 -0
- data/spec/fixtures/MX/Banxico/historico/respuestas_correctas/tipo_de_cambio.xml +2228 -0
- data/spec/fixtures/MX/Banxico/historico/respuestas_incorrectas/mal_formado.xml +1 -0
- data/spec/fixtures/MX/Banxico/historico/respuestas_incorrectas/serie_sin_valores.xml +28 -0
- data/spec/fixtures/MX/Banxico/historico/respuestas_incorrectas/sin_series.xml +26 -0
- data/spec/fixtures/MX/Banxico/historico/tipo_de_cambio/dolar_fix/respuesta_correcta.xml +393 -0
- data/spec/fixtures/MX/Banxico/historico/tipo_de_cambio/dolar_fix/serie_sin_valores.xml +28 -0
- data/spec/fixtures/MX/Banxico/historico/tipo_de_cambio/dolar_fix/sin_serie.xml +26 -0
- data/spec/fixtures/MX/Banxico/web_services/respuestas_correctas/reservas_internacionales_banxico.xml +41 -0
- data/spec/fixtures/MX/Banxico/web_services/respuestas_correctas/tasas_de_interes_banxico.xml +50 -0
- data/spec/fixtures/MX/Banxico/web_services/respuestas_correctas/tipos_de_cambio_banxico.xml +56 -0
- data/spec/fixtures/MX/Banxico/web_services/respuestas_correctas/udis_banxico.xml +41 -0
- data/spec/fixtures/MX/Banxico/web_services/tipo_de_cambio/dolar_fix/error_fecha_tipo_de_cambio.xml +41 -0
- data/spec/fixtures/MX/Banxico/web_services/tipo_de_cambio/dolar_fix/error_nodo_obs.xml +40 -0
- data/spec/fixtures/MX/Banxico/web_services/tipo_de_cambio/dolar_fix/error_valor_tipo_de_cambio.xml +41 -0
- data/spec/fixtures/MX/Banxico/web_services/tipo_de_cambio/dolar_fix/respuesta_correcta.xml +41 -0
- data/spec/spec_helper.rb +31 -0
- metadata +152 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1137c2b18fed5bb10d083f917faaaf2dd3e0f428
|
4
|
+
data.tar.gz: ff012be3f2c8a839aea8136170c8f234116671e8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4c996b8f71622192ae061f31fe6dfceb3a9548f59cad6fbc2eae4721cb84748c015a7e46e36207dbcc686a5df0678ed5e183ffd4e37cee7a50441dfc3a398fdf
|
7
|
+
data.tar.gz: 9924eb9b7e1a6afbf3955b75f119e7e974063daa65785ff60cd56048f6f6a02d7992552edf3a3fb606ae87e8e0513c797a97f330c2dc36884deb7f1fa5fe8a2e
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
language: ruby
|
2
|
+
|
3
|
+
before_install:
|
4
|
+
- gem install bundler -v '>= 1.12'
|
5
|
+
|
6
|
+
rvm:
|
7
|
+
- ruby-head
|
8
|
+
|
9
|
+
addons:
|
10
|
+
code_climate:
|
11
|
+
repo_token:
|
12
|
+
secure: "V+kAHFHYVxk3INQ92tjdHWzpkgpec6Hi3cZmI3kfirh12c8BuQsJy187ySjDuzyq6uPF4+WXUBUBoErZBi3SRI0u+qGavpjVEf6onlrykwfBHutYWMjkFybNZ03wKKNK+kSOLWrxOsdrjhFsnZ1SffliaIzxbT+DL2mWpiWkUBQmsBVwjKNpXBP5UowFnbwnaQpAdb7F9diGA83IcBpFueWx+q9ER+ekvNiGs30FmghJVsSveo7VVcWk+Tu8tPsXFwR2b9J3QZ1Ik4alldzVHWNv+O+a75WsJkpXV6eA+CojJ/S8HlhppN3yTUSIxd/fs05QEB+uM+1IsJ2I6IKJ1XsD9KG10kdUCUUL+tr8svfw5pdeqgouEiz4VbrN5wpt869OJznHsZIwQbMmJ3xtEcvD+v1ii260T3wfOFonjCBZOWNvru1xyFwDgoB4UJ2ucbFvKezwtnV5tPcGJqdEVfgM6NopwTKwcs95DRCkRDqB4prH3qGdu0ouu9i+b3c8JnUrny5pr+w/HTizL5lY5uiDIxJdQ5RiAoqMVGIdca4dWkWm+LvUiSCOam2Qf7loGnUcEtk+61BISzYQe7lBqyEMiKrU2b/Lp4mahvI/Q+UpPnsbVfCn5ecMMN4prnmKYVZDdrmgR0t1vEBC4+fy4pJClIOT51gLknYaiwz39dE="
|
data/.yardopts
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
# Changelog / Bitácora de cambios
|
2
|
+
|
3
|
+
* **Versión 0.0.1.pre**
|
4
|
+
* Primera implementación de web service para obtención del tipo de cambio.
|
5
|
+
* Es posible recuperar seriee históricas, haciendo una petición POST al mismo lugar donde lo hace la página web de consultas históricas de BANXICO.
|
data/Gemfile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
group :development, :ci_filter do
|
6
|
+
gem 'guard'
|
7
|
+
gem 'guard-bundler', require: false
|
8
|
+
gem 'guard-rspec', require: false
|
9
|
+
gem 'pry'
|
10
|
+
gem 'pry-remote'
|
11
|
+
gem 'pry-byebug', platform: [:mri_20, :mri_21, :mri_22]
|
12
|
+
gem 'pry-nav', platform: [:mri_19, :jruby]
|
13
|
+
gem 'terminal-notifier'
|
14
|
+
gem 'terminal-notifier-guard'
|
15
|
+
end
|
16
|
+
|
17
|
+
group :development, :test do
|
18
|
+
gem 'bundler'
|
19
|
+
gem 'rake'
|
20
|
+
gem 'rspec'
|
21
|
+
end
|
22
|
+
|
23
|
+
group :test do
|
24
|
+
gem 'codeclimate-test-reporter'
|
25
|
+
gem 'simplecov', require: false
|
26
|
+
gem 'coveralls', require: false
|
27
|
+
gem 'rspec-collection_matchers'
|
28
|
+
gem 'shoulda-matchers', require: false
|
29
|
+
gem 'webmock', require: false
|
30
|
+
end
|
31
|
+
|
32
|
+
group :doc do
|
33
|
+
gem 'yard'
|
34
|
+
gem 'redcarpet'
|
35
|
+
gem 'github-markup'
|
36
|
+
end
|
data/Guardfile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
guard :rspec, cmd: "bundle exec rspec", cmd_additional_args: '-f progress', failed_mode: :focus do
|
2
|
+
require "guard/rspec/dsl"
|
3
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
4
|
+
|
5
|
+
# RSpec files
|
6
|
+
rspec = dsl.rspec
|
7
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
8
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
9
|
+
watch(rspec.spec_files)
|
10
|
+
|
11
|
+
# Ruby files
|
12
|
+
ruby = dsl.ruby
|
13
|
+
dsl.watch_spec_files_for(ruby.lib_files)
|
14
|
+
end
|
15
|
+
|
16
|
+
guard :bundler do
|
17
|
+
require 'guard/bundler'
|
18
|
+
require 'guard/bundler/verify'
|
19
|
+
helper = Guard::Bundler::Verify.new
|
20
|
+
|
21
|
+
files = ['Gemfile']
|
22
|
+
files += Dir['*.gemspec'] if files.any? { |f| helper.uses_gemspec?(f) }
|
23
|
+
|
24
|
+
# Assume files are symlinked from somewhere
|
25
|
+
files.each { |file| watch(helper.real_path(file)) }
|
26
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2016 Pablo Ruiz
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/MX-Banxico.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'MX/Banxico/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "MX-Banxico"
|
7
|
+
spec.version = MX::Banxico::VERSION
|
8
|
+
spec.platform = Gem::Platform::RUBY
|
9
|
+
spec.authors = ["Pablo Ruiz"]
|
10
|
+
spec.email = ["pjruiz@maquech.com.mx"]
|
11
|
+
spec.summary = %q{Banco de México web services utilities / Utilerías para usar los servicios web del Banco de México (Banxico)}
|
12
|
+
spec.description = %q{Banco de México web services utilities / Utilerías para usar los servicios web del Banco de México (Banxico)}
|
13
|
+
spec.homepage = "https://github.com/Maquech/MX-Banxico"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.required_ruby_version = '>= 2.0'
|
17
|
+
|
18
|
+
spec.add_dependency 'nokogiri', '~> 1.6'
|
19
|
+
spec.add_dependency 'httparty', '~> 0.13'
|
20
|
+
spec.add_dependency 'savon', '~> 2.11'
|
21
|
+
|
22
|
+
spec.files = `git ls-files`.split("\n")
|
23
|
+
spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
|
+
spec.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
25
|
+
spec.require_paths = ["lib"]
|
26
|
+
|
27
|
+
spec.post_install_message = "¡Viva México!"
|
28
|
+
|
29
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
# MX::Banxico
|
2
|
+
|
3
|
+
|
4
|
+
[](https://badge.fury.io/rb/MX-Banxico) [](https://travis-ci.org/Maquech/MX-Banxico) [](https://codeclimate.com/github/Maquech/MX-Banxico) [](https://codeclimate.com/github/Maquech/MX-Banxico/coverage)
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
## Why and what for / Por qué y para qué
|
9
|
+
|
10
|
+
This gem was conceived as an aid in the automation of information extraction from the web site and web services provided by
|
11
|
+
the [Bank of Mexico](http://www.banxico.org.mx).
|
12
|
+
|
13
|
+
|
14
|
+
This project is not endorsed in any way by the Mexican government. It's an effort to contribute to the preservation of mental
|
15
|
+
health of the developers who have to deal with this things :)
|
16
|
+
|
17
|
+
|
18
|
+
---
|
19
|
+
|
20
|
+
Esta gema se concibió como una ayuda para la automatización de extracción de información de la página y servicios web que provee
|
21
|
+
el [Banco de México](http://www.banxico.org.mx).
|
22
|
+
|
23
|
+
|
24
|
+
Este proyecto no está patrocinado de ninguna forma por el gobierno mexicano. Es un esfuerzo para contribuir a la sanidad mental de los programadores que tenemos que lidiar con estas cosas :)
|
25
|
+
|
26
|
+
|
27
|
+
## Installation / Instalación
|
28
|
+
|
29
|
+
Add this line to your application's Gemfile:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
gem 'mx-banxico'
|
33
|
+
```
|
34
|
+
|
35
|
+
And then execute:
|
36
|
+
|
37
|
+
$ bundle
|
38
|
+
|
39
|
+
Or install it yourself as:
|
40
|
+
|
41
|
+
$ gem install mx-banxico
|
42
|
+
|
43
|
+
---
|
44
|
+
|
45
|
+
Agrega esta línea al archivo Gemfile de tu aplicación:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
gem 'mx-banxico'
|
49
|
+
```
|
50
|
+
|
51
|
+
Luego ejecuta:
|
52
|
+
|
53
|
+
$ bundle
|
54
|
+
|
55
|
+
O instálalo tu mismo usando:
|
56
|
+
|
57
|
+
$ gem install mx-banxico
|
58
|
+
|
59
|
+
|
60
|
+
## Dependencies / Dependencias
|
61
|
+
|
62
|
+
The only dependencies are:
|
63
|
+
|
64
|
+
* [Nokogiri](http://http://www.nokogiri.org/) for XML processing.
|
65
|
+
* [Savon](http://savonrb.com) for web services exploitation.
|
66
|
+
* [HTTParty](https://github.com/jnunemaker/httparty/tree/master/lib/httparty) for making a request to the Bank of Mexico's web site and download information.
|
67
|
+
|
68
|
+
---
|
69
|
+
|
70
|
+
Las únicas dependencias son:
|
71
|
+
|
72
|
+
* [Nokogiri](http://http://www.nokogiri.org/) que es una gema (y una joya) para procesar XML.
|
73
|
+
* [Savon](http://savonrb.com) para explotar los servicios web.
|
74
|
+
* [HTTParty](https://github.com/jnunemaker/httparty/tree/master/lib/httparty) para hacer una petición al sitio web y descargar
|
75
|
+
información de ahí.
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
## Usage / Uso
|
80
|
+
|
81
|
+
El Banco de México (también conocido como Banxico) maneja información de UDIS (Unidades de inversión), tipo de cambio, tasas de interés y reservas internacionales en uno de sus [servicios web] (http://www.banxico.org.mx/DgieWSWeb/DgieWS?WSDL). También, en su sitio web, tienen una [herramienta](http://www.banxico.org.mx/SieInternet/consultarDirectorioInternetAction.do?accion=consultarCuadro&idCuadro=CF102§or=6&locale=es) para consultar la información histórica de diversos indicadores (o series como ellos les llaman).
|
82
|
+
|
83
|
+
Ahora, la biblioteca (sí: _library -> biblioteca_, _bookstore -> librería_) está dividida en tres partes, cada una separada por un espacio de nombres (_namespace_) para poder distinguir los elementos con los que se está trabajando: {MX::Banxico}, {MX::Banxico::Historico} y {MX::Banxico::WebServices}.
|
84
|
+
|
85
|
+
#### Ejemplos:
|
86
|
+
|
87
|
+
* Para trabajar con el tipo de cambio histórico, se utiliza una instancia de {MX::Banxico::Historico::TipoDeCambio}.
|
88
|
+
* Si deseas obtener el tipo de cambio al día de hoy, usa una instancia de {MX::Banxico::WebServices::TipoDeCambio}.
|
89
|
+
|
90
|
+
|
91
|
+
En la clase {MX::Banxico::Series} encontrarás métodos para listar las series con las que trabaja la biblioteca. Básicamente es un contenedor de la información de las series (o indicadores) que tiene Banxico. La información ahí contenida se extrajo principalmente del servicio web, aunque la herramienta de consulta web del Banco también la maneja de la misma forma (se agradece consistencia).
|
92
|
+
|
93
|
+
Tanto los servicios web como la página, devuelven XML. Para facilitar las cosas, todos los métodos de clases o instancias en {MX::Banxico::Historico::TipoDeCambio} o {MX::Banxico::WebServices::TipoDeCambio} devuelven arreglos de objetos (u objetos) del tipo {MX::Banxico::TipoDeCambio}. **¿Ves el patrón?** La idea es que si trabajarás con UDIS, uses {MX::Banxico::Historico::UDIS}, {MX::Banxico::WebServices::UDIS} y {MX::Banxico::UDIS}.
|
94
|
+
|
95
|
+
Por el momento, sólo están las clases para trabajar con el tipo de cambio :'( pero siempre puedes contribuir a esta biblioteca y hacer a más gente feliz :)
|
96
|
+
|
97
|
+
|
98
|
+
## Docs
|
99
|
+
|
100
|
+
Check the [online documentation](http://http://www.rubydoc.info/gems/MX-Banxico/1.0) or generate it using YARD with:
|
101
|
+
|
102
|
+
$ bundle exec yard server --port 8828 --reload
|
103
|
+
|
104
|
+
Also, check the [references](REFERENCIAS.md).
|
105
|
+
|
106
|
+
---
|
107
|
+
|
108
|
+
Consulta la [documentación en línea](http://http://www.rubydoc.info/gems/MX-Banxico/1.0) o genera la documentación con YARD:
|
109
|
+
|
110
|
+
$ bundle exec yard server --port 8828 --reload
|
111
|
+
|
112
|
+
También revisa las [referencias](REFERENCIAS.md).
|
113
|
+
|
114
|
+
|
115
|
+
## Contributing / Contribuir
|
116
|
+
|
117
|
+
1. Fork it ( https://github.com/Maquech/MX-Banxico/fork )
|
118
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
119
|
+
3. Create your specs (100% coverage please!) and add code or make changes (TDD, right?)
|
120
|
+
4. Commit your changes (`git commit -am 'Add some feature'`)
|
121
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
122
|
+
6. Create a new Pull Request
|
123
|
+
|
124
|
+
You can also submit technical observations on the algorithms here implemented alongside with references to official documentation that supports it.
|
125
|
+
|
126
|
+
---
|
127
|
+
|
128
|
+
Puedes contribuir mandándonos tus observaciones sobre la implementación de los algoritmos aquí implementados o referencias a documentos oficiales que las respalde.
|
129
|
+
|
130
|
+
Ahora, diviérte con esta traducción (si sabes el término correcto en español, háznoslo saber por favor):
|
131
|
+
|
132
|
+
1. Crea tu copia del repositorio ( https://github.com/Maquech/MX-Banxico/fork )
|
133
|
+
2. Crea tu rama con la funcionalidad propuesta (`git checkout -b mi-nueva-funcionalidad-shubiduby`)
|
134
|
+
3. Crea tus pruebas (specs que tengan una covertura del 100% porfa) y realiza cambios o agrega código (estás haciendo TDD, ¿cierto?)
|
135
|
+
4. Compromete tus cambios (`git commit -am 'Nueva funcionalidad shubiduby'`)
|
136
|
+
5. Empuja la rama a tu repositorio (`git push origin mi-nueva-funcionalidad-shubiduby`)
|
137
|
+
6. Crea una nueva petición de jalada|tirada|extracción|acarreo
|
138
|
+
|
139
|
+
|
140
|
+
|
data/REFERENCIAS.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
begin
|
2
|
+
require "MX/Banxico/version"
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
require 'yard'
|
6
|
+
YARD::Rake::YardocTask.new
|
7
|
+
|
8
|
+
RSpec::Core::RakeTask.new(:spec, :tag) do |t, task_args|
|
9
|
+
t.rspec_opts = ["--tag #{task_args[:tag]}", "--format", "--color"]
|
10
|
+
end
|
11
|
+
|
12
|
+
task default: :spec
|
13
|
+
task test: :spec
|
14
|
+
|
15
|
+
|
16
|
+
task :build do
|
17
|
+
system "gem build MX-Banxico.gemspec"
|
18
|
+
end
|
19
|
+
|
20
|
+
task :release => :build do
|
21
|
+
system "gem push mx-banxico-#{MX::Banxico::VERSION}"
|
22
|
+
end
|
23
|
+
|
24
|
+
rescue LoadError
|
25
|
+
end
|
26
|
+
|
data/lib/MX/Banxico.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'savon'
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
require "MX/Banxico/version"
|
6
|
+
require "MX/Banxico/historico"
|
7
|
+
require "MX/Banxico/web_services"
|
8
|
+
require "MX/Banxico/series"
|
9
|
+
require "MX/Banxico/tipo_de_cambio"
|
10
|
+
require "MX/Banxico/historico/tipo_de_cambio"
|
11
|
+
require "MX/Banxico/web_services/web_service"
|
12
|
+
require "MX/Banxico/web_services/tipo_de_cambio"
|
@@ -0,0 +1,296 @@
|
|
1
|
+
# Clase para recuperar series históricas del tipo de cambio.
|
2
|
+
#
|
3
|
+
# La información se obtiene de la página de
|
4
|
+
# {http://www.banxico.org.mx/SieInternet/consultarDirectorioInternetAction.do?accion=consultarSeries Banxico},
|
5
|
+
# haciendo una petición POST que simula una consulta
|
6
|
+
# realizada por un usuario desde un navegador web.
|
7
|
+
#
|
8
|
+
class MX::Banxico::Historico::TipoDeCambio
|
9
|
+
include HTTParty
|
10
|
+
|
11
|
+
|
12
|
+
# URL de la página del Banco de México (Banxico).
|
13
|
+
#
|
14
|
+
URL = "www.banxico.org.mx"
|
15
|
+
|
16
|
+
|
17
|
+
# Ruta para realizar la petición POST para obtener la información.
|
18
|
+
#
|
19
|
+
POST_PATH = "/SieInternet/consultarDirectorioInternetAction.do?accion=consultarSeries"
|
20
|
+
|
21
|
+
|
22
|
+
# Año inicial de la consulta (por omisión).
|
23
|
+
#
|
24
|
+
AÑO_INICIO_CONSULTA = 2015
|
25
|
+
|
26
|
+
|
27
|
+
# Año final de la consulta (por omisión).
|
28
|
+
#
|
29
|
+
AÑO_FINAL_CONSULTA = 2015
|
30
|
+
|
31
|
+
|
32
|
+
# Tipos de cambio soportados.
|
33
|
+
#
|
34
|
+
TIPOS_DE_CAMBIO = MX::Banxico::Series.tipos_de_cambio.keys.dup.freeze
|
35
|
+
|
36
|
+
|
37
|
+
# !@method base_uri
|
38
|
+
# URI base para la clase que incluye a {https://github.com/jnunemaker/httparty HTTParty}.
|
39
|
+
#
|
40
|
+
base_uri URL
|
41
|
+
|
42
|
+
|
43
|
+
# !@method open_timeout
|
44
|
+
# tiempo de espera para abrir la conexión para clase que incluye a {https://github.com/jnunemaker/httparty HTTParty}.
|
45
|
+
#
|
46
|
+
open_timeout 10
|
47
|
+
|
48
|
+
|
49
|
+
# !@method format
|
50
|
+
# formato esperado de la respuesta {https://github.com/jnunemaker/httparty HTTParty}.
|
51
|
+
#
|
52
|
+
format :xml
|
53
|
+
|
54
|
+
|
55
|
+
# !@attribute [r] errores.
|
56
|
+
# @return [String] la descripción de los errores sucedidos al recuperar el histórico.
|
57
|
+
attr_reader :errores
|
58
|
+
|
59
|
+
|
60
|
+
# Inicializador de la instancia.
|
61
|
+
#
|
62
|
+
def initialize
|
63
|
+
@errores = nil
|
64
|
+
end
|
65
|
+
|
66
|
+
# Indica si hay algún errror.
|
67
|
+
#
|
68
|
+
# @return [Boolean] `true` si hay errores, `false` de lo contrario.
|
69
|
+
#
|
70
|
+
def errores?
|
71
|
+
!@errores.nil?
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
# Recupera el histórico de una serie de tipo de cambio de acuerdo al identificador o nombre de la serie dada.
|
76
|
+
#
|
77
|
+
# @param serie [Symbol] el nombre de la serie de la que se desea recuperar el histórico.
|
78
|
+
# @param año_inicio_consulta [Integer] año de inicio de la consulta.
|
79
|
+
# @param año_termino_consulta [Integer] año de término de la consulta.
|
80
|
+
#
|
81
|
+
# @return [Array<MX::Banxico::TipoDeCambio>] si se recuperó la información, un arreglo con los tipos de cambio de la serie.
|
82
|
+
# @return [nil] si hubo un error al recuperar la información.
|
83
|
+
#
|
84
|
+
def de_serie(serie, año_inicio_consulta = nil, año_termino_consulta = nil)
|
85
|
+
begin
|
86
|
+
id_serie = MX::Banxico::Series.identificador(:tipos_de_cambio, serie)
|
87
|
+
opts = { id_serie: id_serie, serie: serie }
|
88
|
+
return peticion_post(body_hash(id_serie, año_inicio_consulta, año_termino_consulta), opts)
|
89
|
+
rescue ArgumentError => e
|
90
|
+
registrar_error(e.message)
|
91
|
+
end
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
# Recupera todos los históricos de las series de tipo de cambio en {MX::Banxico::Series.tipos_de_cambio}.
|
97
|
+
#
|
98
|
+
# @param año_inicio_consulta [Integer] año de inicio de la consulta.
|
99
|
+
# @param año_termino_consulta [Integer] año de término de la consulta.
|
100
|
+
#
|
101
|
+
# @return [Array<MX::Banxico::TipoDeCambio>] si se recuperó la información, un arreglo con los tipos de cambio de la serie.
|
102
|
+
# @return [nil] si hubo un error al recuperar la información.
|
103
|
+
#
|
104
|
+
def completo(año_inicio_consulta = nil, año_termino_consulta = nil)
|
105
|
+
opts = { ids_series: MX::Banxico::Series.identificadores(:tipos_de_cambio) }
|
106
|
+
body_str = hash_a_query_string(body_hash(opts[:ids_series], año_inicio_consulta, año_termino_consulta))
|
107
|
+
return peticion_post(body_str, opts)
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
# Realiza la petición POST de acuerdo al cuerpo dado.
|
115
|
+
#
|
116
|
+
# @param body [Hash, String] el cuerpo de la petición. Usamos una cadena
|
117
|
+
# cuando algún parámetro tiene como valor un arreglo, de lo contrario se usa un `Hash`.
|
118
|
+
# @param opts [Hash] información adicional para procesar la respuesta.
|
119
|
+
#
|
120
|
+
# @return [Array<MX::Banxico::TipoDeCambio>] si se recuperó la información, un arreglo con los tipos de cambio de la serie.
|
121
|
+
# @return [nil] si hubo un error al recuperar la información.
|
122
|
+
#
|
123
|
+
def peticion_post(body, opts = {})
|
124
|
+
respuesta = self.class.post(POST_PATH, headers: header_hash, body: body)
|
125
|
+
return procesar_respuesta(respuesta.body, opts) if respuesta.code == 200
|
126
|
+
registrar_error("código de error #{respuesta.code}.")
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
# Procesa la respuesta de la petición, que es un `Hash` generado por {https://github.com/jnunemaker/httparty HTTParty}.
|
132
|
+
#
|
133
|
+
# @param respuesta [String] la respuesta de la petición realizada.
|
134
|
+
# @param opts [Hash] información adicional para procesar la respuesta.
|
135
|
+
#
|
136
|
+
# @return [Array<MX::Banxico::TipoDeCambio>] si no hubo errores, un arreglo con los tipos de cambio encontrados en la respuesta.
|
137
|
+
# @return [nil] si hubo un error al recuperar la información.
|
138
|
+
#
|
139
|
+
def procesar_respuesta(respuesta, opts = {})
|
140
|
+
xml_doc = Nokogiri::XML(respuesta, nil, 'UTF-8')
|
141
|
+
if xml_doc.root.respond_to?(:xpath)
|
142
|
+
if opts[:id_serie] && opts[:serie]
|
143
|
+
return procesar_serie(xml_doc, opts[:id_serie], opts[:serie])
|
144
|
+
else
|
145
|
+
return procesar_series(xml_doc, opts[:ids_series])
|
146
|
+
end
|
147
|
+
else
|
148
|
+
registrar_error("La respuesta de la petición no tiene el formato correcto.")
|
149
|
+
end
|
150
|
+
nil
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
# Procesa el XML, buscando la serie del identificador dado.
|
155
|
+
#
|
156
|
+
# @param xml_doc [Nokogiri::XML::Document] el XML con la respuesta de la petición realizada.
|
157
|
+
# @param id_serie [String] el identificador de la serie.
|
158
|
+
# @param serie [Symbol] el nombre de la serie.
|
159
|
+
#
|
160
|
+
# @return [Array<MX::Banxico::TipoDeCambio>] si no hubo errores, un arreglo con los tipos de cambio encontrados en la respuesta.
|
161
|
+
# @return [nil] si hubo un error al recuperar la información.
|
162
|
+
#
|
163
|
+
def procesar_serie(xml_doc, id_serie, serie)
|
164
|
+
historico = procesar_nodos_obs(xml_doc.root.xpath(%Q{bm:DataSet/bm:Series[@IDSERIE="#{id_serie}"]/bm:Obs}), serie)
|
165
|
+
return historico unless historico.empty?
|
166
|
+
registrar_error("No se encontró información de la serie #{serie} dentro de la respuesta de la petición.")
|
167
|
+
nil
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
# Procesa el XML de las series encontradas.
|
172
|
+
#
|
173
|
+
# @param xml_doc [Nokogiri::XML::Document] el XML con la respuesta de la petición realizada.
|
174
|
+
#
|
175
|
+
# @return [Array<MX::Banxico::TipoDeCambio>] si no hubo errores, un arreglo con los tipos de cambio encontrados en la respuesta.
|
176
|
+
# @return [nil] si hubo un error al recuperar la información.
|
177
|
+
#
|
178
|
+
def procesar_series(xml_doc, ids_series)
|
179
|
+
historico = []
|
180
|
+
xml_doc.root.xpath("bm:DataSet/bm:Series").each do |serie|
|
181
|
+
if serie["IDSERIE"] && ids_series.include?(serie["IDSERIE"])
|
182
|
+
begin
|
183
|
+
nombre_serie = MX::Banxico::Series.nombre(serie["IDSERIE"], :tipos_de_cambio)
|
184
|
+
historico += procesar_nodos_obs(serie.xpath("bm:Obs"), nombre_serie)
|
185
|
+
rescue ArgumentError # no se encontró el nombre de la serie
|
186
|
+
rescue Nokogiri::XML::XPath::SyntaxError # no jaló el xpath
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
return historico.sort unless historico.empty?
|
191
|
+
registrar_error("No se encontraron series en la respuesta.")
|
192
|
+
nil
|
193
|
+
end
|
194
|
+
|
195
|
+
|
196
|
+
# Procesa los nodos XML de la respuesta de la petición que contiene la información del tipo de cambio.
|
197
|
+
#
|
198
|
+
# @param nodos_obs [Nokogiri::XML::Nodes] nodos de la serie con el valor y fecha del tipo de cambio (bm:Obs).
|
199
|
+
# @param nombre_serie [Symbol] el nombre tipo de cambio solicitado. Ver {TIPOS_DE_CAMBIO}.
|
200
|
+
#
|
201
|
+
# @return [Array<MX::Banxico::TipoDeCambio>] los valores del tipo de cambio.
|
202
|
+
#
|
203
|
+
def procesar_nodos_obs(nodos_obs, nombre_serie)
|
204
|
+
historico = []
|
205
|
+
nodos_obs.each do |nodo_obs|
|
206
|
+
begin
|
207
|
+
tdc = MX::Banxico::TipoDeCambio.new(nombre_serie, nodo_obs[:TIME_PERIOD], nodo_obs[:OBS_VALUE])
|
208
|
+
historico << tdc
|
209
|
+
rescue ArgumentError
|
210
|
+
end
|
211
|
+
end
|
212
|
+
historico
|
213
|
+
end
|
214
|
+
|
215
|
+
|
216
|
+
# Registra el mensaje de error en {#errores}.
|
217
|
+
#
|
218
|
+
# @param error [String] el error que se agregará a {#errores}
|
219
|
+
# @param desc [String] descripción del error.
|
220
|
+
#
|
221
|
+
# @return [String] la nueva cadena de error.
|
222
|
+
#
|
223
|
+
def registrar_error(error, desc = nil)
|
224
|
+
err = "Error#{(desc.nil? or desc.empty?) ? "" : " (#{desc})"}: #{error}"
|
225
|
+
@errores = errores? ? "#{@errores} #{err}" : err
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
# Encabezado para la petición POST para recuperar el histórico de las series.
|
230
|
+
#
|
231
|
+
# @return [Hash] con los valores para el encabezado de la petición POST.
|
232
|
+
#
|
233
|
+
def header_hash
|
234
|
+
{ "Content-Type" => "application/x-www-form-urlencoded" }
|
235
|
+
end
|
236
|
+
|
237
|
+
|
238
|
+
# Crea el cuerpo para la petición POST para recuperar el histórico de las series.
|
239
|
+
#
|
240
|
+
# @param serie [String, Array<String>] el identificador o arreglo de identificadores de la serie o series
|
241
|
+
# de la que se desea recuperar el histórico.
|
242
|
+
# @param año_inicio_consulta [Integer] año de inicio de la consulta.
|
243
|
+
# @param año_termino_consulta [Integer] año de término de la consulta.
|
244
|
+
#
|
245
|
+
# @return [Hash] con los valores para el cuerpo de la petición POST.
|
246
|
+
#
|
247
|
+
def body_hash(serie, año_inicio_consulta = nil, año_termino_consulta = nil)
|
248
|
+
{ # Información recuparada de la petición POST al descargar desde la página web
|
249
|
+
idCuadro: "CF102",
|
250
|
+
sector: "6",
|
251
|
+
version: "2",
|
252
|
+
locale: "es",
|
253
|
+
"formatoSDMX.x" => "41",
|
254
|
+
"formatoSDMX.y" => "8",
|
255
|
+
formatoHorizontal: false,
|
256
|
+
metadatosWeb: true,
|
257
|
+
tipoInformacion: nil,
|
258
|
+
# años de consulta
|
259
|
+
anoInicial: año_inicio_consulta || AÑO_INICIO_CONSULTA,
|
260
|
+
anoFinal: año_termino_consulta || AÑO_FINAL_CONSULTA,
|
261
|
+
# las series a descargar en la consulta
|
262
|
+
series: serie
|
263
|
+
}
|
264
|
+
end
|
265
|
+
|
266
|
+
|
267
|
+
# Convierte un `Hash` a una cadena de petición HTTP.
|
268
|
+
#
|
269
|
+
# @example Conversión del `Hash`
|
270
|
+
# hsh = { un_param: "foo", otro_param: "bar", param_arreglo: ["a", "b"] }
|
271
|
+
# hash_a_query_string(hsh) #=> "un_param=foo&otro_param=bar¶m_arreglo=a¶m_arreglo=b"
|
272
|
+
#
|
273
|
+
#
|
274
|
+
# @param hsh [Hash] el `Hash` a convertir a cadena.
|
275
|
+
#
|
276
|
+
# @return [String] la cadena de petición.
|
277
|
+
def hash_a_query_string(hsh)
|
278
|
+
pares = []
|
279
|
+
hsh.each_pair do |k,v|
|
280
|
+
v.is_a?(Array) ? v.each{ |val| pares << par_query_string(k, val) } : pares << par_query_string(k, v)
|
281
|
+
end
|
282
|
+
pares.join("&")
|
283
|
+
end
|
284
|
+
|
285
|
+
|
286
|
+
# Crea un par de llave y valor escapado para URIs.
|
287
|
+
#
|
288
|
+
# @param llave [String, Symbol] la llave del par.
|
289
|
+
# @param valor [String, Symbol] el valor del par.
|
290
|
+
#
|
291
|
+
# @return [String] el par escapado para URI.
|
292
|
+
#
|
293
|
+
def par_query_string(llave, valor)
|
294
|
+
"#{URI.escape llave.to_s}=#{URI.escape valor.to_s}"
|
295
|
+
end
|
296
|
+
end
|