开发者

Associating one class to belong to two different classes in DataMapper using Sinatra

开发者 https://www.devze.com 2023-03-18 04:59 出处:网络
I am working with DataMapper and Sinatra to create a simple app. Here\'s the structure: The app has Accounts. Each account has users and campaigns. Each user has comments that should be related to a

I am working with DataMapper and Sinatra to create a simple app. Here's the structure:

The app has Accounts. Each account has users and campaigns. Each user has comments that should be related to a specific campaign.

Comments should ideally have a user_id and a campaign_id to relate them both.

How can I relate the 2 together? Here's the code that I have which does not work:

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
  proper开发者_StackOverflowty :created_at, DateTime
end

With this code, I can't save a comment since I can't figure out how to associate it to a campaign and a user at the same time. I can't really get my head around wether I should even try to relate them at all using DataMapper.

I would love to know if this code is correct, how I can go about creating a comment that is related to both. If not, what structure and associations would be optimal for this scenario?

Thanks so much for the help!


What you're doing seems reasonable, I think you just need to get rid of the :key => true options since you don't really want those associations to be part of the comment's primary key.


You should probably start by looking at these datamapper docs on properties.

Alex is right, what you have there is a composite primary key. This would be ok if you only wanted each user to have one comment per campaign, but this is probably not the case but you do want to make sure that the comment is associated to a user and a campaign so use required => true, like so:

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

Also your key in the campaign model may be problematic:

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

You probably just want to make that required too.


So it seems that my thinking was correct. I can relate a comment to both a user and a campaign in this way:

# 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's suggestion to replace the :key => true option with :required => true also helped clean up the schema. Thanks!

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号