-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create an example project #71
Comments
|
Attachment is a good idea! For relation post <-> categories I've to implement missing many to many relationships. And I came to the conclusion that I need something to declare belongs_to. For both I've some ideas I've to think over. Suggestion: Change the syntax in the struct post
{
oos::identifier<unsigned long> id;
oos::varchar<255> title;
oos::time created_at;
oos::has_many<comment> comments;
oos::has_many<category> categories;
oos::has_one<author> creator;
template < class SERIALIZER >
void serialize(SERIALIZER &s)
{
s.primary_key("id" id);
s.attribute("title", title);
s.attribute("created_at", created_at);
s.has_many("comment", comments);
s.has_many("category_post", categories);
s.belongs_to("author", creator);
}
};
struct author
{
oos::identifier<unsigned long> id;
oos::varchar<255> name;
oos::has_many<post> posts;
template < class SERIALIZER >
void serialize(SERIALIZER &s)
{
s.primary_key("id" id);
s.attribute("name", name);
s.has_many("author", posts); // counterpart of creator in post
}
};
struct category
{
oos::identifier<unsigned long> id;
oos::varchar<255> name;
oos::has_many<post> posts;
template < class SERIALIZER >
void serialize(SERIALIZER &s)
{
s.primary_key("id" id);
s.attribute("name", name);
s.has_many("category_post", posts);
}
}; At first sight it is more readable and understandable for the user. What do you think? |
As for many-to-many relationships Rails offers two methods In either way user should create a joining table. A simple example is as follows:
And for The new syntax looks good. |
This page might give you a hint: http://guides.rubyonrails.org/association_basics.html#choosing-between-has-many-through-and-has-and-belongs-to-many |
And the column As for many-to-many relationships there will be two statements declaring the relation table thus it might lead to duplicate of CREATE TABLE publishment. Then we have to reconsider the implementation details. |
Btw VARCHAR allocates extra bytes to determine the data length.
As you can see the former is slightly better. So the people have been historically using the former more often. |
Thanks for your comments! This would be possible with the new Thus the new syntax is API changing I would put it into 0.5.0. As for many_to_many and belongs_to as well as custom attributes it should be done later. one_to_one isn't explicitly supported, you can achieve it with having a struct person
{
identifier<unsigned long> id;
has_one<person_details> details;
};
struct person_details
{
identifier<unsigned long> id;
has_one<person> person;
}; What do you mean with custom-defined types? In a former version there have been both I wasn't aware of that VARCHAR behavior. Thanks for the information. I'll change my sample code above. |
I'm afraid that
I mean something like class URL
{
public:
URL(std::string const& scheme, std::string const& host, unsigned port, std::string const& path, std::string const& query, std::string const& fragment);
static URL parse(std::string const& url_str);
std::string to_string();
private:
std::string scheme_, host_, path_, query_, fragment_;
unsigned port_;
};
class Site
{
public:
template<class S>
void serialize(S& s)
{
s.serialize("url", url_.to_string()); // It's going to be VARCHAR(255)
}
template<class S>
void deserialize(S const& s)
{
std::string url_str;
s.deserialize("url", url_str);
url_ = URL::parse(url_str); // <------ here
}
private:
URL url_;
}; So you will need both serialize/deserialize API. What do you think of this case? |
Refs issue #72 |
That's what I meant with 'not exactly the same'. We need a belongs_to! Right after 0.5.0 as a next step. Ok, I understand user-defined types. But what about having the possibility to pass to_string/parse function provided for example by the user-defined type class. struct url
{
static std::string to_string();
static url void parse(const std::string &value);
};
template<class S>
void serialize(S& s)
{
s.attribute("url", url_, &url::to_string, &url::parse);
} Or OOS will detect these methods via type traits And the names template<class S>
void serialize(S& s)
{
s.attribute("url", url_);
} And OOS will do the rest. |
The problem for that method is that the user-defined types might be designed to use a (multiple) free function or something. And the most important issue is that you are actually going to place restrictions for the function prototype. What if a class in a library already has some kind of parse/to_string functions available and they have a different API than the one OOS is expecting? You will need to write an another wrapper then. static URL parse(std::string const& str, bool verbose /* <-- */); You could still do something like s.attribute("url", url_, &url::to_string, std::bind(&url::parse, std::placeholders::_1, false)); But it won't fit all the cases because it depends on how complex the user-defined type is. The member function's name could also vary among the implementation like below so the auto-detection will not work
How do you think? |
Ok, I get the point. But to be honest I don't like the idea of a I would like to find another solution for that. We can mix the auto detection of I've learned that it's hard to cover 100% of all use cases but 90% is much easier. And the remaining 10% are also able to get their things done with the library (with a bit overhead on their side). What do you think? |
The design of boost::serialization might give you a hint. A plain, simple non-intrusive serializing code is written in this way: #include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
struct Data {
int number;
double real;
};
namespace boost { namespace serialization {
template<class Archive>
void serialize(Archive & ar, Data & d, unsigned int /* version */) {
ar & make_nvp("number", d.number);
ar & make_nvp("real", d.real);
}
} } // namespace boost::serialization And for splitting serialization, it's written in this way; #include <boost/serialization/serialization.hpp>
#include <boost/serialization/split_free.hpp>
struct Data {
int value;
};
namespace boost { namespace serialization {
template<class Archive>
void serialize(Archive & ar, Data & d, unsigned int version) {
split_free(ar, d, version);
}
template<class Archive>
void save(Archive & ar, Data const& d, unsigned int /* version */) {
const int v = d.value ^ 0xFFFFFFFF;
ar & v;
}
template<class Archive>
void load(Archive & ar, Data & d, unsigned int /* version */) {
int v;
ar & v;
d.value = v ^ 0xFFFFFF;
}
} } // namespace boost::serialization So the common thing is to call
No offense but I actually don't like the auto detection. Because the "convention" which OOS is specifying, i.e. the rule that "a function called to_string() will be used for serializing", might not be logically accurate. It (the to_string() function) could actually be a function doing something totally different than serializing, for example, it could be a function which yields a string value for logging purpose.
This idea is not that bad but I think it could be superseded by the splitting serialization feature.
These five steps can not be done by specifying a single function. That's what I'm concerning. |
You're right with the auto detection. The more I think about it the clearer gets my opinion that auto detection isn't the right strategy for that. But I'm afraid that I'm not convinced with the splitting of the serialization method. I knew the boost::serialization. I like the approach but I'm not satisfied with some points of how they implemented the user interface. Splitting is one point. The example is good - in a theoretical way. Imagine a class with lets say twelve attributes of which two are user defined types. You have to double over 80% of the code if you use splitting. I would prefer an approach where you pass an adapter object to the user defined type: s.custom_attribute("url", url, url_adapter); As you asume correctly the adapter implements an interface to serialize and deserialize the custom type. In addition there could be a global mapping (like the table name mapping we've implemented), where you register an adapter to custom type globaly. This can be overwritten in any case call This approach needs only one serialization method and puts the custom type formatting and parsing in an separate reusable class. I personally like this approach and would be satisfied with it. What are your thoughts? P.S.: Anyway, we will implement this in a later release. What do you think about the renaming. Could you go with it? |
Nice point! s.custom_attribute("url", url, url_adapter); This is magic. We should go with this.
As for renaming (you mean #72 right?) I think it has a small bad aspect.
I think the opposite way. It could made implicit for reducing redundancy since you will need to write a doubled code: oos::has_many<post> posts; // one "has_many" here to specify the type
s.has_many("category_post", posts); // one more "has_many" here. You need to go back to the member declaration and check what type it was. So I think the current implementation which uses type deduction for serializing provides better user experience and less redundancy. boost::serialization deduces type within |
Thanks! But I don't think it's magic 😄 It's just another way of solution (indeed which I like more). And as for blobs we could use the adapter as well. If we have a member of type
Yes, you're right. It's the as for Thanks for this constructive discussion! I think we've a plan! |
So we have agreed to reject #72 and unify them into |
Yes, I think we need to implement a kind of An alternative is to integrate it in the I would go for a |
I think it would be nice to have OMG I'm so drunk now. |
Yes I understand absolutely what you mean 👍 Do you have a party? It's almost 20:45 in Tokyo. Have fun! |
I'm having a party in my friend's apartment 😄 😂 |
Create an example project which covers almost all facets of OOS.
Suggestion: Blog
Entities
Post
Author
Comment
Category
The text was updated successfully, but these errors were encountered: