Typo의 부활. +_+
한 동안 Typo에 문제가 있었다.
관리자 페이지에서 Content 탭에 들어갈 때 에러가 나는 문제 였는데, 갑자기 한번 고쳐보고 싶어서 손을 대 봤다.
문제는 Postgresql과 MySQL의 차이였다. Typo의 Content 탭에서는 published_at 컬럼을 기반으로 글을 보여주는 코드가 있는데, 여기서 Timestamp without Timezone 형인 published_at과 integer 형인 0의 비교가 있어서 문제가 생겼던 것!
app/models/content.rb #104
def find_by_pub/lished_at(column_name = :publication)
from_where = "FROM #{self.table_name} WHERE #{column_name} > 0 AND type='#{self.name}'"
end그냥 남들 쓰듯 MySQL을 썼으면 문제가 안됐을 일이지만… 뭐.. 어쩌랴. 내가 반골인걸. ㅎㅎ
어쨌건 살아난 기념으로 포스팅 하나!
P.S: 문제 해결은 다음과 같이 했다.
app/models/content.rb #104
def find_by_published_at(column_name = :publication)
from_where = "FROM #{self.table_name} WHERE #{column_name} > TO_TIMESTAMP(0) AND type='#{self.name}'"
endCapistrano deploy file for Thin & NginX & SCM Git
지금 프로젝트에서 사용중인 Capistrano Deploy File.
잡다한 작업은 plugin에 맡기니 일이 확실히 줄어든다. Capistrano Bells Plugin 사용.
# pty setting
default_run_options[:pty] = true
# General configuration settiongs, required for all recipes!
set :application, "#{application_name}"
role :web, "#{webserver_domain}"
role :app, "#{appserver_domain}"
role :db, "#{dbserver_domain}", :primary => true
# User Setting
set :user, "production"
# Deployment Settings
set :repository, "#{repository_location}"
set :scm, :git
set :deploy_to, "#{deploy_location}"
set :deploy_via, :remote_cache
set :config_files, %w()
# Change this to :thin if you want to use Thin instead.
set :app_server, :thin
# =============================================================
# Application Server Settings (Thin or Mongrel)
# =============================================================
set :thin_servers, 3
set :thin_port, 7007
set :thin_environment, 'production'
set :thin_address, '127.0.0.1'
set :thin_conf, "#{shared_path}/config/thin.yml"
# =============================================================
# Nginx Settings
# =============================================================
set :nginx_sites_available, "/etc/nginx/sites-available"
set :nginx_sites_enabled, "/etc/nginx/sites-enabled"
after "deploy:update_code", "db:symlink"
after "db:symlink", "attachment:symlink"
namespace :db do
desc "Make symlink for database yaml"
task :symlink do
run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
end
end
namespace :attachment do
desc "Make symlink for attachment directory"
task :symlink do
run "ln -nfs #{shared_path}/attachments/article_images #{release_path}/public/images/article_images"
end
endRails with NginX File Upload
Swfupload를 이용한 파일 업로드 시에 생겼던 문제.
사실 알고보면 단순한 문제인데, 원인 파악을 잘못해서 고생했었다.
413 에러가 계속 나는 문제였는데, 이 413에러를 Swfupload 쪽에서 보내는 걸로 착각한것. 서버에는 호출됐다는 로그가 안남고, swfupload 쪽에서는 계속 413에러를 내고, 해당 에러 메시지를 swfupload 쪽에서 찾아보면 UI_NO_CLASS_FOUND가 뜨고.. ;;; 대체 이게 뭔 에런지 거의 여덟시간을 헤멤.
결론은…. 너무나도 당연하게도 HTTP 413 메시지였다. ;;; Request entity too large. 맘 편하게 그냥 처음부터 HTTP 에러 메시지로 갔으면 쉬웠을 것을.. 괜히 swfupload랑 연결시켜서 생각하느라 시간낭비한 상황.
당연히, nginx의 vhost 설정에 clientmaxbody_size 50M 한줄 추가로 해결. ;;
좀 쉽게 가도 될 것을…
지금 사용중인 .irbrc 파일.
레일스 개발을 하면서 script/console을 쓰게 되는 경우도 있고, 간단한 ruby code 테스트에는 irb를 습관적으로 많이 사용하기에 .irbrc 파일을 재정의 해서 사용중이다.
레일스 관련 약간의 설정, 그리고 일상적으로 많이 쓰이는 것들을 require한 것 뿐. ^^; 백업 용도로 블로그에 정리!
require 'rubygems'
require 'irb/completion'
require 'irb/ext/save-history'
require 'map_by_method'
require 'what_methods'
require 'pp'
IRB.conf[:AUTO_INDENT]=true
IRB.conf[:SAVE_HISTORY] = 100
IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-save-history"
IRB.conf[:PROMPT_MODE] = :SIMPLE
# Just for Rails...
if rails_env = ENV['RAILS_ENV']
rails_root = File.basename(Dir.pwd)
IRB.conf[:PROMPT] ||= {}
IRB.conf[:PROMPT][:RAILS] = {
:PROMPT_I => "#{rails_root}> ",
:PROMPT_S => "#{rails_root}* ",
:PROMPT_C => "#{rails_root}? ",
:RETURN => "=> %s\n"
}
IRB.conf[:PROMPT_MODE] = :RAILS
# Called after the irb session is initialized and Rails has
# been loaded (props: Mike Clark).
IRB.conf[:IRB_RC] = Proc.new do
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Base.instance_eval { alias :[] :find }
end
endPOJO, DTO, VO에 관하여..
OKJSP의 DTO, POJO, VO 의 차이점이 무엇인가요? 라는 글에 답변으로 달았던 글입니다.
일단.. DTO, VO는 따로 떼 놓고.. POJO는 Plain Old Java Object 라고 부릅니다. 원래는 Java Language Specification을 제외한 어떤 규칙에도 제약받지 않는 녀석(그러니까, 기본 Java Spec에 있는 것을 제외한 특정 클래스를 상속 받거나, 인터페이스를 구현하거나, Annotation을 지정하는..)을 POJO라 그러는데, 사실 이렇게 만들기는 힘들어서, 심각한 수준의 제약만 아니면 POJO-compliant라고 하긴 합니다. (결국, DTO나 VO같은 특정 부분에 사용되는 것을 지칭하는게 아닙니다.)
DTO랑 VO는.. 사실 좀 역사가 복잡합니다. ;;
Core J2EE Patterns 라는 책에서는… Value Object랑 Transfer Object를 동일한 뜻으로 사용합니다만(Transfer Object at Core J2EE Patterns).. 반대로 Martin Fowler는 저서 Patterns of Enterprise Application Architecture에서 약간 다른 의미로 이야기 합니다. DTO는 메소드 호출 횟수를 줄이기 위해 데이터를 담고 있는 녀석으로, VO는 값이 같으면 동일 오브젝트라고 볼 수 있는 녀석으로 표현을 하고 있죠.
예를 들자면
DTO a = new DTO(1);
DTO b = new DTO(1);이라고 했을때,
a != bVO a = VO(1);
VO b = VO(1);이라고 했을때
a == b개인적으로는, 구분의 용이성과 용도가 갈리는 경우가 분명히 존재한다는 면에서, 마틴 파울러의 정의에 한표를 던집니다만.. ;; 사실 저거 구분하는것도 일이라.. 보통은 동일한 의미로 사용합니다.
Attachment_fu model With Custom Filename, Square Cropping.
이번 작업을 하면서 필요했던 부분.
Attachment_fu에서 저장되는 파일 명 변경과 함께, 특정 이미지를 골라서 정해준 위치에 맞게 Cropping을 하는 기능이 필요했다. Cropping 관련 메소드는 Kropper에서 빌려옴. ^^
class ArticleImage < ActiveRecord::Base
belongs_to :article
@@thumbs = {
:large => '180x180!',
:medium => '120x120!',
:small => '90x90!'
}
has_attachment :content_type => :image,
:storage => :file_system,
:max_size => 20.megabytes,
:path_prefix => "public/images/#{table_name}",
:resize_to => '600x400>',
:processor => "Rmagick",
:thumbnails => {
:large => '180x180!',
:medium => '120x120!',
:small => '90x90!'
}
validates_as_attachment
# Customizing Filename.
def full_filename(thumbnail = nil)
file_system_path = (thumbnail ? thumbnail_class : self).attachment_options[:path_prefix].to_s
@thumb = self.thumbnail unless (@thumb = thumbnail)
asset = self.parent_id.nil? ? self.id : self.parent_id
File.join(RAILS_ROOT, file_system_path, *partitioned_path(thumbnail_name_for(@thumb, asset)))
end
# Filename Customizing Method
def thumbnail_name_for(thumbnail = nil, asset = nil)
suffix = "_#{thumbnail}" unless thumbnail.blank?
extension = filename.scan(/\.\w+$/)
return "#{asset}#{suffix}#{extension}"
end
# crops the attached image according to the passed left, top, width, and height params.
# if resize_to_stencil is true, the image is resized to stencil_w x stencil_h.
# after cropping and resizing, the resulting image is saved back to disk.
# any thumbnail image the image may have is automatically updated.
def crop!( options = {} )
# setup the default params
options[:crop_left] ||= 0
options[:crop_top] ||= 0
options[:crop_width] ||= 100
options[:crop_height] ||= 100
options[:stencil_width] ||= 100
options[:stencil_height] ||= 100
options[:resize_to_stencil] ||= false
# passed params could be strings, so convert them to ints/booleans
crop_l = options[:crop_left].to_i
crop_t = options[:crop_top].to_i
crop_w = options[:crop_width].to_i
crop_h = options[:crop_height].to_i
stencil_w = options[:stencil_width].to_i
stencil_h = options[:stencil_height].to_i
resize_to_stencil = false if (options[:resize_to_stencil] == false) || (options[:resize_to_stencil] == "false")
resize_to_stencil = true if (options[:resize_to_stencil] == true) || (options[:resize_to_stencil] == "true")
# call the appropriate crop method for the image processor we're using with attachment_fu
if self.class.include?(Technoweenie::AttachmentFu::Processors::RmagickProcessor)
crop_with_rmagick! crop_l, crop_t, crop_w, crop_h, stencil_w, stencil_h, resize_to_stencil
else
raise "You're using an unsupported image processor."
end
end
private
def crop_with_rmagick!(crop_l, crop_t, crop_w, crop_h, stencil_w, stencil_h, resize_to_stencil)
# create a temporary cropped version of our image
cropped_img = nil
self.with_image do |img|
if (crop_w <= 0) || (crop_h <= 0) || (crop_l + crop_w <= 0) || (crop_t + crop_h <= 0) || (crop_l >= img.base_columns) || (crop_t >= img.base_rows)
raise InvalidCropRect
end
cropped_img = img.crop(crop_l, crop_t, crop_w, crop_h, true )
cropped_img.resize!(stencil_w, stencil_h) if resize_to_stencil
end
# write the cropped image to a temp file, which attachment_fu will use
# to replace the existing image file (and thumbnail, if any) on save
self.temp_path = write_to_temp_file(cropped_img.to_blob)
@@thumbs.each { |suffix, size| create_or_update_thumbnail(self.temp_path, suffix, *size) }
#callback_with_args :after_resize, cropped_img
end
endAttachment_fu model Spec for RSpec
OKJSP에 남겨놨던 글을 좀 자세하게 블로그에 정리.
환경은 다음과 같다.
- Ruby on Rails 2.0.2
- RSpec 1.1.3
- Spec::Rails 1.1.3
- Attachment_fu 2008-03-17
사실 원래 목적은, 이번 플젝을 진행하면서 소소하게 BDD를 적용해 보다가, Plugin으로 처리되는 파일 업로드를 위한 Spec 파일을 만드는것.
역시나 언제나 처럼 구글에는 개발할 때 필요한 거의 모든게 있다. ^^
require File.dirname(__FILE__) + '/../spec_helper'
describe ArticleImage do
before(:all) do
SAMPLE_FILE = RAILS_ROOT + '/tmp/rails.png'
@article_image = ArticleImage.new
@article_image.uploaded_data =
ActionController::TestUploadedFile.new(SAMPLE_FILE, 'image/png')
@article_image.send :process_attachment
end
it "should be valid" do
@article_image.should be_valid
end
end블로그도 좀 쓰고 그럴까...
왜이렇게 블로그에 글을 올린다는건 부담스럽지…
위키나 다른 곳에 글을 올리는건 크게 부담스럽게 생각하지 않으면서, 꼭 블로그에 글 쓰는건 부담스러워 하는거 같같다. ;;
하루 한개씩 올리는 연습이라도 해야 하나…
퇴사 후 이틀째...
흐.. 이걸 이틀 째라고 해야 하는지는 모르겠지만…
지난주 금욜 이후로 출근을 안했으니 일단은 이틀째라고 치고..
토/일 한 챕터 끝낸 상태..
이제 남은건… 11~13, 17 챕터.. 4챕터 마무리 하면 기본적인 초벌 번역본은 끝나는 거고..
에휴… 이래저래 할 일도 쌓이고.. 생각도 많고… 과연 쉬는게 쉬는건가.. 싶은 생각만.. @.@
Working With Rails가 다시 오픈했습니다
Working With Rails가 새로운 기능과 멋진 색상으로 돌아왔습니다. 아주 멋져 보여요. Rails Hackfests와 같은 행사를 주관해 주시는 것에 대해서도 감사드립니다.
Older posts: 1 2