Rehber: ActiveRecord modellerini projeler arası paylaştırmak

4
murat

Günümüzde microservis, dağıtık uygulamalar.. vs popüler olmaktan ziyade, otomatik ölçeklenen uygulamalar geliştirmek için gerekli bir yaklaşım halini aldı. Geliştirdiğimiz uygulamanın farklı görevleri olan kısımlarını farklı uygulamalar olarak dağıtabilmek için projeleri bölmeye başladık. Ben de böyle bir ihtiyaçtan yola çıkıp kompleks bir yapısı olan ve refactor gerektiren bir rails uygulamasını görevlerine göre ufak uygulamacıklara bölmeye başladım. Bunu yaparken en önemli sorunum kod kopyalamadan(duplicate) etmeden bu işin altından nasıl kalkarım, daha güzel bir deyişle data modelimi birden fazla rails ve ya rails olmayan projeler arasında nasıl paylaştırırım sorusuna odaklandım. Denemelerim sonucunda sadece ActiveRecord sınıflarını taşıyan bir ruby gem'i yaparak, bu gem'i bir rails projesi, bir sinatra projesi, bir de saf ruby betiği ile kullanabilir hale getirdim. Bu yazıda bulgularımı bir rehber niteliğinde paylaşmak istiyorum.

İçerik

ActiveRecord sınıflarını taşıyan bir ruby gem'i

Yeni bir ruby gem'i oluşturmak için bundle bize aşağıdaki gibi bir template veriyor.

➜ bundle gem models
...
  create  models/Gemfile
  create  models/lib/models.rb
  create  models/lib/models/version.rb
  create  models/models.gemspec
  create  models/Rakefile
  create  models/README.md
  create  models/bin/console
  create  models/bin/setup
  create  models/.gitignore
  create  models/.travis.yml
  create  models/.rspec
  create  models/spec/spec_helper.rb
  create  models/spec/models_spec.rb
  create  models/LICENSE.txt
  create  models/CODE_OF_CONDUCT.md
# :)
➜ mv models models_rb

Tüm uygulama kodlarımızı lib dizini içinde yazacağız. Örnek olarak Student adında bir ActiveRecord modeli oluşturup diğer projelerimizde bunu kullanacağız. Öncelikle .gemspec dosyasında gerekli satırları düzenledikten sonra Gemfile'a 'activerecord' gem'ini ekliyoruz.

# Gemfile

source "https://rubygems.org"

gem "activerecord", "~> 5.0"

# Specify your gem's dependencies in models.gemspec
gemspec

lib/models dizini altında da Student sınıfını oluşturup lib/models.rb dosyasında require ederek gem'i paketleyebiliriz.

# lib/models/student.rb
require "active_record"

module Models
  class Student < ActiveRecord::Base; end
end
# lib/models.rb
require "models/version"
require "models/student"

module Models
  class Error < StandardError; end
end

Gem'i paketleyip rubygems'de yayınlamak isterseniz gerekli adımları şuradan öğrenebilirsiniz. Biz şimdilik yerel adres üzerinden diğer projelerimize dahil edeceğiz. Fakat .gemspec dosyamızdaki spec.files değeri git ls-files -z komutundan dönen dosyaları LOAD_PATH e dahil ettiği için git add . ve git commit -m "mesaj" komutlarını çalıştırmak gerekiyor.

Veritabanı oluşturalım

Basit bir örnek olacağı için sqlite3 ile bir veritabanı oluşturacağım. Bunun için database adında bir dizin açarak içinde sqlite3 app.sqlite3 komutunu çalıştırıyorum ve aşağıdaki sql ile students tablosunu oluşturuyorum.

CREATE TABLE students(
  id INT PRIMARY KEY NOT NULL,
  name TEXT NOT NULL
);

Tablo oluşturduktan sonra kontrol amaçlı .tables komutunu çalıştırıyor ve tablo göründüyse .quit komutu ile çıkıyorum.

Saf ruby betiklerinde nasıl kullanırım?

Başka bir dizine giderek bir app.rb dosyası oluşturalım.

Satır içi bundle

Bir projeye bundle edilmiş bir gem'i dahil etmek için ilk akla gelen yöntem bundle init diyerek bir Gemfile oluşturmak olabilir ama bu sadece bir dosyalık betik olacağından yeni öğrendiğim bundler/inline kullanarak devam edeceğim. Bu işimizi çok kolaylıştıracak. app.rb dosyasına aşağıdakileri ekleyelim.

# app.rb
require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'

  gem "models", path: "../models_rb"
  gem "activerecord"
  gem "sqlite3", "~> 1.4"
end

ActiveRecord::Base.establish_connection(
  adapter: "sqlite3",
  database: "../database/app.sqlite3"
)

puts 'Gems installed and loaded!'
puts "Total student: #{Models::Student.count}"

Models::Student.create id: Models::Student.order(id: :desc).limit(1).first.id + 1, name: "murat"
puts "Total student: #{Models::Student.count}"

Ve ruby dosyamızı ruby app.rb komutu ile çalıştırabiliriz. Göreceğiniz üzere ActiveRecord modelimiz saf bir ruby betiğinde kullanılabilir halde.

Not: Gerçek hayatta veritabanımızı düzgün oluşturacağımız id değerini biz vermeyeceğiz.

Sinatra

Basit bir sinatra projesi oluşturalım.

cd .. && mkdir sinatra_app && cd sinatra_app
➜ bundle init
Writing new Gemfile to sinatra_app/Gemfile

Gemfile'a aşağıdakileri ekleyip bundle install çalıştıralım.

# Gemfile

gem "models", path: "../models_rb"
gem "sinatra"
gem 'sinatra-activerecord'
gem "rake"
gem "json"
gem "sqlite3", "~> 1.4"

Ve app.rb adında bir dosya açıp aşağıdakileri ekleyelim.

# app.rb
require "sinatra"
require "sinatra/activerecord"
require "json"
require "models"

set :database, {adapter: "sqlite3", database: "../database/app.sqlite3"}

get "/" do
  content_type :json
  Models::Student.all.to_json
end

Ve aşağıdaki şekilde çalıştıralım,

➜ bundle exec ruby app.rb

Şimdi tarayıcımızdan http://localhost:4567 adresine gittiğimizde veritabanına eklediğimiz öğrencileri json olarak göreceğiz.

Rails

Bir rails uygulaması oluşturalım, pratik olsun diye --api flag'i ile oluşturacağım.

cd .. && rails new rails_app --api -B -T

➜ cd rails_app

Gemfile'a models gem'imimizi ekleyelim

# Gemfile
# ...
gem "models", path: "../models_rb"

bundle install komutunu çalıştırıp home/index diye bir rota oluşturalım.

➜ rails g controller home index

home_controller index metoduna aşağıdakini yazalım.

# home_controller.rb

# ...
  def index
    render json: { students: Models::Student.all }
  end
end

Ve son olarak database.yml'da sqlite database adresimizi güncelleyip rails s komutu ile sunucusunu ayağa kaldıralım. Ve tarayıcımızdan http://localhost:3000/home/index adresine gidip öğrencilere bakalım.

Son

Artık models gibi bir gem geliştirip tüm ActiveRecord sınıflarımızı yazarak, birden fazla, farklı tipte uygulamada ortak akıl kullanabilir olduk. Faydalı olması dileğiyle.

Not: Bu yazıyı beğendiyseniz medium profilimden de yerebilir veya övebilirsiniz...

Görüşler

2
aren

kudos

1
kakkoyun

Sayin @murat,

Acikcasi bu oruntunun yarardan cok zarar getirecegine inaniyorum. ActiveRecord oruntusu veri tabanina cok bagli, eger veri tabani coklanmayacaksa model katmaninin ayri bir gem olarak ayrimasinin yarardan cok zarari olacagina inaniyorum.

Buradaki aklima gelen bir kac sorun soyle:

1) Gem'i kullanan servisler "Schema migration"'lari hangi hangi sirada ve ne sekilde uygulacaklar? Servisler arasinda senkronizasyon problemleri cikmasi cok olasi. Boyle degisimler soz konusu oldugunda, ayni veritabanini paylasan birden fazla servis var ise hepsinin ayni anda guncellenmesi gerekecek, bunun yaratacagi operasyon yuku cok fazla.

2) Ayni baglamda, sadece kisa sureli bile olsa farkli semaya sahip versiyonlar ayni anda nasil calisacaklar? Olasi hatalar nasil onlenecek? "Zero downtime" guncellemeler nasil yapilacak?

Tabi buradaki tum problemler "tek veri tabani ve birden fazla 'model' katmani" oldugunu varsayiyor. Her servisin kendi veri tabani olacak ve davranislara paylasmak icin boyle bir gem kullanilacaksa bir sorun teskil etmeyecektir.

Fakat senin kullanimin daha cok "tek veritabani ve birden fazla servis" modeline giriyor sanki. Dikkat olmani oneririm.

1
murat

Yorumların için teşekkürler, tamamen hak veriyorum, dezavantajlarını ilk günlerde farkettim ben de. Şu an bu yoldan dönmüş durumdayım. Ama yine de "nasıl" sorusu birilerinin aklına gelirse faydalı olur diye düşündüm. 😅

Görüş belirtmek için giriş yapın...

İlgili Yazılar

Ruby.NET Derleyicisi BETA Sürümü Çıktı

FZ

Gardens Point Ruby.NET derleyicisinin BETA sürümü çıkmış. Sitesinde yazılanlara göre derleyici şu anda bir Ruby kaynak kod dosyasını doğrulanabilir bir .NET 2.0 "assembly" dosyasına derleyebiliyor veya doğrudan söz konusu Ruby kaynak kodunu çalıştırabiliyor (derle, yükle, çalıştır). Ruby.NET derleyicisi Ruby 1.8.2 süiti ile gelen samples/test.rb içindeki 871 testi de düzgün olarak geçmiş durumda.

IBM'den Ruby'ye destek

anonim

IBM, Rails ile DB2 veritabanı kullanacak gelişticiler için özel bir araç seti hazırlamış.

IBM gibi önemli bir firma Ruby on Rails'i kendi ürünü için desteklerken hala kafasını kuma gömen kaldıysa onlar için uyanmanın vakti gelmiş demektir ;)

Javacılar da Ruby Demeye Başladı

FZ

Chris Adamson Ruby the Rival başlıklı yeni yazısında Java dünyasının ağır topları Bruce Tate, James Duncan Davidson, Robert Cooper ve Bill Venners sohbet etmiş ve Ruby'ye nasıl baktıklarını ele almış.

Bir iki şüpheli bakış açısını, "acaba ...?"lı tereddüdü bir kenara bırakırsak görülen manzara şu ki Java programcıları da Ruby'nin çekiciliğine dayanamıyorlar. Her ne kadar "ya aslında bakın enterprise mevzular, çok elemanlı projeler, evet var böyle argümanlarımız ama..." filan deseler de Ruby'nin getirdiği üretkenlik kazancı, Ruby on Rails'in katalizör görevi üstlenmesi gibi durumların farkında olduklarını itiraf ediyorlar.

Ruby on Rails Topluluğunda Neler oluyor?

dueSouth

Şimdilerde Rails konuşlandırmak için en çok önerilen sunucu olan Mongrel'in ilk geliştiricisi Zed Shaw kendi blog sayfasında Rails topluluğunun iç dünyası hakkında bilgi veriyor. Görünüşe göre topluluktan bazıları onu kızdırmışlar ve oldukça ağır bir eleştiri olan bu yazıyı yazmasına ve aktif olarak Rails geliştiriciliğinden çekilmesine sebep olmuşlar.

Symbian OS için Ruby, Symbian Tarafından Yayımlandı

anonim

Symbian firması Symbian OS için kendi hazırladığı Ruby implementasyonunu yayımladı.
Bu uygulamanın ilginç tarafı Symbian'ın kendi inisiyatifi ile hazırlanmış olması. Ruby'nin yaygınlaştığının ve değerinin daha iyi anlaşılmakta olduğunun bir göstergesi olarak algılanabileceği gibi Ruby denince akla sadece Rails ve Web programlama gelmesinin yanlış olacağına dair de örnek teşkil ediyor.

Haber kaynağı: PINguAR