Связывание одного класса с двумя разными классами в DataMapper с использованием Sinatra

Я работаю с DataMapper и Sinatra, чтобы создать простое приложение. Вот структура:

В приложении есть Аккаунты. У каждой учетной записи есть пользователи и кампании. У каждого пользователя есть комментарии, которые должны быть связаны с определенной кампанией.

Комментарии в идеале должны иметь идентификатор пользователя и идентификатор кампании, чтобы связать их обоих.

Как я могу связать 2 вместе? Вот код, который у меня есть, который не работает:

class Account
  include DataMapper::Resource
  property :id, Serial
  property :mc_username, String, :required => true
  property :mc_user_id, String, :required => true
  property :mc_api_key, String, :required => true
  property :created_at, DateTime
  property :updated_at, DateTime
  has n, :users
  has n, :campaigns
end

class User
  include DataMapper::Resource
  property :id, Serial
  property :name, String, :required => true
  property :email, String, :required => true
  property :is_organizer, Integer
  property :created_at, DateTime
  property :updated_at, DateTime
  belongs_to :account, :key => true
  has n, :comments
end

class Campaign
  include DataMapper::Resource
  belongs_to :mailchimpaccount, :key => true
  has n, :comments
  property :id, Serial
  property :cid, String
  property :name, String
  property :current_revision, Integer
  property :share_url, Text, :required => true
  property :password, String
  property :created_at, DateTime
  property :updated_at, DateTime
end

class Comment
  include DataMapper::Resource
  belongs_to :campaign, :key => true
  belongs_to :user, :key => true
  property :id, Serial
  property :at_revision, Integer
  property :content, Text
  property :created_at, DateTime
end

С этим кодом я не могу сохранить комментарий, так как не могу понять, как связать его с кампанией и пользователем одновременно. Я не могу понять, стоит ли вообще пытаться связать их с помощью DataMapper.

Я хотел бы знать, правильный ли этот код, как я могу создать комментарий, связанный с обоими. Если нет, то какая структура и ассоциации были бы оптимальными для этого сценария?

Большое спасибо за помощь!


person fholgado    schedule 09.07.2011    source источник


Ответы (3)


То, что вы делаете, кажется разумным, я думаю, вам просто нужно избавиться от параметров :key => true, поскольку вы на самом деле не хотите, чтобы эти ассоциации были частью первичного ключа комментария.

person Alex Reisner    schedule 09.07.2011

Вероятно, вам следует начать с просмотра этих документов datamapper по свойствам.

Алекс прав, у вас есть составной первичный ключ. Это было бы нормально, если бы вы хотели, чтобы у каждого пользователя был только один комментарий для каждой кампании, но это, вероятно, не тот случай, но вы хотите убедиться, что комментарий связан с пользователем и кампанией, поэтому используйте required => true, например так:

class Comment
   include DataMapper::Resource
   property :id, Serial
   belongs_to :campaign, :required => true
   belongs_to :user, :required => true
   property :at_revision, Integer
   property :content, Text
   property :created_at, DateTime
end

Также ваш ключ в модели кампании может быть проблематичным:

class Campaign
   include DataMapper::Resource
   belongs_to :mailchimpaccount, :key => true
   #......

Вы, вероятно, просто хотите, чтобы это тоже требовалось.

person Dangermouse    schedule 09.07.2011
comment
Спасибо за предложения. Изменение ключей на обязательные поля на самом деле немного очистило мою схему базы данных! Я установил их как ключи, так как я продолжал получать ошибки без этой опции, но просто наличие обязательных полей, похоже, работает нормально. - person fholgado; 10.07.2011

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

# Get a user and a campaign first that we can relate to the comment
user = User.get(user_id)
campaign = Campaign.get(campaign_id)
comment = Comment.new
comment.content = "The comment's content"
user.comments << comment # This relates the comment to a specific user
campaign.comments << comment # This now relates the comment to a specific campaign
comment.save # Save the comment

Предложение Dangermouse заменить параметр :key => true на :required => true также помогло очистить схему. Спасибо!

person fholgado    schedule 10.07.2011