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 overriding default CUD opperations #69

Open
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

jasper-lyons
Copy link

This follows on from #68.

I would like some feedback on how to improve the testcase and bring it more inline with the existing tests if possible!

end

def call(input)
command.call(root => input)
command.call(command.name.relation => input)
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I think this change won't cause issues but I'm wondering what made you change this?

Copy link
Author

@jasper-lyons jasper-lyons Feb 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason is because the previous value was:

Dry::Core::Inflector.singularize(command.name.relation).to_sym

Which meant, if the command was for relation :users the command was being called with:

command.call(:user => { ... })

But the tuple_path in the input elevator called when executing a number of the commands was looking for :users. Changing it to command.name.relation instead meant that the commands were always called like:

command.call(users: { ... })

Which provided the right key for the tuple_path in the InputEvaluator to be traversed.

I imagine it would have been better to update how the tuple_path was constructed but I have 0 idea how to do that.

Copy link
Member

@solnic solnic Feb 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, makes sense not to do something that's not really needed :D

This class is a temporary "solution", the only reason why it exists is because command graphs in rom core, as you noticed, need the relation name as the key. If we can tweak it so this is no longer needed, then this whole proxy can be removed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading that code comment made me feel a little better about changing this class. I think we're not far off making this obsolete. Could you point me in the direction of some cool bits of the command graph code to read?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is probably not that difficult to tweak the code in core so that we can ask graph builder to build the command where the first one is marked as a root without a tuple path. Basically here we ALWAYS append a key to the path (and path is empty by default) that's how we end up with evaluator that always expects a tuple path. So we'd have to change two things:

  1. make it possible to do something like ROM::Commands::Graph.build(registry, graph_opts, false which we'd call right here
  2. tweak these two lines so that if path is false then we use an input evaluator that will simply return the input (literally -> input { input })

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps if the path is empty, InputEvaluator should just return the input? Then we could just not add the key to the path?

I don't understand how the path is built up though.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jasper-lyons yeah it crossed my mind to just allow nil but it's a bit nasty, because we'd be adding special meaning to nil and IF it's nil when it shouldn't be we'd be wondering why and debugging would be harder. So I'd say it's better to use input evaluator when there's actually something to evaluate, otherwise just pass the input as it is.

I don't understand how the path is built up though.

It's built by traversing through the command graph ast and building it up as we dive deeper, see the spec where option is a sample ast, we have :users then :tasks so we end up with :'users.tasks' tuple path while traversing through these options.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I'd say it's better to use input evaluator when there's actually something to evaluate, otherwise just pass the input as it is.

Completely agree. Lets do that.

tweak these two lines so that if path is false then we use an input evaluator that will simply return the input (literally -> input { input })

Why not when path is empty?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not when path is empty?

Because it would break public API

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK yeah, I see that.

.gitignore Outdated
@@ -1,3 +1,5 @@
Gemfile.lock
log/*.log
doc
.byebug_history
tags
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vim or Emacs?
BTW, you can configure global gitignore for all projects ever to ignore such files

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vim.

I should definitely do that. Thanks.

end
end

class CreateAccount < ROM::Commands::Create[:memory]
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I could workout how to do this without creating a stand alone constant I could bring this code more inline with the existing tests. @solnic?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use configuration to define a command using rom's DSL:

configuration.commands(:users) do
  define(:create)
end

I use a cludgy `Object.send(:remove_const, :CustomCommand)` here
to allow the naming of the command object which make checking
the type of the command returned easy. This could be implemented
with some duck typing perhaps?
Moved it into my global ignore instead.
I use a cludgy `Object.send(:remove_const, :CustomCommand)` here
to allow the naming of the command object which make checking
the type of the command returned easy. This could be implemented
with some duck typing perhaps?
Moved it into my global ignore instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants