Add has_many association - #46
Conversation
4e5a14d to
e84d548
Compare
e84d548 to
6d199ae
Compare
6d199ae to
13de43e
Compare
13de43e to
f06cb84
Compare
| elsif attribute?(name) then attribute(name) | ||
| elsif predicate?(name) then predicate(name) | ||
| elsif setter?(name) then set_attribute(name, args.first) | ||
| else super |
There was a problem hiding this comment.
I met an error called "SystemStackError: stack level too deep" if write like this in belongs_to commit.
Maybe this association check should be after setter?(name) , I have changed this in that pr.
There was a problem hiding this comment.
In my code, I haven't met this issue. Will try it with your codes later
There was a problem hiding this comment.
I think the problem is you haven't include necessary codes in spec/support/fixtures.rb, like following:
` class CustomPrimaryKeyModel
@@ -37,6 +38,7 @@ class CustomPrimaryKeyModel
include PDC::Resource::Attributes
include PDC::Resource::Attributes
include PDC::Resource::Identity
include PDC::Resource::Identity
include PDC::Resource::Scopes
include PDC::Resource::Scopes
- include PDC::Resource::Associations`
There was a problem hiding this comment.
You need to include PDC::Resource::Associations` for the tested model
|
|
||
| class ProductVersion < Association | ||
| has_many :releases, uri: 'rest_api/v1/releases/?product_version=:product_version_id' | ||
| end |
There was a problem hiding this comment.
When I test with Release class, I add this below line:
has_many :release_variants, uri: 'v1/release-variants/?release=:release_id'
It works, and there is no "rest_api" before v1.
There was a problem hiding this comment.
@xiangge Can u add more detail for this? You mean u add release_variants in a Release class and it doesn't need rest_api?
| class HasMany < Association | ||
| def initialize(*args) | ||
| super | ||
| @options.reverse_merge!(uri: "#{parent_path}/:#{foreign_key}/#{@name}/(:#{primary_key})") |
There was a problem hiding this comment.
Seems even we don't set an uri when init the association, this default uri can't work.
If so I prefer to remove this line
There was a problem hiding this comment.
I think if u don't set the uri, this default one will be used. Maybe in the future we will consider to change the API in this way :)
There was a problem hiding this comment.
Should this maybe be properly joined by a ruby helper function instead of using string interpolation? (Not sure what's out there). Use URI.join maybe?
There was a problem hiding this comment.
OK, got it.
I think we need a comment here to let people know they should add "uri" when they init the association because this default setting can't work currently.
There was a problem hiding this comment.
@romanofski The out for this uri is sth like product-versions/:product_version_id/releases/:release_id. It is the default uri, but actually in PDC server, we don't have this API, we need to customize the uri when defining has_many association. I haven't used URI, because this uri is just a string, it is part of the real URI, this URI includes the sites, and this uri string and params. URI implementation is mostly in lib/pdc/resource/identity.rb and lib/pdc/resource/path.rb
| end | ||
|
|
||
| def load | ||
| self |
There was a problem hiding this comment.
Maybe we don't need to set the "uri" in association, because in each classes it can parse the uri for us.
Here we just need to add the below line to instead of "self" I think.
klass.where(@options[:k_foreign_key] => @params[foreign_key])
And also when we create a association we need to add a var like k_foreign_key there.
Class Release
has_many :release_variants, k_foreign_key: :release
end
There was a problem hiding this comment.
I think the uri is used for overriding. The default one is as the above one uri: "#{parent_path}/:#{foreign_key}/#{@name}/(:#{primary_key})" and u can customize it if your request uri is not following the normal one.
f06cb84 to
56de980
Compare
|
Rebase the latest codes. And add two more test cases related to reflect and custom class name. |
| @@ -0,0 +1,44 @@ | |||
| require 'active_support/dependencies' | |||
There was a problem hiding this comment.
Isn't this addition the same as the one in #47 ? Yet I can't see them being re-used. Any duplication going on or?
There was a problem hiding this comment.
@romanofski Yes. That is duplication. @xiangge and I are all base on the master code and implement has_many and belongs_to respectively. We will rebase it after one patch is merged.
There was a problem hiding this comment.
Ah I see. Fair enough.
| @options[:class_name].constantize if @options[:class_name] | ||
| end | ||
|
|
||
| # https://github.com/rails/rails/blob/70ac072976c8cc6f013f0df3777e54ccae3f4f8c/activerecord/lib/active_record/inheritance.rb#L132-L150 |
There was a problem hiding this comment.
Would be useful to add a comment for the motivation here. Just the link points to a compute_type method which ... well not sure could be different?
There was a problem hiding this comment.
Ok. I think it is imitating rails's implementation to compute the class. I copied this from https://github.com/balvig/spyke. Actually most of the codes are imitating spyke and do some tweaks for our use case. Ok. I will add some comments here :)
There was a problem hiding this comment.
Hm... why are we not actually using spyke? Is there something we do different in this gem? I checked the README, but couldn't find an explanation there.
There was a problem hiding this comment.
@romanofski spyke is a generic gem to Interact with REST services in an ActiveRecord-like manner. It requires activesupport 4.0, but pdc gem needs to run against activesupport 3.2.22. I guess it is because Errata use this version. Also pdc gem is specific for PDC server, we only need to support Get request at least for now, we don't need to support POST/PUT, etc. For example, this association implementation only supports get, no post action.
| class HasMany < Association | ||
| def initialize(*args) | ||
| super | ||
| @options.reverse_merge!(uri: "#{parent_path}/:#{foreign_key}/#{@name}/(:#{primary_key})") |
There was a problem hiding this comment.
Should this maybe be properly joined by a ruby helper function instead of using string interpolation? (Not sure what's out there). Use URI.join maybe?
|
|
||
| def method_missing(name, *args, &block) | ||
| if attribute?(name) then attribute(name) | ||
| if association?(name) then association(name).load |
There was a problem hiding this comment.
Why are we calling load here?
There was a problem hiding this comment.
I think this is to load the association itself, we can use this association to fetch data from PDC server and fill the data in this association later.
There was a problem hiding this comment.
Wouldn't this cause problems if the load fails?
There was a problem hiding this comment.
will load fail? I haven't thought out the case. The fetch action maybe fail or return empty data, but it can be handled correctly.
| VCR.eject_cassette | ||
| end | ||
|
|
||
| let(:site) { 'https://pdc.host.dev.eng.pek2.redhat.com' } |
There was a problem hiding this comment.
Yeah I still have a problem with the data as outlined in previous reviews. See #38 for my explanation.
There was a problem hiding this comment.
Ok. I was thinking we have the conclusion that we don't be nervous with the internal info detail leak as it is not sensitive. But no problem for me to change it to example.com
There was a problem hiding this comment.
Not sure who gave this conclusion. The URL is actually the least of my concern. My concern is how you avoid leaking internal data which should not get into the public?
There was a problem hiding this comment.
hmm... I think the url is the most important one, without this people don't know where to get all these internal information. Wrt the sensitive data to be avoided leaking, maybe release_id/product/product_version are the sensitive data(I am not sure), i choose dummy product and a wrong named ceph product(which name is different with product server), so I am assuming it is not too bad for leaking internal data, does it make sense?
| end | ||
|
|
||
| describe 'association' do | ||
| it 'association independence' do |
There was a problem hiding this comment.
Don't really understand the purpose of this test. What are we testing here?
There was a problem hiding this comment.
This is imitating from spyke :). I think the purpose is to test that we have has_many association releases, not others
| end | ||
|
|
||
| describe 'array like' do | ||
| it 'array like behavior' do |
There was a problem hiding this comment.
Maybe better:
it 'behaves like an array' do
There was a problem hiding this comment.
Ack. Will change it
|
|
||
| product_version = Fixtures::ProductVersion.new(product_version_id: 'ceph-1') | ||
| releases = product_version.releases.where(release_id: 'ceph-1.3@rhel-7') | ||
| releases.any? |
There was a problem hiding this comment.
Should this be asserted here?
There was a problem hiding this comment.
You mean assert at releases.any? or releases.to_a
Actually it is assert the endpoint is only requested once, because we have association
| end | ||
|
|
||
| class ProductVersion < Association | ||
| has_many :releases, uri: 'rest_api/v1/releases/?product_version=:product_version_id' |
There was a problem hiding this comment.
Isn't the URI given by the name spacing of the association? E.g.
pv = PDC::V1::Release::ProductVersion.find('foo')which would translate the URL the above. So not really sure why an additional URI needs to be configured...
There was a problem hiding this comment.
The URI is constructed by several parts, the configured site, the uri and the query parameter. The uri has default value, but it is not proper for current PDC server, we need to customize it. So that is why additional uri needed
|
Dear reviewers, any new comments on this patch? |
|
@romanofski About the sensitive info issue, I am thinking maybe we can make the test cases internal and exclude test in gem repo, but let's think about it in another patch :) |
|
@simozhan I don't know... IMHO unless you have a plan it just seems that you push this decision into the future to make a plan. If it's acknowledged as a problem I suppose coming up with a mitigation process would take precedence over adding more features. No? |
|
@romanofski I created a new jira task in PDC-2541. Will deal with it as the next task. I will merge this patch now, that is really a long time, the rpm feature parity somehow waiting on this. We need to make a new gem to continue with other feature parity's task. Sorry about that and thanks for your review comments. |
1. Implement simple has_many association which can help to cache result and add some test cases. As pdc gem only reads data from pdc server, this patch only implement get related association behavior, not including post action. 2. Change some rubocop configurations Known issues: 1. Need more test cases. 2. Haven't change existing api which can use has_many association like Release, will change it in future patches. JIRA: PDC-1685
7d2b5b1 to
a42c614
Compare
Implement simple has_many association which can help to cache result
and add some test cases.
As pdc gem only reads data from pdc server, this patch only implement
get related association behavior, not including post action.
Known issues:
like Release, will change it in future patches.
JIRA: PDC-1685