Activeadmin'de has_many through ilişkisi

April 26, 2017

Bu blog yazısını yazmak için çok uğraştım. Neden mi? Çünkü bu konuyla alakalı yapmak isteyip de yapamadığım ve aldığım hatalar yüzünden. 2-3 aydır bununla uğraştım diyebilirim. Arada sırada başka branche atlayıp bu aşamaya ara verdiğim çok oldu.

Activeadmin Rails’de Modellerinize göre CRUD işlemleri yapabiliceğiniz sayfaları oluşturacak şekilde admin panel sunan güzel bir gem. Ben kurduktan sonra o tasarımı başka bir gemle değiştirdim: Flat Skin. Eğer siz de tasarımını değiştirmek isterseniz farklı tasarımlara buradan bakabilirsiniz.

Bu arada Activeadmin’in kendine has DSL yapısı var.

DSL (Domain Spesific Language), akla gelebilecek her türlü amaç veya konu için geliştirilmiş özelleştirilmiş dildir.

Ruby on Rails’te many-to-many ilişkisi

Öncelikle Ruby on Rails’de many to many ilişkisi nasıl oluyor bir bakalım. Benim ilişkim Haber ve Kategori modeli arasında oluşuyor. Bir haber birden fazla kategoriye sahip olabilir ve bir kategoride de birden fazla haber olabilir.

class Haber < ApplicationRecord
  has_many :categorizations
  has_many :kategoriler, through :categorizations

  accepts_nested_attributes_for :kategoriler
end

class Kategori < ApplicationRecord
  has_many :categorizations
  has_many :haberler, through :categorizations

  accepts_nested_attributes_for :haberler
end

class Categorization < ApplicationRecord
  belongs_to :haber
  belongs_to :kategori
end

Modellerimizi oluşturup ilişkiyi de kurduktan sonra Activeadmin panelinde yer alması için komut satırından modellerimizi kayıt ettiriyoruz.

rails generate active_admin:resource Haber
rails generate active_admin:resource Kategori

haber.rb dosyamız en başta şu şekilde:

ActiveAdmin.register Haber do
  permit_params :title, :body, :image

  index title: "Haberler" do
    selectable_column
    column "Resim", :image, max_width: "100px" do |img|
      image_tag img.image_url(:thumb)
    end
    column "Başlık", :title
    column "Olusturulma Tarihi", :created_at
    actions
  end

  form do |f|
    f.inputs 'Haber İçeriği', :multipart => true do
      f.input :title, label: "Haber Başlığı"
      f.input :body, label: "Haber Açıklaması"
      f.input :image, :as => :file
      f.input :kategoriler, :as => :check_boxes, :collection => Kategori.all
    end
    f.actions
  end
end

Asıl patladığım olay ise bunların habere bağlanması olayı. En sonunda Özgür Yazılım Günleri’nde tanıştığımız Eyüp Atış ve Göktuğ Göktaş’a sormuştum. Çözüm basitmiş: permit_params methoduna kategori_ids[] eklemek:

permit_params :title, :body, :image, :kategori_ids[]

Kategoriler eklendikten sonraki adım ise bunları göstermek. Bunun için de Eileen Uchitelle’ın blogundan faydalandım:

column "Kategoriler", :kategoriler do |haber|
  haber.kategoriler.each.map do |category|
    link_to category.name, [ :admin, category ]
  end.join(', ').html_safe
end

Bu aşamalarla birlikte many-to-many ilişkisinin en azından Rails ve Activeadmin’deki işleyişini görmüş oldum. Umarım size de faydalı olmuştur.. :)