node -v
# Tienes dos opciones para instalar NVM
curl https://raw.githubusercontent.com/creationix/nvm/v0.12.1/install.sh | bash
# wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.12.1/install.sh | bash
source ~/.profile
# Si no te funcionan los siguientes comandos, abre un terminal nuevo
nvm ls-remote # lista de versiones
nvm install v4.4.4 # intalacion
nvm current # version Node NVM activado
node -v # version Node que esta siendo usada
npm -v # version NPM que esta siendo usada
which node # donde esta instalado Node
# Ya podemos instalar los paquetes
npm -g install ember-cli # Install Ember-cli
npm -g install bower # Install bower package manager
npm -g install phantomjs # Install phantomJS (integration testing)
ember new proyecto # Creamos un nevo proyecto ember
cd proyecto
ember server # arrancamos el servidor
# Si clonaramos un proyecto de git
git clone git@github.com:...
cd proyecto
npm install # instalamos dependencias
bower install
ember server
# para usar una version concreta de Node
nvm use v4.4.4
viernes, 20 de mayo de 2016
Ember: Instalar Node.js/NPM sin Sudo
lunes, 10 de agosto de 2015
Iframe
# config/application.rb
# Enable IFrame
config.action_dispatch.default_headers = { 'X-Frame-Options' => 'ALLOWALL' }
Este es el codigo html del iframe
<iframe width="100%" frameborder="0" src="http://nuestra.apprails/" height="400"></iframe>
domingo, 2 de agosto de 2015
Instalar rbenv, ruby-build y bundler en Ubuntu
sudo apt-get update
sudo apt-get install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties libffi-dev
# inatalamos rbenvgit clone https://github.com/sstephenson/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
exec $SHELL
type rbenv #=> "rbenv is a function"
# instalamos ruby-buildgit clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
# Listado de las versiones de ruby$ rbenv install -l
# Instalamos ruby 2.2.2, lo designamos por defecto y lo comprobamosrbenv install 2.2.2
rbenv global 2.2.2
ruby -v
# para evitar intalar la documentecion de la gemasecho "gem: --no-ri --no-rdoc" > ~/.gemrc
# instalamos bundlergem install bundler
# Repo rbenv https://github.com/sstephenson/rbenv# Repo ruby-build https://github.com/sstephenson/ruby-build
# web bundler http://bundler.io/
# Recordatorio RVM, instalación y uso http://en-la-mina.blogspot.com/2012/01/recordatorio-rvm-instalacion-y-uso.html
martes, 13 de mayo de 2014
Aplicación de Datos: Python, Flask, pip y virtualenvs
- Fuente "Aplicación de Datos"
- Necesario instalación de entrada anterior "Python, Django, pip y virtualenvs en Ubuntu"
- Codigo fuente en github
Flask un micro framework para crear aplicaciones web en python. Usar pip para instalar Flask
$ pip install Flask
Crear directorio en donde pondremos archivos con código de la aplicación
$ mkdir mi-app
Adentro crear archivo llamado app.py, donde configuremos Flask y servira como backend de nuestro proyecto. Abrir app.py en un editor
from flask import Flask
app = Flask(__name__)
Configurar para hacer la raíz de tu sitio. Usaremos un archivo llamado 'index.html' para colocar la información. Tenemos que especificarlo en app.py
from flask import Flask
from flask import render_template
app = Flask(__name__)
@app.route("/")
def index():
return render_template('index.html')
Crear directorio "templates" dentro del directorio de nuestro proyecto.
$ mkdir templates
Crear "index.html" dentro del directorio "templates" y colocarle cualquier texto.
¡Hola Mundo!
Volver a editar app.py y agregarle lo siguiente para poder levantar el servidor local de Flask
from flask import Flask
from flask import render_template
app = Flask(__name__)
@app.route("/")
def index():
return render_template('index.html')
if __name__ == '__main__':
app.run(
host="0.0.0.0",
port=8000,
use_reloader=True,
debug=True,
)
Correr app.py en la linea de comandos. Mirar el resultado en un navegador en http://localhost:8000
$ python app.py
Comenzar nuevamente editando "index.html". Reemplazar el contenido por el esqueleto de un archivo HTML
Incendios en España entre 2004 y 2014
Crear directorio para guardar archivos estáticos. Aqui guardaremos el CSV con nuestros datos. Descargalo
$ mkdir static
Abrir app.py en editor de texto. Usaremos libreria csv para acceder a nuestros datos y pasarle la lista de datos del csv a index.html
from flask import Flask
from flask import render_template
app = Flask(__name__)
csv_path = './static/incendios.csv'
csv_obj = csv.DictReader(open(csv_path, 'r'))
csv_list = list(csv_obj)
@app.route("/")
def index():
return render_template('index.html',
object_list=csv_list,
)
if __name__ == '__main__':
app.run(
host="0.0.0.0",
port=8000,
use_reloader=True,
debug=True,
)
Guardar app.py y editar index.html. Colocar la lista del csv en el index.html. En linea de comandos correr app.py y visitar http://localhost:8000 nuevamente
Incendios en España entre 2004 y 2014
{{ object_list }}
Vamos a darle formato a los datos en index.html. Estamos usando el lenguaje de templating jinja de Flask
Incendios en España entre 2004 y 2014
IDPIF
Superficie Forestal Quemada
Fecha
Muertos
Heridos
Comunidad
Provincia
Comarca
Causa
Perdidas
{% for obj in object_list %}
{{ obj['IDPIF'] }}
{{ obj['SUPQUEMADA'] }}
{{ obj['FECHA'] }}
{{ obj['MUERTOS'] }}
{{ obj['HERIDOS'] }}
{{ obj['COMUNIDAD'].decode('UTF-8') }}
{{ obj['PROVINCIA'].decode('UTF-8') }}
{{ obj['COMARCA'].decode('UTF-8') }}
{{ obj['CAUSA'].decode('UTF-8') }}
{{ obj['PERDIDAS'] }}
{% endfor %}
Ahora página de detalles por incendio. Agregamos una nueva ruta en archivo "app.py"
@app.route('//')
def detail(number):
return render_template('detail.html')
Agreguemos el template "detail.html". Editamos el archivo detail.html. Agregar algo simple. Y levantamos la página en el navegador con cualquier número. http://localhost:8000/2004210126/
¡Hola Detalle!
Buscamos el incendio. Conectamos el número en la URL con el número identificador real del incendio en el CSV. Editamos app.py y convertimos la lista que tenemos en algo donde el incendio sea fácilmente buscable por identificador.
Editamos la función detail en app.py para que conecte el número en la URL con el registro correspondiente. Quedaría:
import csv
from flask import Flask
from flask import render_template
app = Flask(__name__)
csv_path = './static/incendios.csv'
csv_obj = csv.DictReader(open(csv_path, 'r'))
csv_list = list(csv_obj)
csv_dict = dict([[o['IDPIF'], o] for o in csv_list])
@app.route("/")
def index():
return render_template('index.html',
object_list=csv_list,
)
@app.route('//')
def detail(number):
return render_template('detail.html',
object=csv_dict[number],
)
if __name__ == '__main__':
app.run(
host="0.0.0.0",
port=8000,
use_reloader=True,
debug=True,
)
Volver a editar detail.html para agregarle datos desde nuestro CSV
{{ object['COMUNIDAD'].decode('UTF-8') }}
Editar "index.html" para enlazar la página del incendio. En la tag table reemplazar la fila de
{{ obj['IDPIF'] }}
Agregar el resto de los campos del incendio en detail.html
Incendio de {{ object['COMUNIDAD'].decode('UTF-8') }}
En la comunidad {{ object['COMUNIDAD'].decode('UTF-8') }}, provincia {{ object['PROVINCIA'].decode('UTF-8') }}, comarca {{ object['COMARCA'].decode('UTF-8') }}, municipio {{ object['MUNICIPIO'].decode('UTF-8') }} se quemó una superficie forestal de {{ object['SUPQUEMADA'] }}. Hubieron {{ object['MUERTOS'] }} muertos y {{ object['HERIDOS'] }} heridos. Se detectó en la fecha {{ object['FECHA'] }}. Se pudo controlar en {{ object['TIME_CTRL'] }} minutos y extinguir en {{ object['TIME_EXT'] }} minutos. La causa del incendio fue {{ object['CAUSA'].decode('UTF-8') }}. En la extinción del incendio participaron {{ object['PERSONAL'] }} personas, {{ object['PESADOS'] }} vehiculos pesados y {{ object['AEREOS'] }} medios aereos.
Javascript. Ahora vamos a colocar un mapa con los incendios usando una libreria de Javascript llamada Leaflet. Primero hay que importarla en el archivo "index.html"
...
Crear un elemento HTML para el mapa
...
Incendios en España entre 2004 y 2014
...
Y usar Leaflet para centrarlo en España. Inicializamos el mapa con las coordenadas de España y nivel de zoom
Agregamos la capa de tiles desde mapquest, que utiliza open street map. Se le pasa la URL para las imagenes de tiles, el nivel máximo de zoom (18) y el texto sobre de donde vienen los mapas.
Le agregamos el layer al elemento del mapa
Transformar los datos del CSV que tenemos a GeoJSON. GeoJSON es un formato para guardar estructuras de datos geograficos junto a información no geografica
Agregar una ventanita popup que muestre información sobre el incendio. Sustituir var dataLayer
Hacemos lo mismo en "detail.html" agregamos un mapa del incendio. Quedaria:
Incendio de {{ object['COMUNIDAD'].decode('UTF-8') }}
En la comunidad {{ object['COMUNIDAD'].decode('UTF-8') }}, provincia {{ object['PROVINCIA'].decode('UTF-8') }}, comarca {{ object['COMARCA'].decode('UTF-8') }}, municipio {{ object['MUNICIPIO'].decode('UTF-8') }} se quemó una superficie forestal de {{ object['SUPQUEMADA'] }}. Hubieron {{ object['MUERTOS'] }} muertos y {{ object['HERIDOS'] }} heridos. Se detectó en la fecha {{ object['FECHA'] }}. Se pudo controlar en {{ object['TIME_CTRL'] }} minutos y extinguir en {{ object['TIME_EXT'] }} minutos. La causa del incendio fue {{ object['CAUSA'].decode('UTF-8') }}. En la extinción del incendio participaron {{ object['PERSONAL'] }} personas, {{ object['PESADOS'] }} vehiculos pesados y {{ object['AEREOS'] }} medios aereos.
domingo, 20 de abril de 2014
Python, Django, pip y virtualenvs en Ubuntu
Instalamos entorno Python/Django [gdggranada.com]:
Ubuntu (12.04) ya trae Python (2.7), aun así comprobamos que está todo:
verdor@enlamina ~$ sudo apt-get install python-virtualenv python-pip python-dev sqlite3 python-sqlite build-essential
verdor@enlamina ~$ #sudo apt-get install python-imaging python-pythonmagick python-markdown python-textile python-docutils #parece que esto es opcional
- pip es una herramienta para instalar y administrar Paquetes Python (¿RubyGem?)
- virtualenvs o entornos virtuales (de Python) es un espacio completamente independiente de otros entornos virtuales y de los paquetes instalados globalmente en el sistema (¿RVM?) [Tutorial de Python virtualenv]
Podemos instalar Django con apt-get de sistema...
verdor@enlamina ~$ sudo apt-get install python-django
...o bajar los repos...
verdor@enlamina ~$ git clone https://github.com/django/django.git
... o usar pip...
verdor@enlamina ~$ pip install Django==1.6.2 # Estable
verdor@enlamina ~$ # pip install https://www.djangoproject.com/download/1.7b1/tarball/ # version beta 1.7
Continuamos...
Preparamos el Entorno:
Actualizamos pip e instalamos virtualenv (se puede hace con sudo)
verdor@enlamina ~$ pip install --upgrade pip
verdor@enlamina ~$ pip install --upgrade virtualenv # --upgrade es opcional
Preparamos el entorno:
verdor@enlamina ~$ cd src
verdor@enlamina ~/src$ mkdir entorno
verdor@enlamina ~/src$ cd entorno
verdor@enlamina ~/src/entorno$ virtualenv env
New python executable in env/bin/python
Installing setuptools, pip...done.
Activamos el entorno:
verdor@enlamina ~/src/entorno$ source env/bin/activate
(env)verdor@enlamina ~/src/entorno$ # ojo con el prompt
Instalamos django 1.5:
(env)verdor@enlamina ~/src/entorno$ pip install django==1.5
Downloading/unpacking django==1.5
Downloading Django-1.5.tar.gz (8.0MB): 8.0MB downloaded
...
Successfully installed django
Cleaning up...
Creamos un proyecto (luego distinguiremos entre proyecto y aplicación):
verdor@enlamina ~$ django-admin.py startproject mysite
verdor@enlamina ~$ cd mysite
verdor@enlamina/mysite ~$ python manage.py runserver
Validating models...
0 errors found
April 20, 2014 - 06:51:31
Django version 1.5, using settings 'mysite.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Vamos a comprobar que arranca la aplicación en el navegador http://127.0.0.1:8000/, y esto es lo que vemos:
It worked!
Congratulations on your first Django-powered page.
- If you plan to use a database, edit the
DATABASESsetting inmysite/settings.py. - Start your first app by running
python manage.py startapp [appname].
DEBUG = True in your
Django settings file and you haven't configured any URLs. Get to work!
¿Y donde esta el código generado de mi proyecto?
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py
- miblog/: El Directorio externo que contiene nuestro projecto.
- miblog/miblog: El directorio interno que sera el nombre que usaremos para importar el paquete.
- manage.py: Una utilidad de línea de comandos para interactuar con nuestro proyecto(crear las tablas, iniciar el servidor...).
- miblog/__init__.py: Un archivo vació requerido para que Python trate a este directorio como un paquete.
- miblog/settings.py: Configuraciones para este proyecto de Django.
- miblog/urls.py: La “tabla de contenidos” de nuestro proyecto.
- miblog/wsgi.py: El archivo encargado de ser compatible con el servidor web.
Editamos settings.py. Guias: maestrosdelweb.com django-en-cero-coma-i 1ªDjangoApp
Codificacion de caracteres:
#encoding:utf-8
Ruta del proyecto. Con ello creamos una nueva variable de configuración que guarda la ruta del proyecto, de manera que ahora podemos indicar el resto de rutas de forma relativa a la nueva variable. Además añadimos esta ruta al path de python lo que repercutirá en ventajas futuras.
# Identificando la ruta del proyecto
import os
PROJECT_PATH = os.path.dirname(os.path.realpath(__file__))
Configuramos la base de datos. Usamos sqlite3. También podríamos usar por fácilmente postgresql, mysql y oracle
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
'NAME': 'mysite.db', # Or path to database file if using sqlite3.
# The following settings are not used with sqlite3:
'USER': '',
'PASSWORD': '',
'HOST': '', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
'PORT': '', # Set to empty string for default.
}
}
Otras variables:
TIME_ZONE = 'Europe/Madrid'
LANGUAGE_CODE = 'es-es'
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
# Uncomment the next line to enable the admin:
'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
'django.contrib.admindocs',
# Esta es la aplicación que estamos haciendo
'mysite',
)
Aplicaciones instaladas INSTALLED_APPS: Un proyecto en Django necesita de aplicaciones, algunas ya vienen configuradas de manera predeterminada. En nuestro proyecto usaremos la aplicación de administración y su documentación, estas ya vienen construidas, y también nuestra primera aplicación creada líneas arriba, llamada principal. Para habilitar estas aplicaciones debemos buscar la siguiente sección que se encuentra casi al final del archivo settings.py. Django tendra que crear las tablas de estas aplicaciones adames de las que necesite nuestra propia aplicación mysite.
El resto de configuraciones se iran modificando a medida que lo necesitemos.
Creación de la base de datos. (Ojo, si no esta cargado el envairoment no funcionara):
(env)verdor@enlamina ~/src/entorno/mysite$ python -c "import django; print(django.get_version())" # Prueba
1.5
verdor@enlamina ~/src/entorno/mysite$ source ../env/bin/activate # Si falla lo cargamos así
(env)verdor@enlamina ~/src/entorno/mysite$ python manage.py sync #Creación BD
Creating tables ...
Creating table auth_permission
Creating table auth_group_permissions
Creating table auth_group
Creating table auth_user_groups
Creating table auth_user_user_permissions
Creating table auth_user
Creating table django_content_type
Creating table django_session
Creating table django_site
Creating table django_admin_log
You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (leave blank to use 'verdor'):
Email address:
Password:
Password (again):
Superuser created successfully.
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)
Configuramos las direcciones/rutas del proyecto. Fichero urls.py. Es solo descomentar algunas lineas:
from django.conf.urls import patterns, include, url
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'mysite.views.home', name='home'),
#url(r'^mysite/', include('mysite.foo.urls')),
# Uncomment the admin/doc line below to enable admin documentation:
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
url(r'^admin/', include(admin.site.urls)),
)
Arrancamos el servidor y ya podemos ir a la zona de administración http://127.0.0.1:8000/admin
(env)verdor@enlamina ~/src/entorno/mysite$ python manage.py runserver
Este es un buen momento usar git y hacer un comit inicial y montar un repositorio en github
? Antes de seguir. Lo que hemos hecho es crear un proyeco. Un proyecto puede estar compuesto de múltiples aplicaciones (ejemplo las que vienen por defecto en INSTALLED_APPS), y una aplicación se puede integrar en múltiples proyectos.
Creamos una aplicación:
Vamos a realizar un blog
verdor@enlamina ~$ ~/src/entorno/mysite$ source ../env/bin/activate #Cargamos el entorno
(env)samu@sub ~/src/entorno/mysite$ python manage.py startapp blog #Creamos al aplicacion
Ahora tenemos los siguientes ficheros:
mysite/
manage.py
blog/
__init__.py
models.py
tests.py
views.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py
Comenzamos con el modelo (ejemplo 1, ejemplo 2) (ORM). Editamos models.py:
from django.db import models
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=200)
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
category = models.ForeignKey(Category)
creation_date = models.DateTimeField(auto_now_add=True)
Antes de probar el modelo, hay que incluir la aplicación blog en el proyecto editando mysite/setting.py
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
# Uncomment the next line to enable the admin:
'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
'django.contrib.admindocs',
# Esta es el proyecto
'mysite',
# Esta es aplicación
'blog',
)
Una vez hecho esto ejecutamos el siguiente comando y comprobamos que se generan las consultas esperadas:
(env)verdor@enlamina ~/src/entorno/mysite$ python manage.py sqlall blog
BEGIN;
CREATE TABLE "blog_category" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(200) NOT NULL
)
;
CREATE TABLE "blog_post" (
"id" integer NOT NULL PRIMARY KEY,
"title" varchar(200) NOT NULL,
"content" text NOT NULL,
"category_id" integer NOT NULL REFERENCES "blog_category" ("id"),
"creation_date" datetime NOT NULL
)
;
CREATE INDEX "blog_post_6f33f001" ON "blog_post" ("category_id");
COMMIT;
Ahora creamos las tablar realmente:
(env)verdor@enlamina ~/src/entorno/mysite$ python manage.py syncdb
Creating tables ...
Creating table blog_category
Creating table blog_post
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)
Toca el momento de crear las vistas. Editamos blog/views.py e importamos los modelos que vayamos a utilizar:
# Create your views here.
from django.shortcuts import render_to_response
from blog.models import Category
from blog.models import Post
Tambien en blog/views.py añadiremos las funciones que gestionan las peticiones que se hagan al servidor. Algo así como los controladores de RoR.
# Create your views here.
from django.shortcuts import render_to_response
from blog.models import Category
from blog.models import Post
# Vista para un post
# Show
# template/post.html
def one_post(request, idpost):
post = Post.objects.get(id=idpost)
return render_to_response(
"post.html",
{
"post":post,
},
)
# Vista de un listado de posts
# Index
#template/home.html
def home(request):
posts = Post.objects.order_by("-creation_date")
return render_to_response(
"home.html",
{
"posts":posts,
},
)
# Vista de un listado de posts filtrado por category
#template/home.html
def posts_by_category(request, idcategory):
category = Category.objects.get(id=idcategory)
posts = category.post_set.order_by("-creation_date")
return render_to_response(
"home.html",
{
"posts":posts,
},
)
Ahora creamos las plantillas. Lo que en RoR serian las vistas. Se estarán en la carpeta blog/templates/
Creamos blog/templates/base.html. Se usará de base para generar el resto de las plantillas. Las plantillas heredarán de base.html, y a través de etiqueta block base.html mostrara el código de las plantillas que hereden de esta:
#blog/templates/base.html
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
Creamos post.html
{% extends "base.html" %}
{% block title %}
{{ post.title }}
{% endblock %}
{% block content %}
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
{% endblock %}
home.html
{% extends "base.html" %}
{% block title %}Mi blog{% endblock %}
{% block content %}
{% for post in posts %}
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
<hr>
{% endfor %}
{% endblock %}
Tenemos que indicar en al proyecto donde estan las plantillas, editamos TEMPLATE_DIRS de mysite/settinds.py :
TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
"../blog/templates",
)
Nos quedan crear las URLs de la aplicacion (las rutas). Lo primero indicar al proyecto que busque las URLs de la aplicacion blog. Editamos mysite/urls.py e indicamos que incluya las rutas de blog. Quedaria asi:
from django.conf.urls import patterns, include, url
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'mysite.views.home', name='home'),
#url(r'^mysite/', include('mysite.foo.urls')),
# Uncomment the admin/doc line below to enable admin documentation:
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
url(r'^admin/', include(admin.site.urls)),
# Rutas de la aplicacion blog
url(r'^', include('blog.urls')),
)
Ahora crearemos un fichero blog/urls.py de la aplicación. Debe quedar así:
from django.conf.urls import patterns, include, url
urlpatterns = patterns('',
url(
r'^post/(?P[0-9]+)/$',
'blog.views.one_post',
name="one_post"),
url(
r'^category/(?P[0-9]+)/$',
'blog.views.posts_by_category',
name="posts_by_category"),
url(
r'^$',
'blog.views.home',
name='home'),
)
Por último vamos hacer accesibles nuestro modelos den blog desde el panel de adminición. Para ello vamos a añadir un fichero admin.py en el directorio blog indicándoselo. Debería quedar así:
from django.contrib import admin
from blog.models import Category
from blog.models import Post
admin.site.register(Post)
admin.site.register(Category)
Símplemente registramos los modelos en el panel de administración. Por último, vamos a ejecutar de nuevo el comando para sincronizar la base de datos, ya que Django Admin añadirá alguna tabla más:
(env)verdor@enlamina ~/src/entorno/mysite$ python manage.py syncdb
Creating tables ...
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)
(env)verdor@enlamina ~/src/entorno/mysite$ python manage.py runserver
Ya podemos introducir algún post por la zona de admin http://localhost:8000/admin/ y luego verlo http://localhost:8000/post/1/
Consola Django
(env)verdor@enlamina ~/src/entorno/mysite$ python manage.py shell
Python 2.7.3 (default, Feb 27 2014, 19:58:35)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> import django
>>> from blog.models import Post, Category
>>> Category.objects.all()
[, ]
>>> Category.objects.all()[0]
>>> Category.objects.all()[0].id
1
>>> Category.objects.all()[0].name
u'ruby'
>>> Category.objects.all()[1].name
u'lorem'
>>>
Para que la salida de los objetos por la consola sea mas amigable, tendremos que añadir a los modelos los métodos "def __str__(self):" quedando el fichero bog/models.py de esta manera:
from django.db import models
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=200)
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
category = models.ForeignKey(Category)
creation_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '%s %s' % (self.title, self.creation_date)
jueves, 17 de abril de 2014
Raspberry Pi: Desplegando aplicación Rails,RVM,Thin en nginx con Capistrano
Configuración en el servidor:
Instalación de RVM multi-usuario [script]:
pi@raspberrypi ~ $ sudo su
root@raspberrypi:/home/pi# curl -L get.rvm.io | bash -s stable
#source /etc/profile.d/rvm.sh
root@raspberrypi:/home/pi# source /etc/profile
root@raspberrypi:/home/pi# rvm requirements;
root@raspberrypi:/home/pi# apt-get install build-essential openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev automake libtool bison subversion pkg-config
root@raspberrypi:/home/pi# rvm install 2.0.0
Tenemos que instalar Nginx. Esta explicado en la anterior entrada: Cambiando Apache por Nginx
Vamos a crear el usuario que realizara los deploy de capistrano. El aprovechamos para crear con un home diferente /var/deploy y alojar ahí las aplicaciones. Luego bloqueamos la contraseña, solo podremos logarnos y deployar a través de ssh.
root@raspberrypi:/home/pi# adduser --home /var/deploy deploy
root@raspberrypi:/home/pi# passwd -l deploy
Nos vamos ponernos como usuario deploy y lo configuramos para poder autenticarnos por ssh como el usuario deploy (explicado en entrada anterior):
root@raspberrypi:/home/pi# su - deploy
deploy@raspberrypi ~ $ pwd #comprobamos donde estamos y si es igual al HOME esperado
/var/deploy
deploy@raspberrypi ~ $ mkdir .ssh
deploy@raspberrypi ~ $ vim .ssh/authorized_keys #introducimos la llave publica a autorizar
Vamos a crear el gemset de nuestra aplicación y como instalaríamos thin:
deploy@raspberrypi ~ $ rvm use 2.0.0@showip --create
deploy@raspberrypi ~ $ rvm gemset create showip
deploy@raspberrypi ~ $ # gem install thin
Configuración en nuestra aplicación (entorno de desarrollo):
En el Gemfile añadimos capistrano y thin [ejemplo thin, ejemplo unicorn]:
# Use Capistrano for deployment
group :development do
gem 'capistrano'
gem "rvm-capistrano"
end
# Use Thin for production
gem 'thin', group: :production
Si no tenemos instalado ningún motor de Javascript en el servidor, tenemos que descomentar también la linea de therubyracer. Otra opción, instalar en el servidor nodejs.
Ejecutamos un bundle y comando para crear ficheros de capistrano:
$ bundle install
$ capify .
[add] writing './Capfile'
[add] writing './config/deploy.rb'
[done] capified!
Configuramos el fichero de /config/deploy.rb, (lo creamos si es necesario). En mi caso queda así:
require "rvm/capistrano"
#require "capistrano/ext/multistage"
require "bundler/capistrano"
#set :stages, %w(staging production) #Si queremos mas de un entorno
set :application, "showip"
set :repository, "git@github.com:verdor/showip.git"
default_run_options[:pty] = true
ssh_options[:forward_agent] = true
# la versión de ruby tiene que estar instalada y el gemset existir
# antes del cap deploy:setup
set :rvm_ruby_string, 'ruby-2.0.0-p451@showip'
set :rvm_type, :system
set :scm, :git
set :git_shallow_clone, 1
server "192.168.1.10", :app, :web, :db, primary: true
#server "showip.tk", :app, :web, :db, primary: true
set :user, "deploy"
set :keep_releases, 5
set :use_sudo, false
#set :port, 22 #sustituye con el puerto que usas
# Capistrano's default location "/u/apps/#{application}"
set :deploy_to, "/var/#{user}/apps/#{application}"
set :deploy_via, :remote_cache
set :branch, "master"
after "deploy:finalize_update" , "symlinks"
after "deploy", "deploy:cleanup"
namespace :deploy do
desc "Despues de ejecutar el setup subimos ficheros de configuracion"
task :setup_config, roles: :app do
#run "mkdir #{shared_path}/config"
#run "#{try_sudo} mkdir #{shared_path}/config"
top.upload("config/nginx.conf", "#{shared_path}/nginx.conf", via: :scp)
top.upload("config/thin_config.yml", "#{shared_path}/thin_config.yml", via: :scp)
top.upload("config/database.yml", "#{shared_path}/database.yml", via: :scp)
#top.upload(".rvmrc", "#{shared_path}/.rvmrc", via: :scp)
top.upload(".versions.conf", "#{shared_path}/.versions.conf", via: :scp)
#sudo "mv #{shared_path}/config/nginx.conf /etc/nginx/sites-available/showip"
#sudo "ln -nfs /etc/nginx/sites-available/showip /etc/nginx/sites-enabled/showip"
end
after "deploy:setup", "deploy:setup_config"
end
task :symlinks, roles: [:app] do
run <<-CMD
ln -s #{shared_path}/cache #{release_path}/public/;
ln -s #{shared_path}/database.yml #{release_path}/config/;
ln -s #{shared_path}/thin_config.yml #{release_path}/config/;
ln -s #{shared_path}/.versions.conf #{release_path}/;
CMD
end
namespace :deploy do
desc "Start the Thin processes"
task :start do
run <<-CMD
cd #{current_path}; bundle exec thin start -C config/thin_config.yml
CMD
end
desc "Stop the Thin processes"
task :stop do
run <<-CMD
cd #{current_path}; bundle exec thin stop -C config/thin_config.yml
CMD
end
desc "Restart the Thin processes"
task :restart do
run <<-CMD
cd #{current_path}; bundle exec thin restart -C config/thin_config.yml
CMD
end
end
Un a vez hecho esto, queremos ver el listado de tareas capistrano:
verdor@enlamina ~$ cap -T
Creamos el fichero de configuración del servidor en nginx para nuestra aplicación:
upstream showip {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name showip.pi showip.jeronima.tk showip.tk;
root /var/deploy/apps/showip/current/public/;
access_log /var/log/nginx/showip-access.log;
error_log /var/log/nginx/showip-error.log;
rewrite_log on;
location ~ ^/assets/ {
root /var/deploy/apps/showip/current/public;
gzip_static on;
expires 1y;
add_header Cache-Control public;
add_header ETag "";
break;
}
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_redirect off;
if (!-f $request_filename) {
proxy_pass http://showip;
break;
}
}
if (-f $document_root/system/maintenance.html) {
return 503;
}
error_page 503 @maintenance;
location @maintenance {
rewrite ^(.*)$ /system/maintenance.html last;
break;
}
error_page 500 502 503 504 /50x.html;
}
Escribimos nuestro fichero de configuracion del thin, pero al final no lo usamos y lo generamos con thin en el propio servidor, probar ejecutando thin -h:
---
chdir: /var/deploy/apps/showip/current
environment: production
address: 0.0.0.0
port: 3000
timeout: 30
log: /var/deploy/apps/showip/current/log/thin.log
pid: /var/deploy/apps/showip/current/tmp/pids/thin.pid
max_conns: 1024
max_persistent_conns: 100
require: []
wait: 30
threadpool_size: 20
servers: 1
user: deploy
group: deploy
daemonize: true
Ahora tenemos que preparar el servidor con capistrano:
verdor@enlamina ~$ cap deploy:update
verdor@enlamina ~$ cap deploy:start
* Ojo, la aplicación no tiene base de datos, ni asset.
Más configuración en el servidor. WRAPPERS. Que wrappers.
Queremos que nuestra aplicación se inicie como un servicio más (init.d):
pi@raspberrypi ~ $ sudo su
root@raspberrypi:/home/pi# source /etc/profile #cargamos rvm
root@raspberrypi:/home/pi# rvm use ruby-2.0.0-p451@showip
root@raspberrypi:/home/pi# thin install
Installing thin service at /etc/init.d/thin ...
mkdir -p /etc/init.d
writing /etc/init.d/thin
chmod +x /etc/init.d/thin
mkdir -p /etc/thin
To configure thin to start at system boot:
on RedHat like systems:
sudo /sbin/chkconfig --level 345 thin on
on Debian-like systems (Ubuntu):
sudo /usr/sbin/update-rc.d -f thin defaults
on Gentoo:
sudo rc-update add thin default
Then put your config files in /etc/thin
Genera el el fichero /etc/init.d/thin, mostramos como se crea, pero luego lo renombraremos y editaremos:
#!/bin/sh
### BEGIN INIT INFO
# Provides: thin
# Required-Start: $local_fs $remote_fs
# Required-Stop: $local_fs $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: S 0 1 6
# Short-Description: thin initscript
# Description: thin
### END INIT INFO
# Original author: Forrest Robertson
# Do NOT "set -e"
DAEMON=/usr/local/rvm/gems/ruby-2.0.0-p451@showip/bin/thin
SCRIPT_NAME=/etc/init.d/thin
CONFIG_PATH=/etc/thin
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
case "$1" in
start)
$DAEMON start --all $CONFIG_PATH
;;
stop)
$DAEMON stop --all $CONFIG_PATH
;;
restart)
$DAEMON restart --all $CONFIG_PATH
;;
*)
echo "Usage: $SCRIPT_NAME {start|stop|restart}" >&2
exit 3
;;
esac
:
Si vamos a tener más de una aplicación que use thin, renombramos el fichero /etc/init.d/thin, en nuestro caso por /etc/init.d/showip y modificamos...
SCRIPT_NAME=/etc/init.d/showip
CONFIG_PATH=/etc/showip #var/deploy/showip
Lo renombramos y ponemos en el arranque:
root@raspberrypi:~# mv /etc/init.d/thin /etc/init.d/showip
root@raspberrypi:~# sudo /usr/sbin/update-rc.d -f showip defaults
Generamos la configuracion del thin para nuestra aplicacion showip
root@raspberrypi:~# thin config -C /etc/thin/showip.yml -c /var/deploy/apps/showip/current --servers 1 -p 3000
Wrote configuration to /etc/thin/showip.yml
Editamos el fichero del config /etc/thin/showip.yml para ver si le damos algun retoque:
---
chdir: /var/deploy/apps/showip/current
environment: production
address: 0.0.0.0
port: 3000
timeout: 30
log: log/thin.log
pid: /var/deploy/apps/showip/current/tmp/pids/thin.pid
max_conns: 1024
max_persistent_conns: 100
require: []
wait: 30
threadpool_size: 20
servers: 1
user: deploy
group: deploy
daemonize: true
Generamos el wrapper de RVM ya que la ruta /usr/local/rvm/gems/ruby-2.0.0-p451@showip/bin/thin no nos acaba de funcionar, despues editaremos de forma definitiva /etc/init.d/showip
root@raspberrypi:~# rvm wrapper ruby-2.0.0-p451@showip showip thin
Regenerating ruby-2.0.0-p451@showip wrappers.........
Comprobamos que se ha generado (es un enlace blando):
root@raspberrypi:~# ls /usr/local/rvm/bin/ | grep showip
showip_thin
Podemos probarlo y si hay algun fallo en el fichero de configuracion, nos lo dira:
root@raspberrypi:~# /usr/local/rvm/bin/showip_thin start -C /etc/thin/showip.yml
/usr/local/rvm/rubies/ruby-2.0.0-p451/lib/ruby/2.0.0/psych.rb:205:in `parse': (/etc/thin/showip.yml): could not find expected ':' while scanning a simple key at line 15 column 1 (Psych::SyntaxError)
#o funcionara
Starting server on 0.0.0.0:3000 ...
root@raspberrypi:~# /usr/local/rvm/bin/showip_thin stop -C /etc/thin/showip.yml
Stopping server on 0.0.0.0:3000 ...
Sending QUIT signal to process 3001 ...
Exiting!
Ya generado el wrapper editamos /etc/init.d/showip dejandolo como queda:
#!/bin/sh
### BEGIN INIT INFO
# Provides: thin
# Required-Start: $local_fs $remote_fs
# Required-Stop: $local_fs $remote_fs
# Default-Start: 2 3 4 5
# Default-Stop: S 0 1 6
# Short-Description: thin initscript
# Description: thin
### END INIT INFO
# Original author: Forrest Robertson
# Do NOT "set -e"
DAEMON=/usr/local/rvm/bin/showip_thin
SCRIPT_NAME=/etc/init.d/showip
CONFIG_PATH=/etc/thin/showip.yml
#chown=/bin/chown
#mkdir=/bin/mkdir
# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0
case "$1" in
start)
$DAEMON start -C $CONFIG_PATH
;;
stop)
$DAEMON stop -C $CONFIG_PATH
;;
restart)
$DAEMON restart -C $CONFIG_PATH
;;
*)
echo "Usage: $SCRIPT_NAME {start|stop|restart}" >&2
exit 3
;;
esac
:
Los fichero creados los ponemos como propiedad del usuario deploy:
chown deploy:deploy /etc/init.d/showip
Hacemos una pruaba antes de reiniciar y ver que arranca la aplicación:
pi@raspberrypi ~ $ sudo service showip start
Starting server on 0.0.0.0:3000 ...
Ya podemos ir desarrollando, subir al repositorio y hacer deploy con las ultimas versiones del código.
verdor@enlamina$ cap deploy
Tendríamos que dar algunos retoques si tuviéramos mas de un entrono (entorno de pruebas) y la aplicación necesitase de base de datos, etc...
Enlaces:
miércoles, 16 de abril de 2014
Tips Linux
df -h
Conocer espacio ocupado de cache apt:
du -sh /var/cache/apt/archives
Elimina del cache los paquetes .deb con versiones anteriores a los de los programas que tienes instalados:
sudo apt-get autoclean
sudo apt-get clean #Elimina todos los paquetes del cache.
sudo apt-get autoremove #Borra los paquetes huérfanos
Ver RAM ocupada en megas y SWAP:
free -m -t
Lista de procesos que se están ejecutando:
top
Cuanto tiempo lleva arrancada su máquina:
uptime
Ejecuta un script/programa en el arranque:
sudo vi /etc/init.d/miscript #creamos script
sudo chmod 755 /etc/init.d/miscript #le damos permisos de ejecución
sudo /etc/init.d/miscript start #lo probamos
sudo /etc/init.d/miscript stop #lo paramos
sudo update-rc.d miscript defaults #lo metemos en el arranque
sudo update-rc.d -f miscript remove #cuando lo queramos eliminar del arranque
Instalar servidor escritorio remoto
sudo apt-get install xrdp
Instalar cliente escritorio remoto
sudo aptitude install remmina remmina-gnome
martes, 11 de marzo de 2014
Raspberry Pi: Cambiando Apache por Nginx
pi@raspberrypi ~ $ sudo service apache2 stop
Instalamos Nginx (fuente)
pi@raspberrypi ~ $ sudo apt-get update
pi@raspberrypi ~ $ sudo apt-get upgrade
pi@raspberrypi ~ $ sudo apt-get install nginx openssl ssl-cert php5-cli php5-sqlite php5-gd
php5-curl php5-common php5-cgi sqlite3 php-pear php-apc curl libapr1 libtool curl
libcurl4-openssl-dev php-xml-parser php5 php5-dev php5-gd php5-fpm memcached php5-memcache varnish
Configuramos Nginx con un solo procesador:
pi@raspberrypi ~ $ sudo vim /etc/nginx/nginx.conf
#/etc/nginx/nginx.conf
user www-data;
worker_processes 1;
pid /var/run/nginx.pid;
Arrancamos Nginx:
pi@raspberrypi ~ $ sudo /etc/init.d/nginx start
Abrimos el navegador apuntando a ip de la Raspberry Pi http://192.168.1.10/ y aparecerá
Welcome to nginx!
Nginx pide certificarnos, así que creamos unos para dos años[*]:
pi@raspberrypi ~ $ sudo openssl req $@ -new -x509 -days 730 -nodes -out /etc/nginx/cert.pem -keyout /etc/nginx/cert.key
Generating a 2048 bit RSA private key
.....+++
........................+++
writing new private key to '/etc/nginx/cert.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:ES
State or Province Name (full name) [Some-State]:MADRID
Locality Name (eg, city) []:MADRID
Organization Name (eg, company) [Internet Widgits Pty Ltd]:MyRaspberryPi
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:owncloud.myraspberrypi.tk
Email Address []:myraspberrypi@gmail.com
Les damos permisos
pi@raspberrypi ~ $ sudo chmod 600 /etc/nginx/cert.pem
pi@raspberrypi ~ $ sudo chmod 600 /etc/nginx/cert.key
Creamos la configuración para ownCloud
pi@raspberrypi ~ $ sudo vim /etc/nginx/sites-available/owncloud
Creamos enlace blando
pi@raspberrypi ~ $ sudo ln -s /etc/nginx/sites-available/owncloud /etc/nginx/sites-enabled/
Configuramos /etc/php5/fpm/php.ini
pi@raspberrypi ~ $ sudo vim /etc/php5/fpm/php.ini
# /etc/php5/fpm/php.ini
upload_max_filesize = 1000M
post_max_size = 1000M
# Añadimos al final del fichero
extension = apc.so
apc.enabled = 1
apc.include_once_override = 0
apc.shm_size = 256
Configuramos /etc/php5/fpm/pool.d/www.conf:
pi@raspberrypi ~ $ sudo vi /etc/php5/fpm/pool.d/www.conf
listen = 127.0.0.1:9000
Reiniciamos web server y PHP
pi@raspberrypi ~ $ sudo /etc/init.d/php5-fpm restart
pi@raspberrypi ~ $ sudo /etc/init.d/nginx restart
Y como ya teníamos la instalación de ownCloud con Apache, ya debería estar funcionando.
Desinstalamos Apache
pi@raspberrypi ~ $ sudo apt-get purge apache2
Vamos ha hacer que el deamon-transmission vaya por nuestro Neginx, creamos el fichero de configuración /etc/nginx/sites-available/transmission que quedara así:
# redirect http to https.
server {
listen 80;
server_name torrent.myraspberrypi.tk transmission.myraspberrypi.tk;
return 301 https://$server_name$request_uri; # enforce https
}
server {
listen 443 ssl;
server_name torrent.myraspberrypi.tk transmission.myraspberrypi.tk;
ssl_certificate /etc/nginx/cert.pem;
ssl_certificate_key /etc/nginx/cert.key;
# Thats the important part. Most of the tutorial on the net are not Transmission specific
# and don't pass the Transmission-Session Header
location / {
proxy_read_timeout 300;
proxy_pass_header X-Transmission-Session-Id;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# if you changed the port number for transmission daemon, then adjust the
# folllowing line
proxy_pass http://127.0.0.1:9091/transmission/web/;
}
# Also Transmission specific
location /rpc {
proxy_pass http://127.0.0.1:9091/transmission/rpc;
}
location /upload {
proxy_pass http://127.0.0.1:9091/transmission/upload;
}
}
Creamos un enlace blando
pi@raspberrypi ~ $ sudo ln -s /etc/nginx/sites-available/transmission /etc/nginx/sites-enabled/transmission
Ahora la configuración para amule:
# redirect http to https.
server {
listen 80;
server_name amule.myraspberrypi.tk;
return 301 https://$server_name$request_uri; # enforce https
}
server {
listen 443 ssl;
server_name amule.myraspberrypi.tk;
ssl_certificate /etc/nginx/cert.pem;
ssl_certificate_key /etc/nginx/cert.key;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:4711/;
proxy_redirect off;
proxy_http_version 1.0;
}
}
Creamos un enlace blandoraspberry pi
pi@raspberrypi ~ $ sudo ln -s /etc/nginx/sites-available/amule /etc/nginx/sites-enabled/amule
Para la red local de casa, crear virtual host y redirigiros desde el /etc/hosts a la ip de la red local que tiene la raspberry py.
martes, 4 de marzo de 2014
Raspberry Pi: Conocer ip publica, y mandarla por correo con tarea cron
pi@raspberrypi ~ $ sudo apt-get install curl # si nos hace falta instalar curl
pi@raspberrypi ~ $ curl icanhazip.com
xxx.xxx.xxx.xxx
Para enviar correos tenemos que instalar [fuente], sendmail, ssmtp, mailutils:
pi@raspberrypi ~ $ sudo apt-get install postfix mailutils
Para enviar emails:
echo "texto a teclear" | mail -s "Asunto" usuario1@dominio.com
Este seria el correo que querríamos mandar:
echo "$(curl ifconfig.me) $(date)" | mail -s "RaspberryPi: $(curl icanhazip.com) $(date)" enlamina@gmail.com
Creamos un script que mande el correo [*]:
pi@raspberrypi ~ $ vi scripts/mailip.sh
#!/bin/sh
# scripts/mailip.sh
# Correo con la ip externa
echo "$(curl ifconfig.me) $(date)" | mail -s "RaspberryPi: $(curl icanhazip.com) $(date)" enlamina@gmail.com
Guardamos con :wq y cambiamos permisos de ejeccución:
pi@raspberrypi ~ $ chmod u+x scripts/mailip.sh
Comprobamos el estatus de el demonio de cron y editamos /etc/crontab y añadimos linea:
pi@raspberrypi ~ $ sudo /etc/init.d/cron status
[ ok ] cron is running.
pi@raspberrypi ~ $ sudo vi /etc/crontab
# /etc/crontab: system-wide crontab
# m h dom mon dow user command
00 10 * * * pi /home/pi/scripts/mailip.sh
y reiniciamos cron:
pi@raspberrypi ~ $ sudo /etc/init.d/cron restart
Se pueden programar tareas para cuando se inicia la maquina, ejemplo:
@reboot pi /home/pi/scripts/mailip.sh
Ahora vamos a usar un servicio de dns dinámico, será http://www.dnsdynamic.org/ API, y actualizaremos a la ip que tiene que apuntar cada media hora con una tarea cron, una vez que nos demos de alta creamos la tarea:
pi@raspberrypi ~ $ vi scripts/update_dnsdynamic.sh
#!/bin/bash
DNSD_USERNAME=enlamina@gmail.com
DNSD_PASS=mi_clave
DNSD_SERVER=www.dnsdynamic.org
DNSD_HOSTNAME=raspberryverdor.dnsdynamic.net
MY_IP=$(curl icanhazip.com)
curl -s -u $DNSD_USERNAME:$DNSD_PASS "https://$DNSD_SERVER/api/?hostname=$DNSD_HOSTNAME&myip=$MY_IP"
sleep 3
exit 0
Damos permisos de ejecución:
pi@raspberrypi ~ $ chmod u+x update_dnsdynamic.sh
Editamos con la herramienta de crontab para el usuario pi y añadimos la tarea:
pi@raspberrypi ~ $ sudo crontab -u pi -e
# m h dom mon dow command
*/30 * * * * /home/pi/scripts/update_dnsdynamic.sh
domingo, 2 de marzo de 2014
Raspberry Pi: Montar clientes Torrent, aMule y servidor ownCloud
pi@raspberrypi ~ $ sudo apt-get -y install transmission-daemon
Lo paramos y configuramos, usaremos disco duro externo:
pi@raspberrypi ~ $ sudo /etc/init.d/transmission-daemon stop
pi@raspberrypi ~ $ cd /media/descargas
pi@raspberrypi ~ $ mkdir torrent
pi@raspberrypi ~ $ cd torrent
pi@raspberrypi ~ $ mkdir finish
pi@raspberrypi ~ $ mkdir temp
pi@raspberrypi ~ $ chmod 777 finish
pi@raspberrypi ~ $ chmod 777 temp
ls -l
Configuración:
pi@raspberrypi ~ $ sudo vi /var/lib/transmission-daemon/info/settings.json
Campos que tenemos que modificar:
“download-dir”: “/media/descargas/torrent/finish”
“incomplete-dir-enabled”: true
“incomplete-dir”: “/media/descargas/torrent/temp”
“rpc-enabled”: true
“rpc-bind-address”: “0.0.0.0″
“rpc-username”: “transmission”
"rpc-whitelist": "127.0.0.1"
“rpc-whitelist-enabled”: false
Arrancamos el servicio:
pi@raspberrypi ~ $ sudo /etc/init.d/transmission-daemon start
Y accedemos desde nuestro ordenador al cliente torrent de la Raspberry Pi. Le pusimos ip estatica y el usuario y la clave por defecto es "transmission":
http://192.168.1.32:9091/transmission
Configuración aMule
Instalamos el demonio:
pi@raspberrypi ~ $ sudo aptitude install amule-daemon
Indicamos un usuario:
pi@raspberrypi ~ $ sudo vi /etc/default/amule-daemon
# Configuration for /etc/init.d/amule-daemon
# The init.d script will only run if this variable non-empty.
AMULED_USER="pi"
# You can set this variable to make the daemon use an alternative HOME.
# The daemon will use $AMULED_HOME/.aMule as the directory, so if you
# want to have $AMULED_HOME the real root (with an Incoming and Temp
# directories), you can do `ln -s . $AMULED_HOME/.aMule`.
AMULED_HOME=""
Comando para iniciar, parar... el demonio
pi@raspberrypi ~ $ sudo /etc/init.d/amule-daemon start
pi@raspberrypi ~ $ sudo /etc/init.d/amule-daemon stop
Generamos contraseña, harán falta dos, una para la aplicación, y otra para para la gestión a través de la aplicación web
pi@raspberrypi ~ $ echo -n "contraseña" | md5sum
4c882dcb24bcb1bc225391a602feca7c -
Configuramos la aplicación:
vi ~/.aMule/amule.conf
AcceptExternalConnections=1
ECPassword=4c882dcb24bcb1bc225391a602feca7c valor md5 de la contraseña
[WebServer]
Enabled=1
Password=4c882dcb24bcb1bc225391a602feca7c
AllocateFullFile=1 # Reserva el espacio
Generamos la configuración de la aplicación web aMule usando la configuración de la aplicación
amuleweb --create-config-from=/home/username/.aMule/amule.conf
Se puede editar. Para que funcionara tuve que poner claves con mayúsculas tanto en amule.conf como en remote.conf
pi@raspberrypi ~ $ vi .aMule/remote.conf
Locale=
[EC]
Host=localhost
Port=4712
Password=4c882dcb24bcb1bc225391a602feca7c
[Webserver]
Port=4711
UPnPWebServerEnabled=0
UPnPTCPPort=50001
Template=
UseGzip=1
AllowGuest=0
AdminPassword=4c882dcb24bcb1bc225391a602feca7c
GuestPassword=
Reiniciamos el demonio y vamos a la ip estatica de la Raspberry Pi en el puerto por defecto:
pi@raspberrypi ~ $ sudo /etc/init.d/amule-daemon restart
[ ok ] Restarting aMule daemon: amuled.
http://192.168.1.32:4711/amuleweb-main-dload.php
Server Recomendados:
!! Saugstube !!
ed2k://|server|193.138.221.214|4242|/
#eMule Serverlist Nr.1#
ed2k://|server|193.138.221.213|4242|/
#eMule Serverlist Nr.2#
ed2k://|server|193.138.221.210|4242|/
..:: France Mule #1 ::..
ed2k://|server|193.42.213.30|9510|/
eDonkeyServer No1
ed2k://|server|77.247.178.244|4242|/
Instalación de servidor OwnCloud
Instalamos servidor Apache:
pi@raspberrypi ~ $ sudo apt-get install apache2 php5 php5-json php5-gd php5-sqlite curl libcurl3 libcurl3-dev php5-curl php5-common php-xml-parser
Instalamos base de datos SQLite:
pi@raspberrypi ~ $ sudo apt-get install sqlite
Nos descargamos el OwnCloud:
pi@raspberrypi ~ $ cd tmp
pi@raspberrypi ~/tmp $ wget download.owncloud.org/community/owncloud-5.0.0.tar.bz2
Descomprimir el archivo y copiarlo en el directorio /var/www
pi@raspberrypi ~/tmp $ sudo tar -xjf owncloud-5.0.0.tar.bz2 -C /var/www
Cambiar propietarios de la carpeta OwnCloud.
pi@raspberrypi ~ $ sudo chown www-data:www-data -R /var/www/owncloud
pi@raspberrypi ~ $ sudo chown www-data:www-data -R /media/descargas #Disco Duro Externo puede fallar
Editar el tamaño máximo de subida de archivos en Apache. Indicamos 2G.
sudo vi /etc/php5/apache2/php.ini
# /etc/php5/apache2/php.ini
upload_max_size = 2048 M
post_max_size = 2048 M
Reiniciamos Apache:
pi@raspberrypi ~ $ sudo service apache2 restart
Para que owncloud vaya mas rápido, instalar el acelerador php cache y reiniciar el apache:
pi@raspberrypi ~ $ sudo apt-get install php-apc
pi@raspberrypi ~ $ sudo service apache2 restart
Comprobamos que esta funcionando y acabamos la instalación http://tuip/owncloud
Nos muestra un error:
Los datos del directorio (carpeta /media /descargas/) es legible para otros usuarios
Por favor, cambie los permisos a 0770 Sun que el directorio no se pueden enumerar por otros usuarios.
Se soluciona editando el fichero /var/www/owncloud/lib/util.php y comentamos parte del código, quedando así:
/*if (stristr(PHP_OS, 'WIN')) {
//TODO: permissions checks for windows hosts
} else {
$permissionsModHint = 'Please change the permissions to 0770 so that the directory'
.' cannot be listed by other users.';
$prems = substr(decoct(@fileperms($dataDirectory)), -3);
if (substr($prems, -1) != '0') {
OC_Helper::chmodr($dataDirectory, 0770);
clearstatcache();
$prems = substr(decoct(@fileperms($dataDirectory)), -3);
if (substr($prems, 2, 1) != '0') {
$errors[] = array('error' => 'Data directory ('.$dataDirectory.') is readable for other users',
'hint' => $permissionsModHint);
}
}
}*/
Solo falta crear usuario en ownCloud y que las descargas vayan a su carpeta files o crear enlaces blandos.
PD. Hacer que transmission, amule y owncloud se lleven bien. fuente molesybits.
Para evitar el parche de los permisos de owncloud hay que hacer que los usuarios www-data y debian-transmission se lleven bien haciendo que ambos usuarios compartan el mismo grupo editando /etc/group:
pi@raspberrypi ~ $ sudo vi /etc/group
Buscamos el grupo debian-transmission y añadimos a los usuarios pi y www-data, quedando la linea:
#/etc/group
debian-transmission:x:111:pi:www-data
Y damos permisos al usuario www-data a la carpeta owncloud del disco duro externo si fuera necesario.
pi@raspberrypi ~ $ cd /media/descargas/owncloud
pi@raspberrypi ~ $ sudo chown -R www-data:debian-transmission data
y reiniciamos los servicios:
pi@raspberrypi ~ $ sudo service apache2 restart
pi@raspberrypi ~ $ sudo service transmission-daemon restart
domingo, 16 de febrero de 2014
Raspberry Pi: Configurar ip fija, acceso ssh y montarle disco duro externo
pi@raspberrypi ~ $ ifconfig
eth0 Link encap:Ethernet HWaddr b8:27:eb:e7:76:6d
inet addr:192.168.1.31 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:463 errors:0 dropped:3 overruns:0 frame:0
TX packets:334 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:48748 (47.6 KiB) TX bytes:36262 (35.4 KiB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
wlan0 Link encap:Ethernet HWaddr 80:1f:02:af:2c:ef
inet addr:192.168.1.32 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:507 errors:0 dropped:526 overruns:0 frame:0
TX packets:5 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:103617 (101.1 KiB) TX bytes:1195 (1.1 KiB)
Nos conectamos a traves de ssh. ssh -X pi@192.168.1.13 y he introducimos la clave. Por defecto "raspberry"
verdor@enlamina ~$ ssh pi@192.168.1.31
Linux raspberrypi 3.6.11+ #474 PREEMPT Thu Jun 13 17:14:42 BST 2013 armv6l
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Feb 16 21:58:15 2014 from 192.168.1.33
pi@raspberrypi ~ $
Asignamos una ip fija a la Raspberry Pi. Se configura en /etc/network/interfaces
pi@raspberrypi ~ $ sudo vi /etc/network/interfaces
#/etc/network/interfaces
auto lo
iface lo inet loopback
#iface eth0 inet dhcp
iface eth0 inet static
address 192.168.1.31
gateway 192.168.1.1
netmask 255.255.255.0
allow-hotplug wlan0
iface wlan0 inet manual
wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
#iface default inet dhcp
iface default inet static
address 192.168.1.32
netmask 255.255.255.0
gateway 192.168.1.1
Reiniciamos la Raspberry Pi para ver que tome los cambios:
pi@raspberrypi ~ $ sudo reboot
Queremos autenticarnos a la Raspberry Pi a través de una llave ssh, ya tenemos una.
Hacemos en el servidor, la Raspberry Pi:
pi@raspberrypi ~ $ pwd
/home/pi
pi@raspberrypi ~ $ mkdir .ssh; chmod 700 .ssh
pi@raspberrypi ~ $ cd .ssh
pi@raspberrypi ~ $ touch authorized_keys; chmod 600 authorized_keys
En el cliente:
verdor@enlamina ~$ cd ~/.ssh
verdor@enlamina ~$ cat id_dsa.pub| ssh pi@192.168.1.32 'cat - >> ~/.ssh/authorized_keys'
Ahora configuramos ssh para acceder mas fácilmente a la Raspberry Pi:
verdor@enlamina ~$ vi ~/.ssh/config
#/home/verdor/.ssh/config
Host raspberrypi
User pi
HostName 192.168.1.31
IdentityFile /home/verdor/.ssh/id_rsa
Guardamos con wq y entramos en la Raspberry Pi
verdor@enlamina ~$ ssh raspberrypi
Linux raspberrypi 3.6.11+ #474 PREEMPT Thu Jun 13 17:14:42 BST 2013 armv6l
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Sun Feb 16 22:49:09 2014 from 192.168.1.33
pi@raspberrypi ~ $
Montamos disco duro externo para datos.
Buscamos dispositivos conectados:
pi@raspberrypi ~ $ lsusb
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 7392:7811 Edimax Technology Co., Ltd EW-7811Un 802.11n Wireless Adapter [Realtek RTL8188CUS]
Bus 001 Device 005: ID 152d:2329 JMicron Technology Corp. / JMicron USA Technology Corp. JM20329 SATA Bridge
Averiguamos como se llama el dispositivo:
pi@raspberrypi ~ $ blkid
/dev/mmcblk0p1: LABEL="RECOVERY" UUID="242D-1618" TYPE="vfat"
/dev/mmcblk0p5: SEC_TYPE="msdos" LABEL="boot" UUID="676B-0317" TYPE="vfat"
/dev/mmcblk0p6: UUID="0eb36e9e-40f5-47f4-a751-4e197c0dd7c8" TYPE="ext4"
/dev/sda1: UUID="XXXX-XXXX" TYPE="vfat"
Para obtener información mas detallada de la lista de las unidades conectadas:
pi@raspberrypi ~ $ sudo fdisk -l
Disk /dev/mmcblk0: 7861 MB, 7861174272 bytes
4 heads, 16 sectors/track, 239904 cylinders, total 15353856 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000ba6a2
Device Boot Start End Blocks Id System
/dev/mmcblk0p1 2048 2466796 1232374+ e W95 FAT16 (LBA)
/dev/mmcblk0p2 2473984 15353855 6439936 85 Linux extended
/dev/mmcblk0p5 2482176 2596863 57344 c W95 FAT32 (LBA)
/dev/mmcblk0p6 2605056 15353855 6374400 83 Linux
Disk /dev/sda: 120.0 GB, 120034123776 bytes
255 heads, 63 sectors/track, 14593 cylinders, total 234441648 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000683e5
Device Boot Start End Blocks Id System
/dev/sda1 63 234436544 117218241 c W95 FAT32 (LBA)
Creamos carpeta para el disco duro:
pi@raspberrypi ~ $ sudo mkdir /media/descargas
Editamos /etc/fstab para que se monte automáticamente al arrancar, añadimos la ultima linea:
pi@raspberrypi ~ $ sudo vi /etc/fstab
# /etc/fstab
proc /proc proc defaults 0 0
/dev/mmcblk0p5 /boot vfat defaults 0 2
/dev/mmcblk0p6 / ext4 defaults,noatime 0 1
# a swapfile is not a swap partition, so no using swapon|off from here on, use dphys-swapfile swap[on|off] for that
UUID="XXXX-XXXX" /media/descargas vfat defaults
Damos permisos de lectura y escritura al directorio de montaje:
pi@raspberrypi ~ $ sudo chmod -Rf 777 /media/descargas
Y montamos o reiniciamos:
pi@raspberrypi ~ $ sudo mount -a
Lo próximo será montar clientes Torrent, aMule y servidor Owncloud
miércoles, 27 de noviembre de 2013
Validación XML
dtd = XML::Dtd.new(IO.read(dtd_path, encoding: "UTF-8"))document = io ? XML::Document.io(xml[:tempfile], encoding: XML::Encoding::ISO_8859_1) : document = XML::Document.file(xml, encoding: XML::Encoding::ISO_8859_1)document.validate(dtd)2ª Opción
xsd = Nokogiri::XML::Schema(File.read(PO_SCHEMA_FILE))doc = Nokogiri::XML(File.read(PO_XML_FILE))xsd.validate(doc).each do |error| puts error.messageendhttp://www.xmlsoft.org/xmldtd.html
http://www.xmlvalidation.com/
sábado, 21 de enero de 2012
Recordatorio RVM, instalación y uso
- ¿que es RVM?
Ruby Version Manager permite gestionar varios entornos de desarrollo Ruby por versiones y dentro de cada versión de Ruby, distintos entornos mediante diferentes conjuntos de conjuntos de gemas. Para cada Ruby hay un gemset Global al que acceden todos los demás gemset - Instalación de RVM:
bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)
Añadimos la siguiente línea al fichero de configuración ~/.bashrc, teniendo en cuenta que no haya ningún “return” antes:Abrimos otro shell y comprobamos que se haya instalado correctamenteecho '[[ -s "$HOME/.rvm/scripts/rvm" ]] && . "$HOME/.rvm/scripts/rvm" # Load RVM function' >> ~/.bash_profile
type rvm | head -1 #la salida sera rvm is a function
- Instalar una versión de ruby con RVM
rvm install ruby-1.9.3-p0 # ultima versión estable rvm --default use ruby-1.9.3-p0 #lo dejamos por defecto ruby -v # compruebo con que versión estoy trabajando - Pregunto por la versión de rubygem:
gem -v #si es menor de 1.8.11 la actualizamos gem update –system #actualizacion (no os hará falta)
- Crear un gemset (entorno de trabajo para rails 3.2.0) , actualizo gema rake si es necesario
rvm ruby-1.9.3-p0@rails320 --create --default # creo entorno rails320 por defecto rvm gemset list #comprobamos que se ha creado gem list #pedimos que nos muestre la información actual sobre las gemas que tenemos gem update rake # si la versión de rake es menor que 0.9.2.2 actualizamos rake -version rvm install ruby-1.9.3-p0 # ultima versión estable
- Instalamos rails 3.2.0 (http://rubygems.org/gems/rails):
gem install rails -v 3.2.0.rc2 # le indicamos la ultima versión apunto de salir, en breve estable
# gem install rails #toma la última versión estable
rails -v # Consulta la versión de la gema rails - listado de otros comandos:
rvm info # información de configuración y sistemarvm list # lista de rubies instaladosrvm list known # lista de rubies que se pueden instalarrvm gemset list # lista de gemsetrvm gemset list_all # lista de gemsets en cada rubyrvm gemset create rails312 # crea el gemset rails312rvmruby-1.9.3-p0@rails312 # nos movemos al nuevo gemsetrvm gemset userails312 # moverse de gemset dentro de la misma versión de rubygem install rails -v 3.1.2 # instalamos en este gemset la versión de rails 3.1.2#rvm gemset deleterails312 #borramos el gemset rails312#rvm uninstall ree,1.8.7 #borramos ruby con passenger y ruby 1.8.7
- Puedes crear ficheros de configuración el tus proyectos en un fichero .rvmrc y así cuando cambias de directorio cargas el entorno correcto, versión de ruby y conjunto de gemas: http://beginrescueend.com/workflow/rvmrc/
# ../myapp/.rvmrc rvm_gemset_create_on_use_flag=1 rvm use 1.9.3-p0 rvm gemset use rails320myapp - También puedes configurar el prompt para que te indique la configuración con la que estas trabajando: http://beginrescueend.com/workflow/prompt/
Fuente: RVM
código
jueves, 12 de mayo de 2011
Generar pdf con wicked_pdf en Rails
sudo mv wkhtmltopdf-tu_version /usr/local/bin/
Instalamos la gema como plugin en nuestra aplicacion Rails:
script/plugin install git://github.com/mileszs/wicked_pdf.git
script/generate wicked_pdf
Tenemos que configurar el plugin para que sepa que versión del Wicked hemos instalado y donde esta. Para ello en config/enviroments.rb (rails 1.x), o donde corresponda en tu aplicación, ponemos algo así:
WickedPdf.config = {
:exe_path => '/usr/local/bin/wkhtmltopdf-amd64',
:zoom => 1.0,
:margin => { :top => 10,:bottom => 10, :left => 10, :right => 10},
:outline => { :outline => true },
:disable_smart_shrinking => false
}
Hay muchas mas posibles opciones, que también se pueden cambiar cuando llamamos a la vista desde el controlador:
def show
respond_to do |format|
format.html
format.pdf do
render :pdf => "file_name"
end
end
end
Fuentes: github, bunario wkhtmltopdf, uso y configuracion por snikt
miércoles, 27 de abril de 2011
jueves, 14 de abril de 2011
Gmate, Gedit como TextMate con Ubuntu
sudo apt-add-repository ppa:ubuntu-on-rails/ppa
sudo apt-get update
Paso 2: Instalar el paquete
sudo aptitude install gedit-gmate
Paso 3: Instalar otros plugins
sudo apt-get install gedit-plugins
nueva ruta gedit3: ~/.local/share/gedit/plugins
Paso 4: Uso y configuración de algunos plugins sacado de josemariaberlanga
- Align: alinea bloques de texto en columnas
- Class Browser: en ruby y RoR usamos clases, nos será muy útil este navegador de clases para manejar funciones y variables.
- Document Statistics: no es primordial pero me gusta saber el número de lineas que llevo escritas, número de palabras, espacios en blanco, etc.
- External Tools: añade una nueva opción al menú Tools, desde ahi podremos ejecutar comandos como en un shell, muy útil para ejecutar todas las posibilidades de un proyecto Ruby on Rails.
- File Browser Pane: fundamental. Un navegador de archivos para movernos rapidamente por las carpetas del proyecto.
- Find in Files: encuentra en todos los archivos de tu root de proyecto (busca en todos los archivos dentro de la carpeta donde te encuentres en el navegador de archivos).
- Gemini: útil si te acostumbras, cierra parentesis, corchetes y comillas dobles.
- Go to File: una forma fácil para moverte entre archivos. Potente si lo manejas desde el teclado.
- Rails Extract Partial: un plugin que nos facilita sacar parciales con sólo pulsar un botón. Muy útil en ciertos momentos.
- Rails File Loader: identifica si un archivo es parte de un proyecto Ruby on Rails y lo señala como lenguaje.
- Rails Hot Command: una opción que se nos abre con todas las opciones de comandos que dispone Rails, muy útil si estamos empezando y aún no los sabemos. Aún después nos será de ayuda a veces jeje
- TabSwitch: se nos activa la posibilidad de cambiar de pestaña con Ctrl-tab.
- Word Completion: completa la palabra que estemos escribiendo. Es útil pero hay que tener cuidado de no caer demasiado, pues a veces las sugerencias pueden dar caso a error. Es un plugins que necesita aún mejorar.
- TextMate Style Autocompletion: completa la palabra que estemos escribiendo pulsando Esc, con cada pulsación muestra una nueva palabra, necesita configuración y no es compatible con Word Completion
- Zen Coding: Este plugins es útil sobretodo si no usamos gemas como haml -el cual recomiendo-. No ayudará a escribir código html, hay varios tutoriales por internet pero basicamente escibes la palabra clave y pulsando Ctrl+E se escribe el codigo HTML.
- Comentar codigo: comentamos el texto seleccionado con Ctrl-M, descomentamos con Ctrl-Mays-M
- Mostrar espacios: dibuja los espacio con un punto, interesante para ver sangria
Fuentes: gmate, josemariaberlanga, joserojas
viernes, 18 de marzo de 2011
Instalar jQuery and jQuery UI en Rails 3
Necesitaremos también los CSS del zip que están localizados en /css/[nombre_del_tema] del zip y los copiamos en ~/public/stylesheets. Finalmente copiamos el contenido de las imagenes en el directorio ~/public/images.
Por lo visto hay que editar el css y reemplazar donde aparece 'mages/' por '/images/'.
Una vez hecho esto hay que indicarle a rails que los use, para ello editamos application.html.erb en ~/views/layouts y le añadimos la siguiente linea dentro de la etiqueta head:
<%= stylesheet_link_tag :all, 'jquery-ui-1.8.custom' %>
<%= javascript_include_tag 'jquery-1.4.2.min', 'jquery-ui-1.8.custom.min', 'rails' %>
<%= csrf_meta_tag %>
Ya solo me falta que esto ande en Refinery-CMS Refinery-Core 0.9.9.4Fuente y enlaces: eddorre gem rails3-jquery-autocomplete * jquery-ujs rails-jquery-autocomplete-tutorial
domingo, 13 de marzo de 2011
Repasando: Partials
Los partial son pequeñas plantillas que se pueden insertar en otras vistas, esta plantilla puede aparecer en varias vistas, asi ahorramos tener que escribirla varias veces. El nombre de estas vistas parciales comienzan con un guión bajo. Un ejemplo de partial:
# _book.erb.html
<%= book.title %>, <%= book.author %>
Con solo invocarlo desde otra planatilla (vista) es suficiente. Un ejemplo de llamada:
<%= render :partial => "book" %> #fallaria, el partial usa una variable que no es globalEstos partials pueden necesitas variables. Se puede pasarle un objeto
render(:partial => "book", :object => @my_book)#el partial usa una var. que se llama como elSi existe @book, podemos omitir el pará́metro :object
render(:partial => "book")Tambien se pueden pasar valores adicionales, que estarán disponibles como variables locales
render(:partial => "book",:locals => { :owner => "Hermenegildo" })Enlace API Rails, Banot.net
sábado, 5 de marzo de 2011
Aplicación Refinerycms en Heroku con SQLite
#0. Prerrequisitos
# http://devcenter.heroku.com/articles/quickstart#prerequisites
# instalar git y crear un clave ssh [MaCaCoDer]
# crear una cuenta en Heroku
# instalar y configuras RVM
# http://rvm.beginrescueend.com/
# instalamos SQLite database Browser por ejemplo
#1. instalamos en rvm la versión 1.9.2
rvm install ruby-1.9.2-p180
#2. cambiamos a este ruby
rvm 1.9.2
#3. creamos el gemset de la aplicación
rvm gemset create gemset_my_app
#4. nos movemos al nuevo gemset
rvm gemset use gemset_my_app
#5. instalamos rails, no se si refiney te lo instala sino lo tienes en el gemset
gem install rails -v=3.0.3
# me ha instalado la versión 3.0.5 ¿?
#6. instalamos refinerycms y lo que haga falta para heroku
# http://refinerycms.com/guides/how-to-install-refinery-on-heroku
gem install refinerycms -v=0.9.9.4
gem install heroku -v=1.18.2
#7. Configuracion de la gema de Heroku
heroku list
heroku help # ayuda
#8. creamos nuestra aplicación refinery para heroku
# esto te crea la aplicación (como rails)
# instala bundler, ejecuta bundle install
# instala mas gemas como aws-s3 para poner fotos en amazone
# http://amedrodriguez.com/blog/2010/09/configurando-amazon-s3-en-rails/
# crea la BBDD SQLite y te migra
# te inicia git, te hace un comit y un push a heroku
refinerycms myapp --heroku
#9. [OPCIONAL] creamos cuenta en amazone web service http://aws.amazon.com/es/
# email: un_correo@dominio.dom
# pass: mycalve#####
# luego habrá que configurar la aplicación para su uso
#10. Como no quiero trabajar con la cuenta que me acabo de crear para el proyecto
# entramos en Heroku y añado como colaborador otra cuenta que tengo.
# Pasos para bajarse el proyecto.
# http://devcenter.heroku.com/articles/sharing
heroku info --app myapp # que sera en la que colaboro
heroku login # me logo
heroku keys:add # añado mi clave publica ssh (hay que crearla antes)
# bajamos el repositorio
git clone git@heroku.com:septimodia.git -o production
# ahora trabajamos con git:
git commit -a -m "log of the changes I made"
git push production master
-----> Heroku receiving push
-----> Launching.... done
#11. [OPCIONAL:ME PETA]
# No se si es que ya tenia el repositorio, o porque había renombrado la app *
# pero se ve esto:
git push production master
No refs in common and none specified; doing nothing.
Perhaps you should specify a branch such as 'master'.
fatal: The remote end hung up unexpectedly
error: failed to push some refs to 'git@heroku.com:myapp.git'
! No such app as empty-journey-445
fatal: The remote end hung up unexpectedly
# http://getsatisfaction.com/railstutorial/topics/problem_pushing_to_heroku
# edito .git/config del directorio de mi aplicacion "myapp"
[remote "production"]
fetch = +refs/heads/*:refs/remotes/production/*
url = git@heroku.com:myapp.git # edito esta linea
# repito el commit y el push, parece que funciona
#12. migramos en producción.
heroku rake db:migrate
# voy a ver si funciona la aplicación
http://myapp.heroku.com/ # funciona!!
miércoles, 23 de febrero de 2011
Tareas RAKE definidas en Rails
- rake -T # Imprime en pantalla un listado de las tareas por defecto de tu aplicación Rail
- rake about # List versions of all Rails frameworks and the environment
- rake db:create # Crea la BD según config/database.yml para el actual modo de trabajo (desarrollo, testeo o producción) de tu aplicacion Rail (si se usa db:create:all crea todas las BD de la configuracion)
- rake db:drop # Borra la BD, también se puede usar db:drop:all
- rake db:structure:dump # Descarga la base de datos con estructura de SQL.
- rake db:migrate # Migración de la base de datos a través del script db-migrate, para especificar la versión añada VERSION =X.
- rake db:migrate:status # Vemos el satado de las migraciones.
- rake rollback # Restaura a la última versión antes de la actual.
- rake db:test:clone # Recrea la base de datos de prueba del esquema de la base de datos
- rake routes # Imprime en pantalla todas las rutas definidas
- rake db:sessions:clear # Borra las sesiones
- rake db:sessions:create # Crea una table para usar con CGI::Session::ActiveRecordStore
- rake rails:update # Actualiza configuraciones, scripts y los javascripts de Rails.
- rake rails:update:configs # Actualiza config/boot.rb de la instalación actual de Rails.
- rake stats # Reporta las estadísticas de código de la aplicación.
- rake test # Prueba todas las unidades y funciones.
- rake log:clear # Borra todos los datos en /log.
- rake tmp:cache:clear # Borra todos los archivos y directorios en tmp/cache.
- rake tmp:clear # Borra sessiones, cache y archivos socket de folder /tmp.
- rake doc:rails # Crea lo archivos HTML de Rails.
Enlaces stuartellis jasonseifer rails-db-rake-tasks rodolinux rake.rb
Más mesmarty