Mi dominio principal es escael.com y como soy aficionado a la fotografía tengo un blog con la url escael.blogspot.com que decidí redireccionar a un subdominio de escael.com, fotos.escael.com.
Hasta aquí la documentación de google es muy clara y no voy a explicar aquí. Para configurar los DNS con Cloudflare debe quedar de la siguiente forma:

Lo importante es desmarcar la opción de Cloudflare de proxy HTTP y dejar solo gestión de DNS.
Espero que le sirva a alguien, yo pase varias horas y no encontraba como solucionarlo.
The post Subdominio Blogger en Cloudflare first appeared on Escael Marrero.]]>
Voy a preparar otra chuleta, de esas que ya van siendo comunes por aquí, que me ayudan a tener recogido y organizado, de cierta manera, las informaciones que necesito para el día a día.
Hoy voy a explicar de manera rápida y sencilla como instalar un servidor NFS para comunicarnos entre el mac y la máquina virtual que tengamos instalada. Hasta ahora he utilizado Samba, pero este protocolo de red es muy lento y en ocasiones me crea «bloqueos» con el IDE (Sublime Text) y manda todo a la mier….
Pues investigando un poco, veo que NFS es mucho mejor, al menos más rápido (esto lo he podido comprobar). Pero que es NFS. Hurgando por ahí me encontré con esto:
«NFS (sistema de archivos de red: «Network File System») es un protocolo que permite acceso remoto a un sistema de archivos a través de la red. Todos los sistemas Unix pueden trabajar con este protocolo; cuando se involucran sistemas Windows, debe utilizar Samba en su lugar».
Pongamos manos a la obra:
1. Instalar servidor NFS. En nuestra máquina virtual, en mi caso, Ubuntu Server 14.04.2 LTS:
sudo apt-get install nfs-kernel-server nfs-common rpcbind
2. Comprobar la instalación:
grep nfs4 /proc/filesystems
que debe devolver algo como esto:

3. Ver cual es nuestro user ID y grupo ID para posteriormente incluirlos:
echo $UID echo $GROUPS
4. Editar el fichero /etc/exports
sudo vi /etc/exports
5. Agregar la siguiente configuración:
/var/www/html ip-del-cliente(rw,async,insecure,all_squash,anonuid=1000,anongid=1000)
en anonuid=1000,anongid=1000 agregar el id del usuario y del grupo respectivamente que hemos obtenido en el punto 3. Esto permite tener permisos de escritura.
6. Reiniciar el servidor de NFS:
sudo /etc/init.d/nfs-kernel-server restart
7. Montar el directorio en nuestro Mac:
mount -t nfs ip-del-servidor:/var/www/html /Users/usuario/carpeta-del-proyecto/
8. Desmontar el directorio en nuestro Mac:
umount /Users/usuario/carpeta-del-proyecto/
Y eso sería todo. El directorio montado aparecerá en la carpeta que hayamos seleccionado.
The post Instalar servidor NFS first appeared on Escael Marrero.]]>Existe multitud de documentación al respecto, en este post he querido resumir los pasos que sigo normalmente. Aprovecho que tengo que instalar una máquina virtual nueva y relato lo que voy haciendo y así me sirve de guía para futuros proyectos y a vosotros os puede servir. Porque si habéis indagado un poco sobre el tema, cada quien hace esto como le viene en gana y la documentación cambia de un sitio a otro. Resumiendo pongo la que a mi me ha funcionado, para sumar un poco de caos a este mundo de muy señor mio, como dicen por ahí.
Nota: Esta documentación esta orientada a Ubuntu. Aunque es perfectamente aplicable a cualquier sistema.
1- Sino lo tienes ya, instala Git como controlador de versiones:
Ahora vamos a instalar Gulpjs para gestionar las tareas de nuestro despliegue de estáticos. Pero antes necesitamos npm como paquete de NodeJs, y tener instalado NodeJs:
Hasta aquí tenemos instalado NodeJs. Ahora instalamos npm:
A continuación viene un proceso que no acabo de entender bien pero que consiste en dar permisos al usuario para que pueda instalar y ejecutar npm sin ser root (los paquetes de NodeJs se instalan a nivel global o a nivel local). De no ser así tendríamos que instalar todos los paquetes de npm como root y esto no esta recomendado, además de ser un coñazo el ir introduciendo contraseña cada vez que queramos hacer algo. Por lo tanto, poner como propietario al usuario a todas los paquetes de npm.
Esta línea no la tengo muy clara, pero basicamente ejecuta npm a nivel local:
Ahora, si he entendido bien, esta configuración vuelve a su punto de origen una vez que se reinicia la sección de usuario. Sería molesto tener que correr dicho comando cada vez que iniciemos la sección. Para ello editamos el fichero .bashrc y agregamos lo siguiente:
Por último creamos un enlace simbólico de NodeJs a node:
(Ayuda en NPM sobre permisos: Fixing npm permissions)
En Digital Ocean tienen un tutorial bastante completo sobre el tema.
Otra de las aplicaciones que vamos a utilizar es Bower, que nos permitirá gestionar los paquetes y sus versiones. Para instalarlo seguimos con npm:
Una vez hecho podremos instalar Gulp a nivel global. Fijarse que no usamos sudo:
Verificamos que Gulp.js ha sido instalado correctamente.
Si esta correcto saldrá algo así:
Ahora vamos a instalar Gulp en un proyecto local. Creamos una carpeta que será la que contendrá nuestro proyecto. Dentro de la misma creamos un fichero:
A continuación tecleamos la instrucción:
que nos pedirá los datos de nuestro proyecto y lo vamos rellenando según nuestra información.
Para instalar gulp en el proyecto local:
Aquí ya estaríamos listos para instalar los paquetes de gulp que vamos a utilizar. Voy a documentar las de uso común y pondré el fichero gulpfile.js con ejemplos de su implementación. Los mismos se pueden hallar aquí: https://www.npmjs.com/package/package
Estos son los que vamos a instalar:
Todos estos paquetes se instalarán en local. Las instrucciones son las mismas, solo cambia el nombre:
Cuando hayamos instalado estos paquetes ya podemos abrir el gulfile.js y crear nuestras primeras tareas:
var gulp = require('gulp');
var sass = require('gulp-sass');
var concat = require('gulp-concat');
var uglify = require('gulp-uglify');
gulp.task('sass', function () {
gulp.src('sass/**/*.{scss,sass}')
.pipe(sass({
errLogToConsole: true
}))
.pipe(gulp.dest('css'));
});
gulp.task('watch', function() {
gulp.watch('sass/**/*.{scss,sass}', ['sass'])
});
gulp.task('default', ['sass', 'watch']);
Como podemos observar la configuración de tareas es muy sencilla. Primero incluimos los paquetes que vamos a necesitar. Después creamos la tarea con gulp.task y al final la lanzamos con el comando gulp en terminal. sino le pasamos ningún parámetro el va a llamar a la task «default».
Y eso sería todo. Espero que este mini tutorial os pueda servir para algo. Por mi parte ya tengo todos los pasos que necesito en un solo lugar
Si veo que falta algo útil lo iré incluyendo, o si alguno por ahí necesita que amplíe no dudéis en dejar un comentario.
Es cierto que existen tutoriales para realizar casi todo lo que uno se proponga. Por lo tanto no voy a inventar la rueda y pretender que lo que diga aquí no este explicado en multitud de webs. Ese no es mi objetivo, sino el de recopilar una serie de ejemplos sobre como realizar determinadas tareas y tenerlas agrupadas en un mismo lugar. De esa manera contaré con ellas para cuando las necesite y estarán disponibles para todos aquellos interesados que por alguna razón aterricen en este espacio.
Voy a comenzar en el mismo punto donde me di cuenta que necesitaba ayuda. Estaba intentando enviar un simple email con OctoberCms y fui incapaz de hacerlo. Este tutorial es una guía de como hacerlo con Laravel.
Esta realizado siguiendo esta magnifica guía de vídeo tutoriales, publicada por Manuel J. Dávila que me ha servido para ir aprendiendo. Los mencionados vídeos están geniales pero hecho de menos un lugar donde poder consultar los códigos que ha ido mostrando el autor. Esos códigos por lo tanto los veréis aquí, exactamente los mismos, con alguna que otra pequeña modificación de mi parte. Como dije anteriormente para tenerlos a mano y para uso de cualquiera que los necesite. Sin más dilatación vamos a comenzar.
Voy a iniciar en el tutorial número 7, por las razones que ya exprese, pero sino conocen mucho de este framework os aconsejo que veáis los vídeos tutoriales desde el inicio.
'host' => 'smtp.gmail.com',
'from' => array('address' => '[email protected]', 'name' => 'Nombre'),
'username' => 'tuusername',
'password' => 'tucontraseña',
Aquí quiero detenerme un segundo. Yo tengo configurado como aplicación de SMTP el Exim. Los datos que agreguemos en el fichero mail.php deben ser los mismos que están en la configuración del Exim, tal y como se muestra en este enlace: http://dajul.com/2009/06/08/configurar-exim4-con-gmail-o-google-apps/. De no hacerlo así a mi, al menos, no me enviaba los emails.

{{ Form::open(array
(
'action' => 'HomeController@contacto',
'method' => 'POST',
'role' => 'form',
))
}}
//campos del formulario aquí....
{{ Form::close() }}
Toda la documentación al respecto la podéis ver aquí: http://laravel.com/api/4.2/
<div class="form-group">
{{ Form::label('name', 'Nombre:') }}
{{ Form::input('text', 'name', null, array('class' => 'form-control')) }}
</div>
<div class="form-group">
{{ Form::label('email', 'Email:') }}
{{ Form::input('email', 'email', null, array('class' => 'form-control')) }}
</div>
<div class="form-group">
{{ Form::label('subject', 'Asunto:') }}
{{ Form::input('text', 'subject', null, array('class' => 'form-control')) }}
</div>
<div class="form-group">
{{ Form::label('msg', 'Mensaje:') }}
{{ Form::textarea('msg', null, array('class' => 'form-control')) }}
</div>
{{ Form::input('hidden', 'contacto') }}
{{ Form::input('submit', null, 'Enviar', array('class' => 'btn btn-primary')) }}
En el vídeo solo agregan los label: {{ Form::label(‘Nombre:’) }}. Yo he agregado el atributo for al label para cuando se de clic sobre el nombre se seleccione el campo, quedando como lo veis arriba.

<html>
<head></head>
<body>
<p>Nombre del contacto: {{$name}}</p>
<p>Email del contacto: {{$email}}</p>
<p>Asunto: {{$subject}}</p>
<p>Mensaje:</p>
{{$msg}}
</body>
</html>

public function contacto()
{
$mensaje = null;
if (isset($_POST['contacto']))
{
$data = array
(
'name' => Input::get('name'),
'email' => Input::get('email'),
'subject' => Input::get('subject'),
'msg' => Input::get('msg')
);
$fromEmail = '[email protected]';
$fromName = 'Nombre';
Mail::send('emails.contacto', $data, function($message) use ($fromName, $fromEmail)
{
$message->to($fromEmail, $fromName);
$message->from($fromEmail, $fromName);
$message->subject('Nuevo mensaje de contacto');
});
$mensaje = '<div class="text-info">Mensaje enviado con éxito</div>';
}
return View::make('HomeController.contacto', array('mensaje' => $mensaje));
}
Route::post('/contacto', array('as'=>'contacto', 'uses'=>'HomeController@contacto'));
En el tutorial esto no se explica, cuando lo probé me dio un error y después de buscar di con la solución. La vista contacto esta ruteada como Get, es decir, todos los parámetros se están pasando por este método y con el envío del formulario se hacen por Post, por eso da error. La solución es agregarle también a la vista ese método de envío y problema resuelto. Si alguien puede explicarlo mejor genial.
Ahora vamos a validar el formulario. Para ello tenemos que ir modificando el controlador y la vista. La documentación de este apartado la podéis consultar en: http://laravel.com/docs/4.2/validation
$rules = array ( 'name' => 'required|regex:/^[a-zA-Z\s]*$/|min:3|max:80', 'email' => 'required|email|between:3,80', 'subject' => 'required|regex:/^[a-zA-Z\s0-9]+$/|min:3|max:80', 'msg' => 'required|between:3,500', );
$validator = Validator::make(Input::All(), $rules);
public function contacto()
{
$mensaje = null;
if (isset($_POST['contacto'])) /* Campo oculto contacto */
{
$rules = array
(
'name' => 'required|regex:/^[a-zA-Z\s]*$/|min:3|max:80',
'email' => 'required|email|between:3,80',
'subject' => 'required|regex:/^[a-zA-Z\s0-9]+$/|min:3|max:80',
'msg' => 'required|between:3,500',
);
$validator = Validator::make(Input::All(), $rules, $messages);
if ($validator->passes())
{
$data = array
(
'name' => Input::get('name'),
'email' => Input::get('email'),
'subject' => Input::get('subject'),
'msg' => Input::get('msg')
);
$fromEmail = '[email protected]';
$fromName = 'escael';
Mail::send('emails.contacto', $data, function($message) use ($fromName, $fromEmail)
{
$message->to($fromEmail, $fromName);
$message->from($fromEmail, $fromName);
$message->subject('Nuevo mensaje de contacto');
});
$mensaje = 'Mensaje enviado con éxito';
}
else
{
return Redirect::back()->withInput()->withErrors($validator);
}
}
return View::make('HomeController.contacto', array('mensaje' => $mensaje));
}
{{ Form::input('text', 'name', null, array('class' => 'form-control')) }}
por:
{{ Form::input('text', 'name', Input::old('name'), array('class' => 'form-control')) }}
<div class="bg-danger">{{ $errors->first('name') }}</div>
Lo mismo en todos los campos
$messages = array ( 'name.required' => 'El campo es requerido', 'name.regex' => 'Solo letras y espacios', 'name.min' => 'Mínimo de 3 caracteres', 'name.max' => 'Máximo de 80 caracteres', 'email.required' => 'El campo es requerido', 'email.email' => 'El formato de email es incorrecto', 'email.between' => 'Entre 30 y 80 caracteres', 'subject.required' => 'El campo es requerido', 'subject.regex' => 'Solo letras y números', 'subject.min' => 'Mínimo de 3 caracteres', 'subject.max' => 'Máximo de 80 caracteres', 'msg.required' => 'El campo es requerido', 'msg.between' => 'Entre 3 y 500 caracteres', );
y en la instancia de la clase Validator agregar lo siguiente:
$validator = Validator::make(Input::All(), $rules, $messages);
En este punto ya nuestro formulario debería funcionar correctamente pero para mejorarlo aún faltan un par de cosillas. Por un lado hacer el envío por Ajax, ya que representa una mejora en la interfaz del usuario y agregarle un captcha para evitar que los spiders que campean por la web se den gusto enviando nuestro formulario con basuras.
{{ Form::open(array
(
'action' => 'HomeController@contacto',
'method' => 'POST',
'role' => 'form',
'id' => 'form'
))
}}
<div class="bg-danger" id="_name">{{ $errors->first('name') }}</div>
{{ Form::input('button', null, 'Enviar', array('class' => 'btn btn-primary', 'id' => 'btn')) }}
$(function () {
function send_ajax()
{
$.ajax({
url: 'contacto',
type: 'POST',
data: $("#form").serialize(),
success: function(datos)
{
$("#_email, #_name, #_subject, #_msg").text('');
if (datos.success == false)
{
$.each(datos.errors, function(index, value)
{
$("#_"+index).text(value);
});
}
else
{
document.getElementById('form').reset();
$("#mensaje").text('Mensaje enviado con éxito');
}
}
});
}
$("#btn").on("click", function()
{
send_ajax();
});
});
En el div donde se muestra el mensaje de enviado agregarle el siguiente id:
<div id="mensaje" class="bg-info">{{$mensaje}}</div>
Que es donde se va a pintar el mensaje de enviado.
if (Request::ajax())
{
return Response::json
([
'success' => false,
'errors' => $validator->getMessageBag()->toArray()
]);
}
else
{
return Redirect::back()->withInput()->withErrors($validator);
}
Incluir un captcha de google
"greggilbert/recaptcha": "dev-master"
composer composer update --dev
A continuación:
'Greggilbert\Recaptcha\RecaptchaServiceProvider'
Vamos nuevamente al terminal y ejecutamos
php artisan config:publish greggilbert/recaptcha
Abrimos el fichero app/config/packages/greggilbert/recaptcha/config.php y veremos que necesitamos incluir dos claves, una publica y otra privada. Para ellos vamos a Google, damos click en GetRecaptcha, nos registramos, agregamos nuestro entorno local en la url, si estamos trabajando sobre localhost o 127.0.0.1 nos sirve cualquier sitio nuestro. Yo tuve que poner mi virtualhost para que me funcionara. Una vez hecho esto nos da nuestras claves publicas y privadas para agregarlas al config.php del recaptcha.
"recaptcha" => 'The :attribute field is not correct.',
{{ Form::captcha() }}
<div class="bg-danger" id="_recaptcha_response_field">{{ $errors->first('recaptcha_response_field') }}</div>
En el script del cabezal agregar el identificador en:
$("#_email, #_name, #_subject, #_msg, #_recaptcha_response_field").text('');
'recaptcha_response_field' => 'required|recaptcha',
'recaptcha_response_field.required' => 'El campo captcha es requerido', 'recaptcha_response_field.recaptcha' => 'Captcha incorrecto',
Para ir terminando esta interminable entrada voy a dejar los códigos completos de la vista y del controlador:
Vista:
<div id="mensaje" class="bg-info">{{$mensaje}}</div>
{{ Form::open(array
(
'action' => 'HomeController@contacto',
'method' => 'POST',
'role' => 'form',
'id' => 'form'
))
}}
<div class="form-group">
{{ Form::label('name', 'Nombre:') }}
{{ Form::input('text', 'name', Input::old('name'), array('class' => 'form-control')) }}
<div class="bg-danger" id="_name">{{ $errors->first('name') }}</div>
</div>
<div class="form-group">
{{ Form::label('email', 'Email:') }}
{{ Form::input('email', 'email', Input::old('email'), array('class' => 'form-control')) }}
<div class="bg-danger" id="_email">{{ $errors->first('email') }}</div>
</div>
<div class="form-group">
{{ Form::label('subject', 'Asunto:') }}
{{ Form::input('text', 'subject', Input::old('subject'), array('class' => 'form-control')) }}
<div class="bg-danger" id="_subject">{{ $errors->first('subject') }}</div>
</div>
<div class="form-group">
{{ Form::label('msg', 'Mensaje:') }}
{{ Form::textarea('msg', Input::old('msg'), array('class' => 'form-control')) }}
<div class="bg-danger" id="_msg">{{ $errors->first('msg') }}</div>
</div>
{{ Form::captcha() }}
<div class="bg-danger" id="_recaptcha_response_field">{{ $errors->first('recaptcha_response_field') }}</div>
{{ Form::input('hidden', 'contacto') }}
{{ Form::input('button', null, 'Enviar', array('class' => 'btn btn-primary', 'id' => 'btn')) }}
{{ Form::close() }}
Script JS de la vista:
$(function () {
function send_ajax()
{
$.ajax({
url: 'contacto',
type: 'POST',
data: $("#form").serialize(),
success: function(datos)
{
$("#_email, #_name, #_subject, #_msg, #_recaptcha_response_field").text('');
if (datos.success == false)
{
$.each(datos.errors, function(index, value)
{
$("#_"+index).text(value);
});
}
else
{
document.getElementById('form').reset();
$("#mensaje").text('Mensaje enviado con éxito');
}
}
});
}
$("#btn").on("click", function()
{
send_ajax();
});
});
Controlador:
public function contacto()
{
$mensaje = null;
if (isset($_POST['contacto'])) /* Campo oculto contacto */
{
$rules = array
(
'name' => 'required|regex:/^[a-zA-Z\s]*$/|min:3|max:80',
'email' => 'required|email|between:3,80',
'subject' => 'required|regex:/^[a-zA-Z\s0-9]+$/|min:3|max:80',
'msg' => 'required|between:3,500',
'recaptcha_response_field' => 'required|recaptcha',
);
$messages = array
(
'name.required' => 'El campo es requerido',
'name.regex' => 'Solo letras y espacios',
'name.min' => 'Mínimo de 3 caracteres',
'name.max' => 'Máximo de 80 caracteres',
'email.required' => 'El campo es requerido',
'email.email' => 'El formato de email es incorrecto',
'email.between' => 'Entre 30 y 80 caracteres',
'subject.required' => 'El campo es requerido',
'subject.regex' => 'Solo letras y números',
'subject.min' => 'Mínimo de 3 caracteres',
'subject.max' => 'Máximo de 80 caracteres',
'msg.required' => 'El campo es requerido',
'msg.between' => 'Entre 3 y 500 caracteres',
'recaptcha_response_field.required' => 'El campo captcha es requerido',
'recaptcha_response_field.recaptcha' => 'Captcha incorrecto',
);
$validator = Validator::make(Input::All(), $rules, $messages);
if ($validator->passes())
{
$data = array
(
'name' => Input::get('name'),
'email' => Input::get('email'),
'subject' => Input::get('subject'),
'msg' => Input::get('msg')
);
$fromEmail = '[email protected]';
$fromName = 'Nombre';
Mail::send('emails.contacto', $data, function($message) use ($fromName, $fromEmail)
{
$message->to($fromEmail, $fromName);
$message->from($fromEmail, $fromName);
$message->subject('Nuevo mensaje de contacto');
});
$mensaje = 'Mensaje enviado con éxito';
}
else
{
if (Request::ajax())
{
return Response::json
([
'success' => false,
'errors' => $validator->getMessageBag()->toArray()
]);
}
else
{
return Redirect::back()->withInput()->withErrors($validator);
}
}
}
return View::make('HomeController.contacto', array('mensaje' => $mensaje));
}
Si tenéis alguna duda de como funciona algo dentro del código os aconsejo que veáis los tutoriales, ahí todo esta explicado al detalle.
The post Enviar emails con Laravel first appeared on Escael Marrero.]]>Exceptuando la 3 y la 4, todas las tenía ya instaladas. Por lo tanto voy a explicar esas dos. Quiero aclarar que los pasos que doy son los que a mi me funcionaron, lo que significa que a otras personas lo hayan solucionado por otra vía.
Para instalar MCrypt:
Para instalar cURL:
Con esto ya tenemos listo el servidor para configurar el virtual host.
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName example.com
ServerAlias example.com
DocumentRoot /var/www/html/example.com
<Directory /var/www/html/example.com>
AllowOverride All
Require all granted
Order allow,deny
Allow from all
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Por último para instalar OctoberCms necesitáis composer, los pasos para instalarlo son los siguientes:
Una vez hecho esto ya estamos listos para instalar OctoberCms:
Los permisos para ejecutar correctamente OctoberCms son los siguientes:
sudo chown -R root:www-data app/storage sudo chown -R root:www-data themes sudo chown -R root:www-data uploads sudo chmod -R 775 app/storage/ sudo chmod -R 775 themes sudo chmod -R 775 uploads
En estas url puede encontrar más información sobre todo este proceso:
The post Instalar OctoberCms en Ubuntu first appeared on Escael Marrero.]]>Siguiendo el consejo de mi buen amigo Roger voy a empezar a crear una serie de post relacionados con todo el proceso que cualquier desarrollador web se tiene que enfrentar en su día a día.
Como se titula esta entrada vamos a configurar PhpMyadmin, proceso bastante sencillo.
A continuación se siguen los pasos que se indican: 

Y eso es todo, espero os sirva.
The post Instalar y configurar PhpMyAdmin en Ubuntu first appeared on Escael Marrero.]]>El último proyecto que casi concluyo es Artesabaking, una web de una tienda de dulces estadounidense, digo casi porque aún quedan algunos ajustes por realizar, detalles sobre todo y algunas vistas llevarlas a RWD. He empleado «SASS 3.2.9», «compass 0.12.2» y el plugin «compass-960-plugin 0.10.4». Cuando comencé a preparar las condiciones para la maquetación pensé hacerlo utilizando Susy pero me percaté que había una nueva versión de SASS y otra de Susy, y al actualizarlas empezaron los problemas. Según la documentación de Susy cuando vas a comenzar un proyecto debes tirar la siguiente línea:
compass create –using susy <project name>
en la misma utilizando compass creas un proyecto con Susy, pero eso me dio error. No era posible crear un proyecto porque Susy 2 depende de SASS 3.3.0 y la versión que tenía de Compass (para compilar) era la 0.12.2. Pues sencillo actualizaba compass y listo. En ese momento la versión estable de compass es la que he nombrado anteriormente, pero los desarrolladores tienen una versión release (1.0.0.alpha.19) que instalando mediante el siguiente comando funcionaría:
gem install compass –pre
pero no amigos, eso me dio otro error, esta vez de Ruby. Para no hacer muy extensiva esta explicación decidí utilizar compass-960-plugin como grid para maquetar y volver a las versiones anteriores de SASS. Un tiempo después logre solucionar el problema de Ruby que no era otro que actualizar a una versión superior, ahora no recuerdo los pasos pero no fueron muy complejos. En fin que instale la versión alpha de compass y de ahí en adelante todo fue de maravillas. El problema que restaba solucionar era como terminar este proyecto, del cual aún no he dicho nada, con las versiones que lo comencé. Para solucionar este detalle vino en mi ayuda Bundler, el cual permite instalar las versiones de diferentes gemas de ruby para cada proyecto en particular. Un ejemplo sería:
source "https://rubygems.org" gem 'sass', "3.2.9" gem 'compass', "0.12.2" gem 'compass-960-plugin', '0.10.4'
eso en un fichero de configuración llamado Gemfile y ubicado en la raíz del proyecto, descarga e instala las versiones que va a necesitar el mismo. Esta practica es muy recomendable sobre todo cuando se trabaja en muchos proyectos que se van quedando «atrasados» y en algún instante es necesario tocarlos.
Bueno y que decir sobre Artesabaking, aparte de ser un diseño muy complejo y bonito fruto de la imaginación de un gran diseñador como es Iván Santamaría, el cual me puso a pensar en más de una ocasión en como solucionar los retos que me planteaba. Puro HTML5 con una marcado semántico aplicando la metodología BEM. Y por último gracias a la magia de SASS y compass pude darle salida a este bello trabajo y con un código que considero de muy buena calidad. Todo versionado con Git para tener un respaldo en todo momento de las modificaciones y estados de códigos.
He utilizado varias de las funcionalidades de SASS como por ejemplo el uso de EACH:
$i: 1;
@each $icon in gift, pizza, clock {
&:nth-child(#{$i}):before {
@include sprite-background("sprites/#{$icon}.png", 90px, 80px);
background-position: center;
background-color: #8f69ec;
}
$i: $i + 1;
}
eso lo utilice en la página de services para pintar el módulo que veis abajo a la izquierda.
Me he extendido hablando un poco sobre los problemas que me encontré en este proyecto pero me siento bien porque al final logre solucionarlos y configurar el ordenador correctamente, además ya tengo un método para futuros trabajos. Si alguno de vosotros tiene problemas parecidos no dude en escribirme o dejar un comentario, estaré encantado de transmitirle mi experiencia.
The post Sobre el proyecto Artesabaking first appeared on Escael Marrero.]]>Como muchos conocéis Bootstrap esta desarrollado con Less y aunque este pre-procesador de css es muy bueno, para muchos entre ellos un servidor, echábamos de menos la posibilidad de jugar con este framework utilizando Sass, pues hoy este anhelo se ha materializado.
Por último y como curiosidad. En mi trabajo oficial, ese que vamos todas las mañanas con sueño después de pasar varias horas nocturnas haciendo proyectos y desarrollos propios, vengo desarrollando con Bootstrap hace unos meses, maldiciendo en muchas ocasiones las limitaciones que a mi entender tiene Less, y justo hoy, cuando termino el proyecto que me mantenía ocupado veo la noticia que os he dado arriba. Podrán imaginarse mi cara de sorpresa, el destino a veces te juega bromas pesadas. Pues nada, tendré que esperar unos meses cuando se decida pasar a una versión superior del proyecto mencionado para empezar disfrutar de Sass.
The post Bootstrap ¡al fin con Sass! first appeared on Escael Marrero.]]>Nada mejor para empezar que un ejemplo de estructuras de control. Os expongo el modelo:
4 div a los cuales tenía que agregarles imagenes de fondo distintas, esas conocidas especificaciones de diseño que tanto nos obligan a pensar. Lo primero que hice fue crear las 4 imagenes siguiendo esta secuencia:
La solución a maquetar fue la siguiente:
Con SASS:
@for $i from 1 through 4 {
.info-#{$i} {
background-image: url('/images/info-#{$i}.png');
}
}
Con LESS:
@iterations: 4;
.loop (@i) when (@i > 0) {
.info-@{i} {
background-image: url('/images/info-@{i}.png');
}
.loop(@i - 1);
}
.loop (0){}
.loop (@iterations);
Como podrán observar es muy simple en ambos casos, cree una variable ($i) que representa la cantidad de elementos a repetir en este caso las 4 imagenes. Sass define en la primera línea de 1 a 4 y crea el correspondiente css sustituyendo la variable $i por el número en la imagen de fondo. Less hace algo parecido pero define el número en otra variable (@iterations) y va restando hasta que llega a 0 y para la ejecución.
En ambos casos es muy simple y como dije anteriormente dejo a su decisión cual resulta más eficiente y rápida.
The post Sass Vs Less first appeared on Escael Marrero.]]>Siempre he escuchado que esta muy mal repetir código dentro de un proyecto web, si ya hiciste algo debes procurar poder reutilizarlo en otras zonas pero sin el copiar y pegar clásico. Por lo tanto cuando estaba desarrollando el thema de este portfolio me di cuenta que precisamente estaba haciendo eso, repetir código por todos lados. Por ejemplo en una misma página tenia esta función de WP:
$args = array( 'posts_per_page'=> 5, 'post_parent' => 3, 'post_type' => 'page', ); query_posts( $args );
que se repetía en varios lugares con la única diferencia que en vez de 5 post por página tenía 10 o simplemente agregaba una línea más como esta por ejemplo:
'post__not_in' => array($post->ID)
Entonces me pregunte sino era posible crear una clase general con esa función y simplemente llamarla cada vez que quisiera. Vino en mi ayuda Jorge, un compañero de trabajo que es un crack y me dio la solución que es increíblemente simple: creas un fichero nuevo y lo nombras digamos _classQuery.php, creas la clase de la cual vas a extender de la siguiente manera:
class Pages {
public static function query($options=array()) {
$options += array(
'posts_per_page'=> 5,
'post_parent'=> 3,
'post_type' => 'page'
);
return query_posts($options);
}
}
Para usarla en nuestras páginas solo debemos llamarla de la siguiente manera:
Pages::query()
Y si queremos sobrescribir o crear un nuevo parámetro:
Pages::query(array(
'posts_per_page' => 1,
));
Esto es muy simple pero gracias a ello no solo ahorramos código sino que nuestra aplicación es mucho más efectiva y rápida.
The post Objetos en WordPress first appeared on Escael Marrero.]]>