Page 121 of 165

Ubuntu 10.10 Ruby, RVM i Rails – instalacja Ruby version managera

W związku ze zmianą twardziela w laptopie, postanowiłem dokonać świeżej instalacji Ubuntu 10.10.

Problemem było to, że mój własny tutorial dot. instalacji Rubiego, przestał działać. Tzn. sam tutorial działa, niestety nie działa już metoda. Odpalając aplikacje pojawiał mi się dość dziwny segmentation fault. Na moje szczęście, instalacja Rubiego w opisany poniżej sposób, działa bezbłędnie.

    sudo apt-get install ruby-full
    wget production.cf.rubygems.org/rubygems/rubygems-1.3.7.tgz
    tar -xvf rubygems-1.3.7.tgz
    cd rubygems-1.3.7/
    sudo ruby setup.rb
    sudo ln -s /usr/bin/gem1.8 /usr/bin/gem

Mamy już Rubiego w wersji 1.8.7 (patchvelev 299), przydałby się jeszcze RVM i Railsy.

Z tym też nie jest (aż tak) trudno. Najpierw musimy zainstalować sobie curl'a oraz gita:

sudo apt-get install curl git-core
# Parę bibliotek
sudo apt-get install libmysqlclient-dev libmysql-ruby
sudo apt-get install libsqlite3-dev build-essential

A następnie uruchamiamy poniższy kod, instalując tym sposobem RVMa:

# Nie jestem pewien czy ta linijka jest konieczna, ale dla pewności daję ;)
sudo gem install rvm
bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)

Mając zainstalowanego RVMa musimy jescze wydedytować plik .bashrc. Odnajdujemy taką linijkę (będzie gdzieś w pierwszych 20-30 linijkach):

[ -z "$PS1" ] && return

i zamieniamy na:

if [[ -n "$PS1" ]]; then

Na końcu pliku .bashrc dołączamy jeszcze to:

if [[ -s $HOME/.rvm/scripts/rvm ]] ; then source $HOME/.rvm/scripts/rvm ; fi

fi

Tyle. Zamykamy sesję konsoli i otwieramy nową (żeby wczytało na nowo .bashrc). Wpisując komendę:

rvm notes

Dostaniemy info dot. tego jakie biblioteki powinniśmy zainstalować, zależnie od tego jakiej wersji Rubiego będziemy używać:

# For RVM
  rvm: bash curl git

# For JRuby (if you wish to use it) you will need:
  jruby: aptitude install curl sun-java6-bin sun-java6-jre sun-java6-jdk

# For Ruby (MRI & ree)  you should install the following OS dependencies:
  ruby: aptitude install build-essential bison openssl libreadline6 
  libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev 
  libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev 
  libxslt-dev autoconf

# In addition to ruby: dependencies,
  ruby-head: subversion

# For IronRuby (if you wish to use it) you will need:
  ironruby: aptitude install curl mono-2.0-devel

My chcemy Rubiego 1.9.2-p0, więc robimy co tam trzeba :) a następnie:

rvm install 1.9.2-p0
# Tutaj chwilę poczekamy...
rvm use 1.9.2-p0 --default

I już mamy ustawionego Rubiego 1.9.2-p0 jako domyślną wersję w systemie.

Uwaga - niektórzy mają problem z uprawnieniami!
Dla pewności (zapobiegawczo) radzimy odpalić przed instalacją raisów w RVM taką komendę:

sudo mkdir ~/.gem/specs sudo chmod 777 ~/.gem/specs

Instalujemy sobie Railsy:

gem install rails

i cieszymy się sprawnie działającym środowiskiem

Rails3, Paperclip i usuwanie oryginalnych obrazów (plików)

Zaktualizowałem parę dni temu Paperclipa i oczywiście nie obyło się bez garści dziwnych problemów. Jednak nie to mnie najbardziej wkur zdenerwowało. W obecnej wersji zmieniono sposób obsługi sprawdzania rozmiaru plików (no chyba że to tak działa tylko u mnie...).

Załóżmy że mam limit rozmiaru ustawiony na 2MB. Przesyłam zdjęcie mające 5MB, ulega ono przekształceniu przez ImageMagicka i ma 1,5MB. Takie zdjęcie nie powinno być dopuszczone (limit pliku 2MB), jednak jest. Aby nie zapisywać oryginalnego pliku, maskowałem go w taki sposób:

  has_attached_file :avatar, :styles => {
                    :mini => "25x25\#",
                    :small => "50x50\#",
                    :medium => "75x75\#",
                    :big => "100x100\#",
                    :original => "200x200>"},

Ustawienie wartości :original powodowało nadpisanie pierwotnego pliku. Okazuje się jednak, że w obecnej wersji Paperclipa, ocena rozmiaru następuje na podstawie originala, po nadpisaniu rozmiaru. Przez takie zachowanie, musiałem opracować nową metodę kasowania pliku oryginalnego.

Postanowiłem wykorzystać do tego PostProcessor, jednak to podejście nie zakończyło się sukcesem. Wykorzystanie Observera do kasowania również nie działa. Observer uruchamia się jeszcze przed zapisaniem plików na dysk, więc nie mogą zostać usunięte.

Problem rozwiązałem stosując Observer wraz z Cronem i przeznaczonym do tego odpowiednim modelem. Utworzyłem prosty model do przechowywania ścieżki do pliku oraz timestampy. Dodałem do niego dwie metody. Jedna odpowiada za wykasowanie pojedyńczego pliku (którego odzwierciedleniem w bazie jest instancja klasy UselessFile) oraz drugą która ma wykasować wszystkie pliki. Należy przy tym pamiętać że należy kasować pliki których obiekt ma minimum parę sekund (żeby nie usunąć wpisu z bazy, pozostawiając plik). Ja ustawiłem domyślnie 5 minut (tak dla pewności).

Model UselessFile:

 
require 'fileutils'

# Musimy "jakoś" kasować oryginalne pliki robione przez paperclipa
# postprocessorem jakoś nie szło, to samo w callbackach, z racji tego powstał
# ten model. Zbiera on listę oryginalnych plików, by potem z crona je usuwac
class UselessFile < ActiveRecord::Base

  def destroy
    File.delete(self.path) if self.path && File.exists?(self.path)
    super
  end

  def self.delete_all
    self.sweep
  end

  def self.sweep
    time = 5.minutes.ago
    self.where("created_at < '#{time.to_s(:db)}' OR updated_at < '#{time.to_s(:db)}'").each { |el|
      el.destroy
    }
  end
end

Działanie jest bardzo proste, z tego względu podaruję sobie tłumaczenie ;)

Observer:

class ProfileObserver < ActiveRecord::Observer
  def after_save(profile)
    return unless profile.avatar?
    path = profile.avatar.url(:original).split('?').first
    path = File.join(Rails.root, 'public',path)
    UselessFile.create(:path => path)
  end
end

Tutaj najpierw sprawdzamy czy model ma avatar (plik) i jeśli tak to "wrzucamy" do bazy jego adres, tak aby w cronie usunąć odpowiadający mu plik.

Cron:

  desc "Czyszczenie bezużytecznych plików zgromadzonych w UselessFile"
  task :useless_files_sweeper => :environment do
    UselessFile.sweep
  end

Tyle :) Nie jest to może rozwiązanie najbardziej optymalne ale działa. Dodatkowo sam model UselessFile i zasadę jego działania możemy wykorzystać nie tylko z Paperclipem.

Copyright © 2024 Closer to Code

Theme by Anders NorenUp ↑