Don't work behaviors in Datamapper - ruby

I work with Sinatra. This is my models.
class Post
include DataMapper::Resource
property :id, Serial
property :title, String
property :body, Text
property :posted, Boolean, :default => true
has n, :comments
has n, :tags
end
class Comment
include DataMapper::Resource
property :id, Serial
property :user, String
property :body, Text
property :posted, Boolean, :default => false
belongs_to :post
end
class Tag
include DataMapper::Resource
property :id, Serial
property :tag, String
property :weight, Integer, :default => 1
belongs_to :post
end
Create a post
tags = params[:tags].split(' ')
post = Post.new(:title=>params[:title],:body=>params[:body])
tags.each { |tg|
post.tags << Tag.create(:tag=>tg)
}
redirect '/admin' if post.save
But no tags. What do I need to fix?

If you use one-to-many relation, you should create tags with :post set to post:
tags.each { |tg|
Tag.create(:tag => tg, :post => post)
}

Related

DataMapper Self Referential Model

I have a model:
class Comment
include DataMapper::Resource
property :id, Serial
property :comment, Text, :required => true
belongs_to :user
belongs_to :lecture
has n, :replies, :child_key => [:source_id]
has n, :comments, self, :through => :replies, :via => :target
end
And I want to add a comment as a reply to another, already created comment. When I try:
lecture = Lecture.get(params[:lecture_id])
comment = Comment.new(:comment => params[:text])
#user.comments << comment
lecture.comments << comment
if !params[:parent].nil? then
parent = Comment.get(params[:parent])
parent.replies << comment
end
The line parent.replies << comment throws the error:
NoMethodError - undefined method source_id=' for #<Comment #id=nil #comment="asd" #user_id=1 #lecture_id=1>
My Reply model is:
class Reply
include DataMapper::Resource
belongs_to :source, 'Comment', :key => true
belongs_to :target, 'Comment', :key => true
end
How do I correctly add a comment as a 'reply'? Thanks.
Are you sure you want Reply model? The comment tree can be build on just one model Comment that has self-association.
class Comment
...
has n, :replies, 'Comment', :child_key => :source_id
belongs_to :source, 'Comment', :required => false
end

DataMapper Associations

I was just trying to create a database with DataMapper. I am trying to associate the class User with class Post, Post2, Post3 and Post4. And I didnt get any message or changes in the Data SQLite Free, a database Mac application that I am using. Below is the code I created. Did I make any mistakes? Thanks!
require 'sinatra'
require 'data_mapper'
DataMapper::setup(:default, "sqlite3://#{Dir.pwd}/wiki2.db")
class User
include DataMapper::Resource
property :id, Serial
property :username, Text, :required => true
property :password, Text, :required => true
property :date_joined, DateTime
property :edit, Boolean, :required => true, :default => false
has n, :posts
has n, :post2s
has n, :post3s
has n, :post4s
end
class Post
include DataMapper::Resource
property :id, Serial
property :content, Text
property :created_at, DateTime
property :updated_at, DateTime
belongs_to :user
end
class Post2
include DataMapper::Resource
property :id, Serial
property :content, Text
property :created_at, DateTime
property :updated_at, DateTime
belongs_to :user
end
class Post3
include DataMapper::Resource
property :id, Serial
property :content, Text
property :created_at, DateTime
property :updated_at, DateTime
belongs_to :user
end
class Post4
include DataMapper::Resource
property :id, Serial
property :content, Text
property :created_at, DateTime
property :updated_at, DateTime
belongs_to :user
end
DataMapper.finalize.auto_upgrade!

DataMapper `has n` for different types of a model

I would like to have a model with different types of has n, for example:
class Blog
include DataMapper::Resource
property :id, Serial
has 1, :owner # of type user...
has n, :authors # of type user...
end
class User
include DataMapper::Resource
property :id, Serial
has n, :blogs # owns some number
has n, :blogs # is a member of some number
end
I don't, however, want to use the Discriminator, since then I need to make new Owner or Author objects of old User objects and that would be ridiculous.
How can I best achieve this?
Try this:
class User
include DataMapper::Resource
property :id, Serial
has n, :blog_authors, 'BlogAuthor'
has n, :authored_blogs, 'Blog', :through => :blog_authors, :via => :blog
has n, :blog_owners, 'BlogOwner'
has n, :owned_blogs, 'Blog', :through => :blog_owners, :via => :blog
end
class Blog
include DataMapper::Resource
property :id, Serial
has n, :blog_authors, 'BlogAuthor'
has n, :authors, 'User', :through => :blog_authors
has 1, :blog_owner, 'BlogOwner'
end
class BlogAuthor
include DataMapper::Resource
belongs_to :blog, :key => true
belongs_to :author, 'User', :key => true
end
class BlogOwner
include DataMapper::Resource
belongs_to :blog, :key => true
belongs_to :owner, 'User', :key => true
end

Datamapper two associations at the same time

Lets say I have a post, this post should have a certian amount of comments, and these comments should be created by certian users. So these are my datamapper models:
class User
include DataMapper::Resource
property :id, Serial
property :name, String,
property :password, String
has n, :post
end
class Post
include DataMapper::Resource
property :id, Serial
property :text, Text
property :created_at, DateTime
belongs_to :user
end
class Comment
include DataMapper::Resource
property :text, Text,
property :created_at, DateTime
belongs_to :post
belongs_to :user
end
So let's say user x creates a post and user y wants to create a comment to this post. How do I do this then? I need something like this:
user = User.get(sessions[:user_id])
post = Post.get(params[:post_id])
comment = post.user.Comment.new {
:text => "Bla",
[...]
}
[...]
comment.save
[...]
So basicly the Model Post should be associated with the Model Comment and the Model Post, how do I realize this?
comment = Comment.create :post => post, :user => user, :text => 'Foo'

Validate uniqueness on combined fields in DataMapper

I want to be able to put entries in my database where the manufacturer will be represented multiple times but not the same combination of manufacturer and model.
So "Sony(manufacturer), Tv(model)" is okay "Sony(manufacturer), OtherTv(model)" but the third entry "Sony(manufacturer), Tv(model)" is not okay since the combination of manufacturer and model is not unique. I tried with the :key => true validation but it doesn't seem to work. And I cannot do something like validates_uniqueness_of :manufacturer AND :model I guess. So how do you do it?
class Tvs
include DataMapper::Resource
property :id, Serial
property :manufacturer, String, :key => true
property :model, String, :key => true
validates_uniqueness_of :
end
You can actually go with:
class Tvs
include DataMapper::Resource
property :id, Serial
property :manufacturer, String, :unique_index => :manufacturer_model
property :model, String, :unique_index => :manufacturer_model
validates_uniqueness_of :model, :scope => :manufacturer
end
This will also give you a unique index in the database.
Nevermind.
It seems this did the job:
class Tvs
include DataMapper::Resource
property :id, Serial
property :manufacturer, String, :unique_index => true
property :model, String, :unique_index => true
validates_uniqueness_of :model, :scope => :manufacturer
end
class Tvs
include DataMapper::Resource
property :id, Serial
property :manufacturer, String, :unique_index => :manufacturer_model
property :model, String, :unique_index => :manufacturer_model
validates_is_unique :model, :scope => :manufacturer
end
I needed to modify the example to use "validates_is_unique" to get this to work.
If you remove the property :id Serial line, you will end up with a composite key (Manufacturer, Model), that will not allow duplicate Models for a particular Manufacturer.

Resources