• Inspiración
  • Tutoriales
  • Bootcamp

Planer

  • Inspiración
  • Tutoriales
  • Bootcamp

Ruby 24

Tutorial de Infinite Scrolling en Rails

Infinite Scrolling en Rails

Infinite scrolling es una técnica que consiste que a medida te acerques al final de la página esta cargue nuevos datos y sirve para remplazar la componente típica de paginación, el si es recomendable implementarla o no en una página es un tema bien discutido en la internet, pero en este tutorial vamos a explicar como implementarla.

Paso 0: Setup

Partamos con una aplicación vacía de Ruby on Rails, y dentro haremos el scaffold del recurso Post que contendrán los campos title y content.

Paso 0.1: Desacoplar el index

En lugar de ocupar el archivo index creado por el scaffold vamos a ocupar una vista parcial que contenga la información de cada post, de esta forma vamos a poder hacer mucho más con menos código.

Así que crearemos la vista parcial _post.html.erb

<!— views/posts/_post.html.erb →
<%= div_for(post) do %>
 <h2><%= post.id %></h2>
 <h2><%= post.title %></h2>
 <p><%= post.content %></p>
<% end %>

Luego el archivo posts/index.html.erb queda de esta forma:

<div id="content">
 <%= render(partial: 'post', collection: @posts) %>
</div>

Paso 1: Instalar la gema Kaminari para la paginación

¿Por qué necesitamos una gema para la paginación?, La respuesta es simple, para escribir menos código, las gemas de paginación nos separan los resultados en grupos, dependiendo de la página, la página 0 (sin número) contiene los primeros x resultados, la segunda página (?page=2) contiene los segundos x resultados. El truco que haremos con infinite scrolling es ir llamando via AJAX a estas distintas páginas generadas por el paginador (Kaminari)

Para instalar la gema hay que abrir el gemfile y agregar la línea

gem 'kaminari'

Paso 2: Paginando

Para paginar tenemos que modificar el controller de posts para especificar que los resultados deben ser paginados, esto lo hacemos modificando el método index.

def index
 @posts = Post.page(params[:page]).per(5)
end

Paso 2.1 Link a la siguiente página

En la vista de posts simplemente haremos un link a la página siguiente, para eso ocuparemos el helper de rails url_for sólo especificando el query string page, o sea este método llamará a la misma página pero añadiendo ?page=2 (o 3, o 4, u otro valor dependiendo del caso)

<p id="view-more">
 <%= link_to('Ver Más', url_for(page: @posts.current_page + 1)) %>
</p>

Paso 3: Agregando datos

Hasta el momento nuestro sitio es un simple listado de posts páginado pero debería estar funcionando, para probarlo vamos a agregar datos ocupando el archivo seeds.rb y una gema espectacular para este propósito llamada Faker.

Paso 3.1: Agregar la gema Faker al gemfile y luego correr bundler

Paso 3.2: Agregar las siguientes líneas al archivo db/seeds.rb

50.times.each do |x| 
 Post.create(:title => Faker::Lorem.sentence, :content => Faker::Lorem.paragraph )
end

paso 3.3: Correr rake db:seeds

paso 3.4: Probar entrando a localhost:3000/posts y ver los resultados, hacer click en siguiente y ver que la paginación funciona.

Paso 4: Infinite Scrolling

Hay librerías que podemos descargarde infinite scrolling, pero con Jquery es posible hacer el efecto de forma sencilla en sólo un par de líneas de código, para hacerlo vamos a crear el archivo scrolling.js.coffee dentro de la carpeta app/assets/javascript

Dentro del archivo vamos a hacer la primera prueba

jQuery ->
 $(window).scroll ->
   if $(window).scrollTop() > $(document).height() — $(window).height() — 50
     alert("Final de la página")

al correr el sitio e ir al final de la página va a aparecer una alerta diciendo Final de la página, el valor -50 debera ser ajustado en casos especiales, como fixed footers que sean muy grandes.

Paso 4.2 Haciendo el llamado Ajax

Ahora vamos a ocupar la idea anterior pero cada vez que se llegue al final de la página vamos a cargar una página nueva con posts más antiguos, para eso el método $.getScript() de jquery a lo que el controller responderá con un archivo index.js.erb con los posts nuevos (al pedir un archivo javascript el controller devuelve lo pedido y lo ejecuta)

jQuery ->
 $(window).scroll ->
   url = $('#view-more a').attr('href')
   if url && $(window).scrollTop() > $(document).height() —    $(window).height() — 50
     $("#view-more").attr('href', '')
     $.getScript url

Lo último que falta es aprovechar el archivo javascript devuelto y utilizarlo para actualizar la página.

Paso 4.3 Cargando los posts.

El archivo devuelto, que todavía no hemos creado, es index.js.erb (siguiendo las convenciones de rails debe llamarse igual que el método), ahora creemos el archivo y dentro de el carguemos la vista parcial de post con la información de los nuevos post y actualizemos el link para que cargue posts aún más antiguos.

$('#content').append("<%= j render @posts %>");
$("#view-more").attr("href", "<%= j posts_path(page: @posts.current_page + 1) %>");

Y con eso logramos Infinite Scrolling

Happy Infinite Scrolling !!!

Paso 4.4 (Opcional, pero elegante): Removiendo el link al final del documento.

Para remover el link tenemos que saber si realemente estamos al final, para eso comparamos @posts.current_page == @posts.total_pages

$('#content').append("<%= j render @posts %>");
<% if @posts.current_page == @posts.total_pages %>
 $('#view-more').remove();
<% else %>
 $('#view-more').html("<%= j link_to('View More', url_for(page: @posts.current_page + 1)) %>");
<% end %>
Share
January 3, 2015 Ruby, Tutorialesajax, Ruby on Rails, Tutoriales

“My Concerts Wishlist” ajax scaffold Ruby on Rails

Esta es una aplicación basada en un scaffold, sin embargo el CRUD está modificado para responder a peticiones Ajax en Rails.Comencemos con el paso a paso! la app la he llamado “My Concerts Wishlist”

demo: http://myconcertwishlist.herokuapp.com

(more…)

Share
January 1, 2015 Ruby, Tutorialesajax, Ruby on Rails

StreetmusicMap parte 2: Integración Gmaps4Rails

Rubystas! Lo prometido aquí está. La segunda parte del tutorial del StreetMusicMap. Si quieres revisar la parte 1 de la historia, en donde explico como crear una relación uno a muchos uniendo 2 scaffolds “Musician” e “Instrument” te dejó por aquí el artículo.

En la segunda parte, vamos a integrar esa data que guardamos a traves del scaffold creado, para visualizarla de una forma entretenida e interactiva usando la gema gmaps4Rails.

Te sugiero que vayas por una buena taza de café antes de comenzar.

Instalando la gema geocoder.

Vamos a agregar la gema geocoder en mapa/Gemfile:

gem 'geocoder'

Luego en el terminal:

$ bundle

y reiniciamos el server con:

$ rails s

Geolocalizando a partir del campo “address”.

Abres app/models/Musician.rb y agregas esta línea:

class Musician < ActiveRecord::Base
  belongs_to :instrument
  geocoded_by :address
  after_validation :geocode
end

En http://locahost:3000/musicians/new agregraremos 2 nuevos registros, dejamos vacíos los campos “latitude” y “longitude” . Luego te darás cuenta que al presionar “create musician” automáticamente se agregan valores. “Santiago Chile” en el campo address, obtendremos “-33.4367933” en latitude y “–70.64107299999” en longitude.

Geocoder es responsable de devolver las coordenadas como “Response” a partir de nuestra “Request” solicitada…Interesante..cierto?

pd: si no sabes por qué aparece este belongs_to:instruments quizás necesitas revisar la parte 1 del tutorial en donde explico todo eso)

Instalando la gema Gmaps4rails.

Vamos a agregar la gema gmaps4rails en mapa/Gemfile:

gem 'gmaps4rails'

Luego en el terminal:

$ bundle

y reiniciamos el server con:

$ rails s

Agregando algunas referencias .js en la vista parcial application.html.erb.

Abrimos el archivo app/views/application.html.erb y agregamos el js de bootstrap, googlemap api y markerclustered ántes de </head>

 <!-- bootstrap 3-->
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>

<!-- google maps -->
<script type="text/javascript" src="//maps.googleapis.com/maps/api/js?v=3.13&amp;sensor=false&amp;libraries=geometrykey=AIzaSyBX2Veo_ENuSNEXA3fdZS54WAOA9_wrm-Y">
</script>

<!-- markerClustered -->
<script src='//google-maps-utility-library-v3.googlecode.com/svn/tags/markerclustererplus/2.0.14/src/markerclusterer_packed.js' type='text/javascript'></script>

Agregando el div “Map” en fullScreen con Bootstrap.

Para dibujar el mapa en modo fullscreen (en cualquier dispositivo) me basé en este ejemplo disponible en Bootstrap examples.

No fue exactamente un copyPaste del ejemplo…tuve que modificar un poquito siguiendo estos pasos para adaptarlo a nuestro propósito.

Primero, agrega una referencia minificada de bootstrap.min.css antes de todas las referencias .js que incluimos en app/views/application.html.erb

<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">

Segundo, descargas el archivo cover.css y lo guardas en app/assets/stylesheets/cover.css

Tercero, buscas la linea en cover.css :

@media (min-width: 992px) {
  .masthead,
  .mastfoot,
  .cover-container {
    width: 700px;
  }
}

y la reemplazas por esta otra:

@media (min-width: 992px) {
  .masthead,
  .mastfoot,
  .cover-container {
    width: 100%;
  }
}

Tercero, abres app/views/musicians/index.html.erb y dibujamos el <div id=”map”> que cargará el contenido de nuestro google map tal como la imagen

  <!-- contenedor del mapa -->
   <div class="site-wrapper">     
    <div  id="map" class="site-wrapper-inner">
      <div  class="cover-container">
        
     </div>
   </div>
 </div>
 <!--//fin contenedor mapa-->

<!-- footer -->
 <div class="container-fluid">
  <div class="row">
    <div class=" col-lg-12 mastfoot">
      <div class="inner">
        <p>street music map <%= link_to 'New Musician', new_musician_path %> </p>
      </div>
    </div>
  </div>
</div>
<!-- //fin footer-->

Musician Controller: Cargando los datos en el objeto @Hash.

En el controller musician en app/controllers/musicians_controller.rb cargamos un objeto @hash y llamamos al método buid_markers() de la gema Gmaps4Rails. Este método necesita un objeto en este caso lo cargamos con @musicians, el cual se comunica con el modelo a través de Musician.All devolviendo todos los registros de musicos que cargamos previamente.

Luego creamos el Marcador, damos su latitud, longitud y configuramos una ventana de información que se verá así.

  def index
    @musicians = Musician.all
    @hash = Gmaps4rails.build_markers(@musicians) do |musician, marker|
      marker.lat musician.latitude
      marker.lng musician.longitude
      marker.infowindow "<div class='box' style='width:200px;'><h4><strong>"+musician.musician_name+", "+musician.instrument.instrument_name+"</strong></h4><img src='http://img.youtube.com/vi/"+musician.youtube_video+"/mqdefault.jpg' width='111' height='90' class=''></div>"
    end
  end

Agregando el Script que dibuja el Mapa.

Ahora, inmediatamente después del html, vamos a añadir al final de app/views/musicians/index.html.erb este script:

<script type="text/javascript"> 
  handler = Gmaps.build('Google');
  handler.buildMap({ provider: {}, internal: {id: 'map'}}, function(){
    markers = handler.addMarkers(<%=raw @hash.to_json %>);
    handler.bounds.extendWith(markers);
    handler.fitMapToBounds();
  });
</script>

Lo que hace básicamente este script es construir el google Map.

Toda la data está contenida en el objeto @hash y google map con su método .addMarkers nos pide cargar un objeto “parseado a Json“. Para lograr esto en ruby lo hacemos asi <%=raw @hash.to_json %>

Google Maps trabaja con JSON, un standard para el intercambio de datos, con el fin de no atar su tecnología a un lenguaje de programación específico, sino que todo lo contrario, hacer que su tecnología sea compatible con cualquier lenguaje de programación con el que quieras trabajar.

Haz la prueba de imprimir por pantalla este código de ruby en la vista index:

<%=raw @hash.to_json %>

Puedes notar que obtienes una cadena de texto entre varios corchetes [{…},{…}] cierto? bueno, es la misma data que ingresamos en musician/new pero parseada en formato JSON, y si copias esta cadena más abajo en un json-parser como el que encontré, te mostrará la cadena en versión “bonita” y más legible.

[{"lat":49.2827291,"lng":-123.1207375,"infowindow":"\u003cdiv class='box' style='width:200px;'\u003e\u003ch4\u003e\u003cstrong\u003eAndres, guitarra\u003c/strong\u003e\u003c/h4\u003e\u003cimg src='http://img.youtube.com/vi/ANj8IJs38qU/mqdefault.jpg' width='111' height='90' class=''\u003e\u003c/div\u003e"},{"lat":-37.814107,"lng":144.96328,"infowindow":"\u003cdiv class='box' style='width:200px;'\u003e\u003ch4\u003e\u003cstrong\u003eEnsamble de Bronces Huevos Fritos, Brass\u003c/strong\u003e\u003c/h4\u003e\u003cimg src='http://img.youtube.com/vi/9WA-W7lI820/mqdefault.jpg' width='111' height='90' class=''\u003e\u003c/div\u003e"},{"lat":-33.4367933,"lng":-70.64107299999999,"infowindow":"\u003cdiv class='box' style='width:200px;'\u003e\u003ch4\u003e\u003cstrong\u003eAndres, piano\u003c/strong\u003e\u003c/h4\u003e\u003cimg src='http://img.youtube.com/vi/ANj8IJs38qU/mqdefault.jpg' width='111' height='90' class=''\u003e\u003c/div\u003e"},{"lat":-33.4691199,"lng":-70.641997,"infowindow":"\u003cdiv class='box' style='width:200px;'\u003e\u003ch4\u003e\u003cstrong\u003eAndrés, guitarra\u003c/strong\u003e\u003c/h4\u003e\u003cimg src='http://img.youtube.com/vi/ANj8IJs38qU/mqdefault.jpg' width='111' height='90' class=''\u003e\u003c/div\u003e"},{"lat":-33.4367933,"lng":-70.64107299999999,"infowindow":"\u003cdiv class='box' style='width:200px;'\u003e\u003ch4\u003e\u003cstrong\u003eAndrés, didgeridoo\u003c/strong\u003e\u003c/h4\u003e\u003cimg src='http://img.youtube.com/vi//mqdefault.jpg' width='111' height='90' class=''\u003e\u003c/div\u003e"},{"lat":-33.4363397,"lng":-70.6435372,"infowindow":"\u003cdiv class='box' style='width:200px;'\u003e\u003ch4\u003e\u003cstrong\u003efunky, didgeridoo\u003c/strong\u003e\u003c/h4\u003e\u003cimg src='http://img.youtube.com/vi/lMpZGAUGk8w/mqdefault.jpg' width='111' height='90' class=''\u003e\u003c/div\u003e"}]

Con estos pasos doy por finalizado el tutorial, si quieres agregar un Buscador de Músicos o de Instrumentos, revisa este Tutorial creado por Gonzalo “Haciendo un pequeño buscador en Ruby on Rails”. También para más personalizaciones del infoWindow que aparece en el, puedes revisar los ejemplos de gmaps4rails o descargar el código fuente del tutorial desde el repo que comparto con ustedes en mi cuenta de Github.

Hay bastante más que podríamos seguir integrando pero hasta aquí es la base del “how to” de este prototipo streetmusicmap y es totalmente reusable con otros conceptos. Lo entretenido es saber que en un rato (bueno o un fin de semana) puedes lograr con Ruby on Rails y unas cuantas gemas útiles, prototipos que concretan todas esas locas buenas ideas 🙂

Streetmusicmap.herokuapp.com

Share
December 12, 2014 Ruby, Tutorialesgeocoder, gmaps4rails, json, Ruby on Rails

StreetmusicMap parte 1: Combobox uno a muchos en Ruby on Rails

Hola Rubystas! para poner en práctica lo aprendido, lo mejor es crear proyectos experimentales para jugar. Aquí les presento una aplicación llamada streetmusicMap, está en su fase inicial, prototipo que comencé este fin de semana, y el cual estoy construyendo junto con mi partner de Software y creadora del blog ConciertosComentados: Melissa.

Para desarrollar esta app, comenzaré con la creación de 2 Scaffolds: Musician e Instrument. y los uniremos en el modelo a través de una relación “uno a muchos”, en donde visualmente nos ayudará un Combobox. En la Segunda Parte  mostraré como esa data la integramos a un Google Map, usando la gema gmaps4Rails.

 Creando la App.

Abres un Terminal y escribes:

$ rails new mapa

Acceder al proyecto desde el terminal:

$ cd mapa

Creando el Scaffold: Musician.

$ rails generate scaffold Musician latitude:float longitude:float youtube_video:string twitter:string facebook:string address:string description:string musician_name:string instrument_id:integer

(*el campo instrument_id:integer es una clave foranea del scaffold Instrument que realizaremos a continuación. y el campo latitude:float longitude:float los usaremos mas adelante en la parte 2 del streetMusicmap cuanodo integremos la gem gmaps4rails)

Ejecutamos en el terminal:

$ rake db:migrate

Creando el Scaffold: Instrument.

$ rails generate scaffold Instrument instrument_name:string

Ejecutamos en el terminal:

$ rake db:migrate

Ok, ahora tenemos 2 CRUD, Musician e Instrument (usen conceptos en inglés para crear scaffolds)

Agregar Instrumentos es simple, ya que es sólo un nombre. La parte que nos interesa es cuando agregamos un Músico, y tenemos que categorizarlo mediante un combobox cargado con instrumentos.

 Modelo: Creando la relación Uno a Muchos.

Accedemos al archivo routes a través de mapa/config/routes.rb y cambiamos “welcome#index” por:

root 'musicians#index'

Al acceder por browser a nuestra vista de músicos http://locahost:3000/musicians los datos se muestran de esta manera: Nombre del Musico / ID del instrumento…pero lo que queremos ver por pantalla es el nombre del instrumento no su ID! Para lograr este proposito es que creamos la relación “uno a muchos” en el modelo:

En app/models/musician.rb escribe:

class Musician < ActiveRecord::Base
 belongs_to :instrument
end

Y en app/models/instrument.rb escribes:

class Instrument < ActiveRecord::Base
 has_many :musicians
end

la relación entre Músico e Instrumento en nuestro ejercicio específicamente se lee así:

“un Músico pertenece_a una categoría” (belongs_to)

y “Una categoría tiene_muchos Musicos”. (has_many)

 La Vista: Cambiando instrument_id.

en app/views/ musicians/ index.html.erb buscas:

<%= musician.instrument_id %>

y lo reemplazas por:

<%= musician.instrument.instrument_name %>

Refrescas el browser y verás por pantalla ahora el Nombre del instrumento en lugar de su ID..mucho mejor!

 El Controller: Modificando el método new

Al mostrar la view /musicians/new tenemos que agregar un nuevo objeto @instruments, el cual recibirá todos los registros que el Modelo le devuelva y esos datos lo vamos a cargar en un combobox.

En app/controllers/musicians_controller.rb busca:

def new
 @musician = Musician.new
end

y lo reemplazas por:

def new
 @musician = Musician.new
 @instruments = Instrument.all
end

Ahora en la vista parcial app/views/musicians/_form.html.erb busca:

<%= f.number_field :instrument_id %>

y reemplázalo por este helper: (ésta línea dibuja el combobox de instrumentos por pantalla)

<%= collection_select(:musician, :instrument_id, @instruments, :id, :instrument_name, prompt: true) %>

Desde tu navegador ingresa a:

http://localhost:3000/musician/new

Excelente! 🙂 Ahora vemos un Combobox para categorizar a nuestros musicos. Más info sobre este Helper collection_select aquí!

Seguramente si accedes a la view “edit” verás un error, eso es porque tenemos que agregar un objeto @instruments en el método “edit” del controller musician ya que también al editar un registro de músico, necesitamos ver el combobox cargado pero posicionando en primer item el instrumento que le pertenece a este músico.

En app/controllers/musicians_controller.rb busca:

def edit

end

y lo reemplazas por:

def edit
 @musician = Musician.find(params[:id])
 @instruments = Instrument.all
end

Ya estamos casi terminando nuestra primera parte de la aplicación, sólo un detalle más…

En app/views/musicians/show.html.erb busca:

<%= @musician.instrument_id %>

y lo reemplazas por:

<%= @musician.instrument.instrument_name %>

Y ya tienes una aplicación uniendo 2 scaffolds y cargando un combobox en la Vista.

pd: Se viene luego la parte 2: Ahora te recomiendo ir por una buena taza de café y luego revisa el tutorial parte 2: Integración con google maps y la gema Gmaps4Rails.

Share
December 11, 2014 Ruby, Tutorialesgmaps4rails, google maps, Ruby on Rails, Tutoriales

Haciendo Un Pequeño Buscador En Ruby On Rails

Haciendo un buscador en Ruby on Rails

Una pregunta que se repite harto en el curso de En1mes es cómo hacer un buscador con ruby on rails, aquí la respuesta:

Paso 1: Para entender como funciona vamos a hacer un pequeño ejercicio, creemos un proyecto nuevo y llamemoslo buscador.

Paso 2: Creemos un scaffold de un recurso, digamos que estamos haciendo un buscador para un blog, donde el recurso principal son los posts, así que ejecutemos la línea:

rails g scaffold post titulo:string contenido:text

Paso 3: Hay que entender el paso de parámetros en rails, estas pueden ser pasadas por get (a través de la url) o por Post a través de algún formulario o dentro de la sesión, en este caso vamos a trabajar con el método get.

En google cuando nosotros buscamos algo podemos ver que el valor que buscamos también aparece en la URL acompañado de un q=

buscando desafíolatam en google

Ruby on Rails nos permite hacer exactamente lo mismo, capturar los valores que vienen de la URL ocupando un diccionario llamado params que captura todos los valores que vienen en la URL (entre otras cosas), por ejemplo si nosotros quisiéramos capturar el mismo valor lo podemos hacer desde el controller de post, en el método index

def index
  @q = params[:q]
  @posts = Post.all
end

Paso 4: Una vez que tenemos capturado el valor lo podemos mostrar en la vista de index de los posts.

<%= @q %>

Paso 5: El formulario

No podemos esperar que el usuario escribe el query a buscar en la URL, lo lógico es que haya un formulario de buscar, lo podríamos hacer con los helpers de Rails pero para mantener la simplicidad del tutorial lo vamos a hacer estilo html.

El formulario consiste simplemente en una etiqueta form y un input y un botón de envío (opcional) que vamos a poner en la vista index de los posts.

<form>
 <input name=”q” <%= @q %> >
 <button type=”submit”>Buscar</button>
</form>

Paso 6: Filtrar los resultados

Lo único importante que está faltando es filtrar los resultados de los posts en base a la búsqueda, para eso tenemos que volver al controller de los posts y editar el método index.

def index
  @q = params[:q]
  if @q
    @posts = Post.where(:titulo => @q)
  else
    @posts = Post.all
   end
end

Si quieren que continúe el post agregando cosas sobre como hacer match parciales y mejorando la búsqueda pueden presionarme por Twitter @gsanchezd ☺

Share
December 4, 2014 Bases de datos, Ruby, Tutoriales
Page 2 of 5«12345»
Tags
mostbetslotticamostbet UZslottica PLkudos casino no deposit bonuskudos casino bonus codeskudos casino free chipkudos casino loginRuby on Railskudos casino sister siteskudos casino free spinskudos casino no deposit bonus codesaviatoraviator KZozwincasinoozwincasino AUemprendimientos digitalesfortunetigerfortunetiger BRTutorialesDiseño20bet plbet20 casinokudos casinoLondonLondon UZ20 betbj88slottica BR20bet casino logowanie20bet kasynoHerramientas20 bet casinohtml5gratogana entrargratogana juegos en vivo20bet logowanieWordpressrubyLanding PageBases de datosplaycroco casinoplay crocogratogana onlineparty poker casino
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • PADANGTOTO
  • Interesado en otros tipos de emprendimiento?

    Quieres aprender a importar y exportar productos a todo el mundo? entra aquí

  • LOMBOKTOTO
  • LOMBOKTOTO
  • LOMBOKTOTO
  • LOMBOKTOTO
  • LOMBOKTOTO
  • LOMBOKTOTO
  • LOMBOKTOTO
  • LOMBOKTOTO
  • LOMBOKTOTO
  • LOMBOKTOTO
  • LOMBOKTOTO
  • LOMBOKTOTO
  • LOMBOKTOTO
  • LOMBOKTOTO
  • No te pierdas ningún artículo.

  • RAMALANTOTO
  • RAMALANTOTO
  • RAMALANTOTO
  • RAMALANTOTO
  • RAMALANTOTO
  • RAMALANTOTO
  • RAMALANTOTO
  • RAMALANTOTO
  • RAMALANTOTO
  • RAMALANTOTO
  • RAMALANTOTO
  • RAMALANTOTO
  • RAMALANTOTO
  • RAMALANTOTO
  • IRAMATOGEL
  • IRAMATOGEL
  • IRAMATOGEL
  • IRAMATOGEL
  • IRAMATOGEL
  • IRAMATOGEL
  • IRAMATOGEL
  • IRAMATOGEL
  • IRAMATOGEL
  • IRAMATOGEL
  • IRAMATOGEL
  • IRAMATOGEL
  • IRAMATOGEL
  • IRAMATOGEL
  • IRAMATOGEL
  • IRAMATOGEL
  • IRAMATOGEL
  • 2025 © UGMSLOT
    Planer theme by Dankov