DataMapper has_one problem - ruby

I`m having trouble associating models in DataMapper. Its really simple, but i just can get the idea.
So, i have 2 tables:
1. Books
-> id
-> title
-> publisher_id
2. Publishers
-> id
-> title
The classes:
class Book
property :id, Serial
property :title, String
property :publisher_id, Integer
end
class Publisher
property :id, Serial
property :title, String
end
So, the question is: How can i connect publisher to book? It is 1-to-1 relationship, and the whole thing supposed to look like this:
p = Book.get(12345).publisher
Sorry, maybe it is stupid. But i just cant figure out what kind of declaration i should use.

Haha, im crazy idiot sitting at 2 in the morning. Always happening to me, when i ask somethis - suddenly find answer for my question myself.
It is incorrect, there is one-to-many relationship. So, it is simple as sun in the sky:
class Book
property :id, Serial
property :title, String
property :publisher_id, Integer
belongs_to :publisher
end
class Publisher
property :id, Serial
property :title, String
has n, :books
end
That`s it. It might be helpful to somebody.

Related

How to make a Many-To-One relationship in DataMapper

I'm trying to create an association between two models:
class Person
include DataMapper::Resource
property :id, Serial
property :name, String
end
class Country
include DataMapper::Resource
property :id, Serial
property :name, String
end
I just need a simple relationship on Person (a country_id).
My first idea was to put a has 1 property on Person:
class Person
include DataMapper::Resource
property :id, Serial
property :name, String
has 1, :country
end
Instead of a country_id on Person table, Datamapper created a person_id on Country.
To get what I need, I had to make it inverse:
class Country
include DataMapper::Resource
property :id, Serial
property :name, String
has 1, :person
end
This way I got my country_id field on Person table, but it really doesn't make any sense for me.
Am I misunderstanding something or is there another way to make this association?
Whenever Model A "has" Model B (either one or many), you add the foreign key to Model B.
The flipside of this is "belongs to" - that's what you put on the Model with the foreign key.
I guess in DataMapper you don't have to add foreign key columns explicitly, but you could still do it if you want.
# Person
property :country_id, Integer
Since the foreign key in on Person, you'd use "belongs to". It seems like the same thing as "has one", but it's not. You generally only need "has one" in special cases like one-to-one relationships.
# Person
belongs_to :country
# Country
has n, :people
# you could use has 1, :person if for some reason every country
# only had 1 person in it

Ruby datamapper associations

I am just learning Ruby and datamapper, I have read the docs about associations from the official DataMapper site, but I still have two problems.
First whenever I add associated object, I can not see it when displaying all objects.
I have test class like:
class Test
include DataMapper::Resource
property :id, Serial
property :name, String
has 1, :phonen, :through => Resource
end
And then phonen class like:
class Phonen
include DataMapper::Resource
property :id, Serial
property :number, String
belongs_to :test
end
Then I am creating those 2 objects
#test = Test.create(
:name => "Name here"
)
#phone = Phonen.create(
:number => "Phone number"
)
#test.phonen = #phone
#test.save
And I want to display them like that (I want to return json)
get '/' do
Test.all.to_json
end
What am I doing wrong? maybe its something with the to_json...
I honestly don't know..
But I have one additional question to this topic, lets say I managed to connect those two classes, if I display JSON will I get Phonen { } or just inside class { }?
I know its probably very easy question, but I can't figure it out. That's why I decided to ask you guys. Thanks for help
Test.all
Is returning an active record association in array form, not a hash, when you try to convert to json it's failing.
You can try:
render json: Test.all
As asked in this question:
Ruby array to JSON and Rails JSON rendering

DataMapper: one to many relationship with one of several models?

Here's my models:
class Item
include DataMapper::Resource
property :id, Serial
has 1, :firstitem
has 1, :seconditem
end
class FirstItem
include DataMapper::Resource
property :id, Serial
belongs_to :item
end
class SecondItem
include DataMapper::Resource
property :id, Serial
belongs_to :item
end
Now, my question is this - if I want FirstItem and SecondItem to be different models but want them both to potentially be part of Item (but only one of the two, so a record with FirstItem will not also have a SecondItem), I could make a has 1 relationship for both of them, and only one of them gets filled.
So in a relational database, does it make sense to do this? Is there a better, more efficient way of defining this relationship?
What you want is a polymorphic association, which sadly, DataMapper does not support. Try looking into ActiveRecord instead; you can easily use it with Sinatra.

Foreign keys and associations using DataMapper

I have read this page quite thoroughly:
http://datamapper.org/docs/associations
If the answer is on there, it's simply not expressed in a way I can understand.
I'm very confused about using setting up relationship via Datamapper. The datamapper site above is pretty much all I can find on the topic, and as I've said, it hasn't been particularly helpful.
For example, if I want to create something like the following:
Table: users
id (primary key)
name
Table: attributes
id (pk)
title
Table: user_attributes
id (pk)
user_id (fk to users.id)
attribute_id (fk to attributes.id)
value
This seems simple enough, but it has been prohibitively difficult. Everything I try gives me errors like No relationships named user_attributes or user_attribute in UserUserAttribute (DataMapper::UnknownRelationshipError)
Can someone please tell me the class definitions for this simple mapping, and perhaps point me to a better discussion of DataMapper associations? Below is some of what I've tried.
class User
include DataMapper::Resource
property :id, Serial, :key => true
property :name, String
has n, :user_attributes, :through=>:attribute
end
class Attribute
include DataMapper::Resource
property :id, Serial, :key => true
property :name, String
has n, :user_attributes, :through=>:user
end
class UserAttribute
include DataMapper::Resource
belongs_to :user
belongs_to :attribute
end
I think you're seeing things like UserUserAttribute because DataMapper is trying to auto-generate an anonymous join class.
Here's an article that describes how to make named many-to-many relationships in DataMapper
You would probably change the example something like this:
User -> User
Project -> Attribute
Collaboration -> UserAttribute
The issue is that your class is UserAttribute, and you're trying to name the relationships with user_attributes. Get rid of the underscore, and your issue will disappear (or add an underscore to the class name)

DataMapper subclassing & many-to-many self-referential relationships

I'm building a small Ruby application using DataMapper and Sinatra, and I'm trying to define a basic blog model:
The blog has multiple Users
I have a collection of Posts, each of which is posted by a User
Each Post has a set of Comments
Each Comment can have its own set of Comments - this can repeat several levels deep
I'm running into trouble getting the self-referential relation between comments going due to the fact that each Comment belongs_to a Post. My classes right now look like this:
class User
include DataMapper::Resource
property :id, Serial
property :username, String
property :password, String
has n, :post
end
class Post
include DataMapper::Resource
property :id, Serial
property :content, Text
belongs_to :user
has n, :comment
end
class Comment
include DataMapper::Resource
property :id, Serial
property :content, Text
belongs_to :user
belongs_to :post
end
I'm following the guide at Associations and building a new object (CommentConnection) to link two comments together, but my issue is that each subcomment shouldn't belong to a Post as implied by the Comment class.
My first instinct was to extract out a superclass for Comments, so that one subclass could be "top-level" and belong to a post, while the other kind of comment belongs to another comment. Unfortunately, when I do that I run into issues with the comment IDs becoming null.
What's the best way to model this kind of recursive comment relationship in DataMapper?
What you need is a self referential join in Comments, e.g., each Comment can have a parent comment. Try the following:
class Comment
include DataMapper::Resource
property :id, Serial
property :content, Text
has n, :replies, :child_key => [ :original_id ]
belongs_to :original, self, :required => false #Top level comments have none.
belongs_to :user
belongs_to :post
end
This will allow you to have replies to any given comment, although accessing them may get a little nasty (slow) if the volume gets high. If you get this working and want something more sophisticated you could look at nested sets, I believe there is a nested sets plugin for DataMapper but I haven't used.

Resources