Skip to content
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

Add support for virtual attributes at the relation definition level #518

Open
waiting-for-dev opened this issue Feb 7, 2019 · 2 comments

Comments

@waiting-for-dev
Copy link
Collaborator

In the same vein that you can define virtual columns in a database, maybe it could be convenient to have something similar for rom attributes at the relation definition level.

In rom-sql, you can already do something like:

relation.order(relation[:attr_1] - relation[:attr_2])

However, the idea would be to have them declared at the relation definition level, together with a new method which could transparently fetch an actual or a virtual attribute.

I think it would be better not to overload .schema and #[] relation methods for this functionality in order to have a clear separation of concerns. In the same way, defined virtual attributes would not be part of the default dataset (at least by default).

Examples

class Relation < ROM::Relation[:sql]
  schema :users  do
    attribute :attr_1, Types::Integer
    attribute :attr_2, Types::Integer
  end

  virtual do |schema|
    attribute(:diff) { |schema| schema[:attr_1] - schema[:attr_2] }
  end
end

# ...

relation.where(relation.fetch(:attr_1) > 2).order(relation.fetch(:diff))

Sure we could find a better name than fetch....

Of course, I could try it myself once I clean a little my stack of pending PRs...

@solnic
Copy link
Member

solnic commented Apr 27, 2019

Why not just define a method:

class Relation < ROM::Relation[:sql]
  schema :users  do
    attribute :attr_1, Types::Integer
    attribute :attr_2, Types::Integer
  end

  def diff
    self[:attr_1] - self[:attr_2]
  end
end

# ...

relation.where(relation.fetch(:attr_1) > 2).order(relation.diff)

???

@waiting-for-dev
Copy link
Collaborator Author

Well, the whole point here is to be able to use them transparently. It would make rom's schemas closer to what we have at the database level. I mean, in SQL we can use an actual field or a dynamic field in the same way: SELECT attr1, attr1 - attr2 FROM...

It is related to the cross-layer convenient coupling I said in #524 (comment):

Then there is also some cross-layer coupling I have been using because sometimes it is too convenient to avoid. For example, say you are rendering an HTML table containing data from a relation and this table have links to be ordered by any of the columns, where each column represents a relation attribute. Currently I'm using the attribute name to build the link, and it is travelling unmodified from the view layer bottom to the relation layer, where it finishes its voyage within #[].

Say in the example you have :attr1, :attr2 and :diff columns. It would be convenient to be able to treat them in the same way and just let the schema resolve the actual difference.

But I'm not 100% sure about it, because at the end one of the reasons I want it is because a coupling, which is convenient, but a coupling anyway. Also, having the relation or schema layer closer to the database layer doesn't have to be a good thing necessarily. But I think it is good to bring this discussion and give it some thoughts, because at first sight I see some benefits to the feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants