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!
精彩评论