Comments (40)
hanami-model will provide more conventional usage than "plain rom" which comes with various conveniences like model inference, auto-timestamps, auto-field renaming etc. Pretty much what you would expect from a full-stack framework.
from model.
@Defman21 Yup. @jodosha is working on changing the backend of hanami-model
to use Ruby Object Mapper (rom). He's started it on the new-engine
branch, so you can check it out there, but it's in progress and the docs don't reflect the changes.
from model.
I'm happy to see that there's some work going on to solve this issue :)
from model.
@jodosha Why do you put [] in an 1-n association?
from model.
@AlfonsoUceda Because the target of the association (the comments in that case; the subject would be the related Article
instance) is a collection instead of a single item, hence the array (collection) notation.
At least, that was my reading of it.
from model.
@AlfonsoUceda yes @jdickey is right. This is a convention that I've seen in other Ruby ORMs, we can stick with it, because it's already known.
from model.
Ok thanks @jodosha and @jdickey ;)
from model.
What do you think about the method association inject in atrributes set de foreign key?
from model.
I'm having a hard time understanding how associations would work with the entity.
If do something like article.comments
is CommentRepository.by_article(article)
called behind the scenes?
from model.
@pablocrivella Sorry for the confusion.
I don't want to give entities this faculty. If you look at the example above, where ArticleRepository
preloads the comments, it fetches and assign them to the article object.
Pseudo-code:
article = fetch_article_from_database
comments = fetch_comments_for(article)
article.comments = comments
This hypothetical code shouldn't be visible to you, but happen behind the scenes.
To recap: no real associations in entities, they are just an accessor who is fed by the repository.
from model.
Will it work with lazy loading? (sorry for the nagging, I'm just curious. I really like the approach you are following, I have tried the repository pattern before but with .Net and nhibernate Orm)
from model.
@pablocrivella Not a problem at all, feel free to ask and let me know if it makes sense for you.
It will be lazy by default, if you will omit the .preload(:comments)
(see above), article.comments
will return nil
. This because Article#comments
is just a dumb getter, so you have to be explicit and set that value via the repository.
from model.
@jodosha What do you think about a #load
method? It will use the same logic that the #preload
has but will serve to lazy load the associations.
from model.
@carloslopes Tell me more, please. Where do you see this #load
mechanism? I'm not sure if I got your idea.
from model.
@jodosha sorry, sometimes I still think like AR. The #load
method would stay on the model, but this will break that separation of concerns that we keep here (and this way is a lot better).
My bad!
from model.
@jodosha So wat you mean is that, after serializing the result of the query to an array, preload loops over the result and fill the association attributes? isn't that super inefficient?
from model.
@coenert Why is that?
At the low level when we translate query results to domain objects (eg. Hash
to Comment
), we have those objects that we assign to the article. It's O(n)
, because we need to deserialize comments one by one, but that's common to all the ORMs. Am I missing something?
from model.
@jodosha nevermind, i missed something. I know we have to deserialize all those records, but i thought that every time we deserialize 1 entitty we had to fetch all the associated objects with another query. But we can just make a query like:
where(article_id: [id1, id2, id3, .....])
And then assign the result to each article.
I would like to try this one!
from model.
Ok, i faced a problem while making an test implementation, and i think we should discuss this problem.
When you define an association in the mapper: association :comments, [Comment]
we find the first problem: because we need the Repository
to retrieve the related objects we also need the collection in the same mapper, but we just don't what the collection is.
To get the collection i have 2 possible solutions:
- collection name ==
Entity
name in plurar form and provide api to give specifiy collection name, the rails way. Don't like this one(person -> people problem) - loop over collections(in the same adapter or given adapter) and use the first collection where
Entity
is givenEntity
. Seems the only reasonable way for me
(bold text is my opinion)
from model.
@coenert Suppose we have the following mapping:
collection :comments do
entity Comment
entity CommentRepository
# ...
end
adapter :disqus do
collection :comments do
entity Comment
entity RemoteCommentRepository
# ...
end
end
collection :articles do
# ...
association :comments, [Comment]
# [1] [2]
end
The proposed solution has two arguments:
- The name of the association, we should use this name both to lookup for the homonym collection (the first
:comments
) and to set the attribute into the entityArticle#comments
. This should lookup the default adapter.
1a. We want to use a collection that comes from a different adapter. We should allow to specify it (see example 1).
1b. We want to have a different accessor to be filled into the entity (egArticle#my_comments
). We should introduce another option too (see example 2).
1c. The serialized objects are stored inside the entity. Think of MongoDB's embedded associations, where we don't have a top level:comments
collection, but they are stored inside each single article. We should introduce:attribute
(or:embedded
), as source of this collection. We can use[Comment]
to infer the entity`. - The plural/singular form of the association, to distinguish between has one and has many form. Theoretically this could be replaced with an option like
multiple: true
. Please don't rely on this to lookup the repository.
2a. If we replace this as shown at point 2, we should introduce a new API to infer the entity in case of embedded collection. See 1c.
Example 1
association :comments, [Comment], adapter: :disqus
Example 2
association :my_comments, [Comment], collection: :comments
Example 3
association :comments, [Comment], attribute: :comments
Now, suppose that we have the following signature:
def association(name, options = {})
# the collection name should be computed by looking at the attribute `:collection`, or fallback to `name`.
collection_name = options.fetch(:collection) { name }
end
We can ask to the mapper to retrieve that collection and, finally ask for the repository: mapper.collection(collection_name).repository
.
There are two missing pieces in the just depicted solution:
- A
Mapping::Collection
doesn't have access to themapper
. Evaluate if this is needed by the development if this feature Mapper#collection
should accept anadapter
option:mapper.collection(collection_name, adapter: :disqus)
.
Does this clarify the intents?
from model.
@jodosha thanks for your complete answer
that means that when we have an has one and we want to name it article
instead of articles
(name of collection) we have to define the association like this:
association :article, Article, collection: :articles
it is
About the missing things:
- In my test implementation i added
mapper
as an constructor argument, access to the mapper is mandatory to receive the collection object. - true, i think i will make an seperate PR for this, is that ok?
from model.
@coenert for has one associations you should use:
association :article, Article
You use the brackets when the association is a collection
from model.
@carloslopes youre right, but only need to remove the []
. edited that
from model.
@jodosha I have some concerns about the api, with the current api there is no difference between belongs_to and has_one, how do we know where the foreign_key is located. i thought about how we can change the api so that you can specify that. I came with the idea that an association also an attribute is, but than lazy loaded. what about this api:
Has Many
attribute :my_articles, has.many_of(Article) {
collection :articles
foreign_key :author_id
}
Has One
attribute :details, has.one_of(UserDetails) {
collection :user_details
}
Belongs To
attribute :author, belongs_to(User) {
collection :users
foreign_key :author_id
}
But you can also specifiy the options inline:
attribute :author, belongs_to(User), collection: :users, foreign_key: :author_id
i think it is also simpeler to understand. what do you think about it?
from model.
Is it official part of lotus model?
If yes, why its not mentioned in Readme?
from model.
No, it isn't
El 30/03/2015 18:16, "Extazystas" [email protected] escribiΓ³:
Is it official part of lotus model?
If yes, why its not mentioned in Readme?Reply to this email directly or view it on GitHub
#35 (comment).
from model.
How would associations work for the insert/remove workflow (adding a comment to/removing a comment from an article)? I guess there'd be no support from lotus/model as it's only a "stupid" ruby object?
About the syntax for declaring assocations:
Defining associations with/without []
to indicate has many/ belongs to seems a bit limited (as @coenert already pointed out with the has one case (foreign key on the other end)). I'd prefer something more speaking, like the inline version from @coenert.
Sidenote:
I'm new to lotus and doing a lot of Rails currently
from model.
@pascalbetz Thank you for your opinion. The workflow for add/remove associated records is something under discussion. We're trying to apply a simple design here.
from model.
If i understand correctly:
associations are just "stupid" getters/setters. So there is no syncing between the foreign key attribute and the association?
(pseudocode)
article = Article(id: 1, ....)
p article.user_id => nil
user = User(id: 10, ...)
article.user = user
p article.user_id => 10
I guess you don't want to autogenerate methods like
def user=(user)
self.user_id= user.try(:id)
@user = user
end
on the entity?
from model.
@coenert
Wouldn't the collection/fk/... options be arguments to belongs_to? (assuming belongs_to is a method which returns a type which represents the association)
attribute :author, belongs_to(User, collection: :users, foreign_key: :author_id)
from model.
@pascalbetz Probably, but now after some time i think my suggested api isn't in any way simpeler to understand then the one @jodosha initially suggested. I think i missed the point of creating less magic DSL's to reduce complexity(still learning
from model.
@coenert
The proposed API by @jodosha might hit some limits though (has and belongs to many, has many through, has one).
How about
attribute :user_id, Integer...
belongs_to :user, User, foreign_key: :user_id, ...
has_many :comments, Comment
Pretty much like Rails does it. Just keep the associated class as the second argument.
from model.
Sir, Any updates on this issue ?
from model.
@kirantpatil we are in the cycle of improving model so please stay tuned.
from model.
Are you still in the cycle of improving Model? I'm missing any sort of relations between tables.
from model.
In lieu of hanami-model, what would be the downsides of just straight-up using rom? What will hanami-model provide that rom doesn't right now?
I've been wanting to start new projects in Hanami but the lack of model associations is a pretty big hurdle; pretty much the primary reason I still spin up new apps in Rails.
from model.
attribute :author, belongs_to(User, collection: :users, foreign_key: :author_id)
returns error uninitialized constant Book::User (NameError) -- why
in db it is working correctly
from model.
@senei Please open a separate issue.
from model.
@senei Where did you found that syntax? And where it is used?
from model.
I'm closing this in favor of future, smaller, focused, and actionable proposals.
from model.
Related Issues (20)
- Date with BC note in PostgreSQL parsed incorrectly
- Optimistic Locking HOT 2
- Repository #find_or_create_by HOT 2
- Database column defaults are not replacing empty string or nil values HOT 4
- Sqlite3 'dumps database schema.sql' test failing HOT 3
- Private method 'Array' in hanami entity HOT 2
- Extra query with assoc and that make app slow HOT 1
- Associations don't seem to work well with as: aliases. HOT 3
- What's the recommend way to use transactions? HOT 3
- NoMethodError: undefined method `one' for #<Hanami::Model::Associations::HasMany> HOT 4
- BigDecimal.new error with Postgres HOT 16
- Can't prepare testing PostgreSQL database HOT 5
- #to_hash and implicit conversion HOT 4
- Error
- db prepare raises Postgres createdb error HOT 14
- Unable to control production DB log HOT 1
- [QUESTION] There is a "How to" guide for the test/development process? HOT 2
- Use original error in case role is missing for Postgres HOT 1
- Change default dataset configured in ROM HOT 1
- Outdated dependencies HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from model.