-
Notifications
You must be signed in to change notification settings - Fork 66
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
Cannot access objects with chained has many associations #89
Comments
Would be great to also see the JSON responses for this, seems like it might be related to #90 🙇 🙏 |
I have used the following slightly modified class definitions in https://github.com/balvig/spyke/blob/master/test/support/fixtures.rb: class Ingredient < Spyke::Base
uri 'recipes/:recipe_id/ingredients/(:id)'
has_many :alternatives, class_name: "IngredientAlternative",
uri: 'recipes/:recipe_id/ingredients/:ingredient_id/alternatives'
end
class IngredientAlternative < Spyke::Base
uri 'recipes/:recipe_id/ingredients/:ingredient_id/alternatives/(:id)'
end and added the following test: def test_chained_associations
json = { result: { id: 1, groups: [{ ingredients: [{ id: 2, recipe_id: 1, name: 'Fish' }] }] } }
stub_request(:get, 'http://sushi.com/recipes/1').to_return_json(json)
json = { result: [{ id: 3, name: "Tofu" }] }
stub_request(:get, 'http://sushi.com/recipes/1/ingredients/2/alternatives').to_return_json(json)
recipe = Recipe.find(1)
assert_equal 1, recipe.id
ingredient = recipe.ingredients.first
assert_equal recipe.id, ingredient.recipe_id
assert_equal 2, ingredient.id
alternative = ingredient.alternatives.first
assert equal 3, alternative.id
end which fails with the exception/error described in the original bug report.
The |
Thank you @paulvt! Seems this is related to Spyke being designed on the assumption of only having "one level of nesting" for associations (ie Not sure of the best way to fix this yet, it maybe needs a rethink about how associations piece together the URI for sending a request 🤔 |
Yes, I have been thinking about this. I can think of two ways...
...
class HasMany < Association
def initialize(*args)
super
@options.reverse_merge!(uri: "#{parent_path}/:#{foreign_key}/#{@name}/(:#{primary_key})")
@params[foreign_key] = parent.id
end
...
def parent_path
parent.class.model_name.element.pluralize
end
end If you look at the above code, for the default URI that would have been used, In this case, would just would like to tell the relation that first, I want to use a different URI namely The latter solution does require that the API provides both IDs though. |
It seems that the association only adds the parameter of the parent (and not all ancestors), see lib/spyke/associations/has_many.rb#L7. As a result, when going through two relations, the URL cannot be constructed any more because there is a parameter missing. For example:
This yields:
I am not too familiar with the code base yet, so I haven't come up with a pull request. A solution might be that
HasMany#initialize
adds all:<something>_id
key/values toparams
that it finds in the URI, not just theforeign_key
that is used in the default URI?The text was updated successfully, but these errors were encountered: