Ruby on Rails

in Lithuania

Ieškai išskirtinės darbo vietos? Sieki darbą paversti įdomiu ir maloniu užsiėmimu?

Mes:
Programuojame Ruby (On Rails) ir ne tik;
Dirbame su pasaulinio lygio projektais;
Taikome "Agile" metodikas;
Dirbame 7 valandas per dieną;

Tu:
Nori dirbti entuziastų komandoje;
Mėgsti programuoti ir mokytis naujų dalykų;
Domiesi WEB technologijomis;
Sieki ne tik dirbti, bet ir užsidirbti;

Susidomėjai? Parašyk mums: info eta rubyonrails taškas lt

Published on 11/08/2008 at 16h40 by Saulius Grigaitis

Centostrano 0.1 - deprec 2 (deployment recipes for capistrano) port to CentOS released!

I’m happy to announce first official release of Centostranodeprec 2 (deployment recipes for capistrano) port to CentOS. Although it is beta release, I use it in production setting without issues, so it’s stable enough to start play with. By the way, original deprec 2 is still not released, so I port back updates from <a href=“http://deprec.org’>deprec 2 to ”https://blog.rubyonrails.lt/redmine/projects/show/centostrano">Centostrano offten.

Main intention is to keep deprec 2 and Centostrano behavior as close as possible. There are some minor differences between tasks, but at the final release recipes and tasks should be the same, except the two main differences in usage (because of technical conflicts):

  • cap task’s namespace is changed from “deprec” to “centos”, so instead of “cap deprec:rails:install_stack” one must use “cap centos:rails:install”
  • instead of “depify” binary one should use “centify”

Also, there are some other internal changes like install software from source with help of Checkinstall

Also, I’m thinking about single task, which with minimal interactive input would setup the server, instead of usage scenario described below. In general, the problem is that if one will not understand Centostrano / deprec 2 concept, then to complete some advanced deployment task using Centostrano / deprec 2 will be impossible. So one of the ways to introduce Centostrano / deprec 2 is to force user to use it as written below. So I provide some usage example, which describes how to install rails stack and deploy application step by step.

First of all install Centostrano gem

sudo gem install centostrano

You need one place from where you will make initial setups of new servers. Create it once, use many times for multiple servers.

$ mkdir -p ~/.centostrano/config
$ cd ~/.centostrano

If you already have ~/.caprc file (i.e it was generated with deprec ), you need manually add line “require ‘centostrano’”. Centify this directory now:

$ centify .

Value of HOSTS will be the same for this usage scenario, so let’s export it

$ export HOSTS=your_domain_name.com

Change root password

$ cap centos:users:passwd USER=root

Edit ~/.caprc, find the line “# ssh_options[:keys] = …”, uncomment it and setup correct path to your private key. Usually, it should look like ssh_options[:keys] = %w(/home/your_username/.ssh/id_rsa). If you don’t have private/public key pair, then issue command:

$ ssh-keygen -t rsa

Add new user, which be used for deployment. In this example user name will be “deploy_user”.

$ cap centos:users:add USER=root

  • executing `centos:users:add’
    Enter userid for new user |root|
    deploy_user
    Should this be an admin account? |no|
    yes
    Enter new password for deploy_user

Setup keys, so you will login into server using private key instead of password (use deploy_user’s password from now)

$ cap centos:ssh:setup_keys USER=deploy_user

  • executing `centos:users:add’
    Enter userid for new user |root|
    deploy_user
    Should this be an admin account? |no|
    yes
    Enter new password for deploy_user

Generate SSH daemon configuration files

$ cap centos:ssh:config_gen

Configure SSH daemon

$ cap centos:ssh:config USER=deploy_user

Enter into your project directory

$ cd /path/to/your/rails_project

Centify it (this generates necessary configuration files)

$ centify .

Set production database name and password in config/database.yml
Set :application and :domain names in config/deploy.rb. If deployment user name is not the same as your local user name, then set deployment :user name too. The beginning of config/deploy.rb should look like:

require ‘centostrano’

set :user, “deploy_user”
set :application, “demoapp”
set :domain, “domain.com”
set :repository, “ssh://[email protected]#{domain}/#{application}.git”

set :scm, :git

Leave the default :repository and :scm settings if you would like to setup Git repository one the server and manage it with Gitosis (see below). If you need something else, then adjust :repository and :scm.

Install rails stack (MySQL, Nginx, Ruby, RubyGems, …). It will take a while.

$ cap centos:rails:install_stack

Create database ( DB and DB user will be created according to production settings in config/database.yml file). Issue command depending on which database you use:

$ cap centos:mysql:install
$ cap centos:mysql:setup_db
or
$ cap centos:postgresql:install
$ cap centos:postgresql:create_db

If you would like to setup Git repository and manage it with Gitosis, then issue those two commands. Last one will initialize git repository in local project directory and commit all content except ignored files, then will setup server keys, so server itself will be able to clone git repository at deployment, then will configure gitosis and push local Git repository to repository at server. Also, there will be config/gitosis/gitosis-admin.git directory containing Gitosis configuration. You can use it to add new user, create new repositories and manage permissions, check Gitosis documentation!

$ cap centos:gitosis:install
$ cap centos:gitosis:setup_repo

Do initial rails project setup on server:

$ cap deploy:setup

And now let’s deploy and run pending migrations:

$ cap deploy:migrations

And finally let’s start nginx:

$ cap centos:nginx:start

Point browser to your domain and enjoy!

That was hardest part. I’ll write few more words about the future usage. Let’s assume that we added more feature in our application and we would like to deploy new version.

If you haven’t commited changes already then this is the time to do it and push to server:

$ git add .
$ git commit -m “Added feature X”
$ git push

And finally deploy without or with running pending migrations:

$ cap deploy
or
$ cap deploy:migrations

I know, this may look not “so easy”, but once you will understand it, deployment becomes pleasure!

Published on 15/07/2008 at 11h32 by Saulius Grigaitis

Screencast #2. Darome rounded corners mygtukus

Ši karta papasakosiu vieną greitą būdą kaip galima sukurti rounded corners mygtuką, kuris vienodai veiks Firefox, Opera, Safari, IE6 ir IE7 naršyklėse.

Paspausk Mane!

O gal Jūs žinote koki kitą gera būda, būtų labai įdomų sužinoti. Geriausio sprendimo autorius gaus šokoladinį kiškį ;) !

Įdomaus ir naudingo žiūrėjimo: rounded_corners

Published on 27/04/2008 at 22h31 by Fiodor Vereščiaka Tags

Screencast #1. Rails 2.1 naujovė - "named scopes"

Su džiaugsmu pristatau pirmąjį screencast’ą, kurį sukūrė Fiodor Vereščiaka. Fiodor pasakoja apie vieną iš būsimų Rails 2.1 naujovių – named scopes. Tai išties patogus funkcionalumas, kuris iki šiol buvo atskirame įskiepyje HasFinder.

class User < ActiveRecord::Base
named_scope :active, :conditions => { :active => true }
named_scope :male, :conditions => { :gender => ‘m’ }
named_scope :female, :conditions => { :gender => ‘f’ }
end

Tada galime patogiai išrinkti:

User.active.female

Įdomaus ir naudingo žiūrėjimo: named_scopes

Published on 16/04/2008 at 22h28 by Saulius Grigaitis Tags

Forumas ir Screencast'ai !

Dauguma šio tinklapio lankytojų jau pastebėjo atsiradusią nuorodą į forumą. Forumas buvo pristatytas RubyConfLT 1.2008 konferencijos metu, o nuo šiol jis oficialiai atidarytas, tad visi galite diskuoti su Ruby susijusiomis temomis. Be to, atidarome ir screencast’ų skiltį, kurioje talpinsime mūsų sukurtus ir įrašytus screencast’us Ruby tematika. Pirmąjį screencast’ą sukūrė Fiodor Vereščiaka apie vieną iš naujovių Ruby on Rails 2.1 versijos karkase – named scopes. Įdomaus ir naudingo žiūrėjimo!

Published on 16/04/2008 at 20h57 by Saulius Grigaitis

RubyConfLT 1.2008 įspūdžiai

Buvo išties “fun” :). Buvo džiugu matyti nemažai entuziastų, kurie aktyviai dalyvavo visą konferencijos laiką, nors pranešimai truko net iki 21-os valandos. Nors tai RubyConf, konferencijos metu daugiausia kalbėta ne vien apie Ruby, bet ir apie Rails, Merb bei Chuck Noriss :). Visą tai artimiausiu metu galėsite pamatyti ir konferencijos vaizdo įrašuose, kurie bus patalpinti KTU distancinių mokymų centro tinklapyje. Dėkui Artūrui už konferencijos organizavimą, pranešėjams, publikai, KTU DMC darbuotojams ir visiems kitiems, prisidėjusiems prie šios konferencijos. Tikiuosi, netruks ilgai iki sekančio susitikimo.

Konferencijos akimirkos:;




RubyConfLT 1.2008

Ir pranešimų skaidrės:

  • Artūras Šlajus:
  • Eimantas Vaičiūnas:
  • Saulius Grigaitis:
  • Fiodor Vereščiaka:
  • Laurynas Liutkus:
  • Published on 14/04/2008 at 21h13 by Saulius Grigaitis

    RubyConfLT 1.2008

    Daugelyje šalių rengiamos “RubyConf” konferencijos susilaukė didelio susidomėjimo tiek profesionalių “Ruby” programuotojų, tiek pradedančiųjų tarpe.

    KTU rengiamo kasmetinio “InfoShow” festivalio metu pirmą kartą vyks “RubyConfLT” konferencija, kuri taip pat išlaikys “RubyConf” konferencijų koncepsiją, bet bus daugiau orientuota į pradedančiuosius “Ruby” ir “Ruby on Rails” programuotojus. Konferencijos metu bus aptariamos tiek ekspertams, tiek ir pradedantiesiems aktualios temos:

    • Artūras ‘arturaz’ Šlajus

      • How I fell in love (and started abusing) Ruby
      • Rails? Čia tas naujas serialas iš Meksikos?
      • (Į)skiepai nuo galvasopio
      • Pažintis su CRUD-oriented architektūros kūrimu
      • Rails profilingas ir optimizavimas
    • Eimantas ‘enc’ Vaičiūnas

      • UJS: nepiktas HTML tiuningas su unobtrusive Javascript
    • Saulius Grigaitis

      • Testavimas su RSpec/Selenium/Watir
      • Saugus seksas su Rails
      • Rails “deploy’inimas” lengvai
    • Fiodor Vereščiaka

      • MERB: WEB’as su Ruby tai ne tik Rails (+ data_mapper)

    Susitiksime RubyConfLT 1.2008 !

    Daugiau informacijos: arturaz.net/blog/rubyconflt-12008/

    Published on 29/03/2008 at 17h42 by Saulius Grigaitis

    Pavasaris!

    Pagaliau išsikraustėm iš hostingo, kuriame negana to, kad downtime’as buvo didesnis už uptime’ą, dar ir neaiškiomis aplinkybėmis dingo duomenys ne tik iš duomenų bazės, bet ir iš atsarginės kopijos. Laimei, straipsnius pavyko atkurti iš kešuotos HTML versijos, o straipsnių komentarai dar laukia savo eilės. Taip pat atnaujinome ir pačią blog’inimo sistemą bei apvilkome pavasarinį rūbą.
    Šiek tiek keičiasi ir pačio tinklapio www.rubyonrails.lt koncepsija, daugiau dėmesio skirsime Lietuvos Ruby ir Rails bendruomenei. Straipsniai, kurie aktualūs tik Lietuvos Ruby ir Rails bendruomenei, bus skelbiami lietuvių kalba, o plačiajai auditorijai aktualūs straipsniai dažniausiai bus skelbiami anglų kalba. Artimiausiu metu startuos forumas, skirtas diskusijoms Ruby ir Rails tematika, tad galima bus diskutuoti ir ieškoti problemų sprendimų įvairiomis temomis. Visi kas turite pasiūlymų ar patarimų tiek blog’o, tiek būsimo forumo klausimais, ar norite prisidėti prie šios bendruomenės, parašykite apie tai komentaruose!

    Published on 29/03/2008 at 16h58 by Saulius Grigaitis

    OpenWFEru: Workflow and Business Process Machine engine(Introduction)

    Nowadays Rails applications are RESTful, so in most cases it avoids any complex workflow(except minor things like account registration). But sometimes workflow becomes important element in application, then the quick way is to use status field, which works well at simple situations. For example Invoice model has status field, which is one of ["new", "pending", "paid", "canceled"] or so. The problem here is that workflow is hardcoded in code. So invoices with status "new" appears in new invoices page, because that action use something like Invoice.find(:all, :conditions => {:status => "new"}), and the same situation is with other pages. Here workflow is hardcoded. One day business process changes and new status of invoice is added, then programmer needs to analyze the app's code, remember the workflow implementation and change a lot of code in tests and models/views/controllers... Usually this is non-effective and painful.

    Other issue - business analyst or customer provides the workflow schematics, then programmers use those. Constantly schematics or implementation of that worklow is changed, but usually synchronization between schematics and implementation is lost, because people make mistakes or are too lazy :).

    Is there any solution to easer control of workflow and avoid mentioned issues? Yes, serious people call it orchestration:). The main idea is to get workflow defined in some external resource, like XML file. Then even business analyst can easily change the workflow with help of IDE, which allows to edit the workflow files(for example jBPM Process Designer for JBoss jBPM). Workflow and business process machine engine OpenWFE has been ported to Ruby, so Ruby folks can use OpenWFEru. Unfortunately, I couldn't find any usable process designer for this engine, but usually it is not painful to write process definition by hand in XML or Ruby.

    There are few things that one must understand before using OpenWFEru: business processes, participants and workitems(or tasks, or tokens, or other name for the same thing).Business processes are defined via trees of expressions named process definitions. Participants are those workers, which starts to do something when get workitem. Participants can be mailer, so it sends email once it gets workitem, or web service client, so it communicates with server via API once it gets workitem, or block of Ruby code, so this code will be executed once it gets workitem, or any other allowed participant. And the most important Gotcha is workitem. Workitem itself doesn't contain any task, it's only token. But one can associate variables with this workitem, so one can pass important data from one participant to other, like the ":translator" participant pass the "translation" to ":reporter" participant in the example. So workitem is created and passed to first participant once business process is initiated, this workitem is passed to next participant according to process definition once first participant completes his task. In same way workitem is passed thought entire process and participants knows when to do their job.

    Here is the simple example, which is based on openwferu.rb. There is very simple workflow: sequence of three participants. First one is you, your task is to enter text in english. Once you complete it, the workitem with the "source_text" you entered will be passed to second participant - translator. Translator here is Ruby block again, which calls google translation service(thanks to rbabel). Once text is translated, it is attached to workitem, and workitem is passed to third participant - reporter. This is Ruby block again, it only prints the source text and translated text. As you see, it is very easy to change the translator. What you need to do, is only change the block of current translator, or register new participant and replace old participant's name in process definition with new one. Also, it is very easy to analyze and change workflow, you only need to be familar with XML(actually, workflow can be defined in Ruby too). And final thing is that participants are loosely coupled, the only one thing is the attached variables to workitem. So participants are like small units, which has input and output, so it's very easy to make various combinations of those units in complex sequences.

    #first install gems
    $ sudo gem install openwferu
    $ sudo gem install rbabel

    then execute this Ruby script

    require 'rubygems' require 'openwfe/def' require 'openwfe/workitem' require 'openwfe/engine/engine' require 'openwfe/participants/enoparticipants' require 'rbabel' # instantiating an engine engine = OpenWFE::Engine.new # adding some participants engine.register_participant :you do |workitem| puts "=========================================" puts "Task for You" puts "Please, enter text in english" workitem.source_text = gets puts "=========================================" end engine.register_participant :translator do |workitem| puts "==============Task for translator========" puts "translating text..." workitem.translation = workitem.source_text.translate(:en, :fr) puts "translated!" puts "=========================================" end engine.register_participant :reporter do |workitem| puts "==============Task for reporter==========" puts "Text in english:\n#{workitem.source_text}\ntranslated to text in french: \n#{workitem.translation}" puts "=========================================" end # a process definition definition = ' ' # launching the process li = OpenWFE::LaunchItem.new(definition) li.initial_comment = "please give your impressions about http://ruby-lang.org" fei = engine.launch li # 'fei' means FlowExpressionId, the fei returned here is the # identifier for the root expression of the newly launched process puts "started process '#{fei.workflow_instance_id}'" engine.wait_for fei

     

    Yes, this example is very simple, but that was my way to show you this concept. If you understand the advantage of workflow and business process engine, then you can imagine how easy it is to implement complex workflow in dynamic enterprise, which is usually very painful without such engine.

    Published on 24/01/2008 at 22h37 by Saulius Grigaitis

    (R)Spec for JavaScript

    With the new year comes a new hope for You, JavaScript developer! Have you ever wanted to test whether your function calls AJAX properly? Or some Effect? Now you can. Just set up JsUnit, download spec.js, include it into your test html and try this:

    function testAjax() {
      expect_create(Ajax.Request).with_params(['/my/url', {asynchronous: true, evalScripts: true, parameters: {a: 'b'}}]);
    
      new Ajax.Request('/my/url', {asynchronous: true, evalScripts: true, parameters: {a: 'b'}});
    }

    While this snippet looks quite nice (except for square brackets - I haven't decided whether to remove them or not), it still needs something. Setup and teardown - JSUnit runs setUp before and tearDown after every test.

    function setUp() {
      RSpec.setUp();
    }
    
    function tearDown() {
      RSpec.tearDown();
    }

    What was actually tested in the first snippet, was class creation with specified parameters. But what if you have an object with some very complex method and only need to be sure it is called. You don't care what will it do. Let's go!

    // let's create a class
    var Ship = Class.create({
      shoot = function(target) {
        alert('shooting specified target');
        new Ajax.Request(...);
      }
    });
    
    // add testing methods for instances of Ship
    Ship.addMethods(RSpecMethods);
    
    // now our test
    function testAttack() {
      ship = new Ship();
      ship.should_receive('shoot').with_params(['Deathstar']);
    
      //replace following line with simulated click event or something similar
      ship.shoot('Deathstar');
    }
    Got crazy? Don't specify any params, but specify how many times to expect:
    ship.should_receive('shoot').exactly(5);
    
    ship.shoot('Deathstar');
    ship.shoot('Norad II');
    ship.shoot('Moon');
    ship.shoot('Deathstar');
    ship.shoot('params', 'count', 'is', {not: 'checked'});

    Published on 01/01/2008 at 22h39 by Laurynas Liutkus

    Powered by Publify Theme Frederic de Villamil | Photo Glenn