рельсы соединяют проблему таблицы - PullRequest
2 голосов
/ 18 сентября 2009

Часть моего приложения RoR отвечает за управление портфелем дизайнов веб-сайтов. Один дизайн веб-сайта может иметь много изображений, связанных с ним. Одно изображение может быть связано только с одним дизайном. Я использую оператор has_many с параметром: through, чтобы связать изображения с дизайном через таблицу соединений. А при удалении изображения связанная запись в объединяемой таблице должна быть удалена. Так что у меня есть следующие модели Для изображений:

class  Image < ActiveRecord::Base
  has_one :images_site_designs , :class_name => "ImagesSiteDesigns" , :dependent => :destroy
  has_one :site_design , :through => :images_site_designs
end

Для site_designs:

class SiteDesign < ActiveRecord::Base
  belongs_to :client
  has_many :images_site_designs , :class_name => "ImagesSiteDesigns"
  has_many :images , :through => :images_site_designs
end

И присоединиться к таблице images_site_designs:

class ImagesSiteDesigns < ActiveRecord::Base
  belongs_to :image 
  belongs_to :site_design
end

Создание новых изображений для site_designs в порядке, поэтому следующий код работает нормально:

   @site_design = SiteDesign.find(params[:id])
   @site_design.images << Image.new(params[:image])

Но когда я пытаюсь удалить изображение, появляется следующая ошибка:

 ActiveRecord::StatementInvalid in ImagesController#destroy

Mysql::Error: Unknown column 'id' in 'where clause': DELETE FROM `images_site_designs` WHERE `id` = NULL

Похоже, что рельсы используют неправильное имя столбца для запроса таблицы соединений images_site_designs. Как я могу это исправить?

UPD:

Функции image_controller, которые удаляют изображение:

  def destroy
    @image = Image.find(params[:id])
    @image.destroy

    respond_to do |format|
      format.html { redirect_to(images_url) }
      format.xml  { head :ok }
    end
  end

Миграция:

class CreateImages < ActiveRecord::Migration
  def self.up
    create_table :images do |t|
      t.string :url
      t.string :name
      t.text :description

      t.timestamps
    end
  end

  def self.down
    drop_table :images
  end
end
class CreateSiteDesigns < ActiveRecord::Migration
  def self.up
    create_table :site_designs do |t|
      t.string :name
      t.text :concept
      t.text :description
      t.integer :client_id

      t.timestamps
    end
  end

  def self.down
    drop_table :site_designs
  end
end

class CreateImagesSiteDesigns < ActiveRecord::Migration
  def self.up
    create_table :images_site_designs , :id => false do |t|
      t.integer :image_id
      t.integer :site_design_id
    end
  end

  def self.down
    drop_table :images_site_designs
  end
end

Ответы [ 3 ]

2 голосов
/ 18 сентября 2009

Проблема здесь в том, что у вас есть миграция, которая делает ваш image_site_design НЕ моделью (столбец id), но вы затем создаете модель ActiveRecord для нее. Для того, чтобы вы работали, вам нужно иметь столбец идентификатора в таблице соединений.

1 голос
/ 18 сентября 2009

Не могу ответить на ваш вопрос, потому что не показано, какой код вызывает ошибку. Предположительно, вызов уничтожить в экземпляре Image, но не уверен.

Тем не менее, это не похоже на то, что вам нужно в любом случае присоединиться к модели. Требование, кажется, удовлетворяется следующим:

class SiteDesign < ActiveRecord::Base
  belongs_to :client
  has_many :images
end

class Image < ActiveRecord::Base
  belongs_to :site_design
end

Конечно, это потребует миграции (удалите таблицу соединений и добавьте site_design_id в таблицу изображений), но кажется более чистым решением. Есть причина не делать этого?

0 голосов
/ 18 сентября 2009

Если вы хотите, чтобы одно изображение могло быть связано только с одним дизайном, почему тогда вы используете отношение has_and_belongs_to (вы используете таблицу n: m!)

Я бы реорганизовал следующее:

1) Перенесите модель изображений и добавьте атрибут Site_design_id

class CreateImages < ActiveRecord::Migration
  def self.up
    create_table :images do |t|
      t.string :url
      t.string :name
      t.text :description
      t.integer :site_design_id

      t.timestamps
    end
  end

  def self.down
    drop_table :images
  end
end

2) Отбросить ImagesSiteDesigns-Migration

drop_table :images_site_designs

3) Измените модели на:

class SiteDesign < ActiveRecord::Base
  belongs_to :client
  has_many :images
end

class  Image < ActiveRecord::Base
  belongs_to :site_design
end

Таким образом, вы получите отношение 1: n, и это должно стать лучшим решением для вашей спецификации.

Вы можете получить доступ к своим моделям следующим образом:

Image.first.site_design
=> <SiteDesign #id:...>
SiteDesign.first.image
=> <Image #id...>

SiteDesign.image = Image.new(params[:image])
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...