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

Polymorphic joined #546

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion flask_restless/serialization/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ def _dump(self, instance, only=None):
if not c.startswith('__') and c not in COLUMN_BLACKLIST)
# Exclude column names that are foreign keys.
foreign_key_columns = foreign_keys(model)
columns = (c for c in columns if c not in foreign_key_columns)
columns = (c for c in columns if c not in foreign_key_columns or c == primary_key_for(model))

# Create a dictionary mapping attribute name to attribute value for
# this particular instance.
Expand Down
160 changes: 136 additions & 24 deletions tests/test_polymorphism.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"""
from operator import itemgetter

from sqlalchemy import Column
from sqlalchemy import Column, ForeignKey
from sqlalchemy import Integer
from sqlalchemy import Enum
from sqlalchemy import Unicode
Expand All @@ -32,15 +32,16 @@
from .helpers import ManagerTestBase


class PolymorphismTestBase(ManagerTestBase):
class PolymorphismTestBaseSingle(ManagerTestBase, ):
"""Base class for tests of APIs created for polymorphic models
defined using single table inheritance.

"""

def setUp(self):
"""Creates polymorphic models using single table inheritance."""
super(PolymorphismTestBase, self).setUp()

super(PolymorphismTestBaseSingle, self).setUp()

class Employee(self.Base):
__tablename__ = 'employee'
Expand All @@ -52,24 +53,30 @@ class Employee(self.Base):
'polymorphic_identity': 'employee'
}

# This model inherits directly from the `Employee` class, so
# there is only one table being used.
# This model inherits directly from the `Employee` class, so
# there is only one table being used.
class Manager(Employee):
__mapper_args__ = {
'polymorphic_identity': 'manager'
}

self.Employee = Employee
self.Manager = Manager

self.Base.metadata.create_all()

self.post_setup()

class FetchingTestBase(PolymorphismTestBase):
"""Base class for test cases for fetching resources."""
def post_setup(self):
"""A post setup step to avoid conflict in inherited tests"""

pass

def setUp(self):
super(FetchingTestBase, self).setUp()

class FetchingTestBase():
"""Base class for test cases for fetching resources."""

def post_setup(self):
# Create the APIs for the Employee and Manager.
self.apimanager = self.manager
self.apimanager.create_api(self.Employee)
Expand All @@ -83,9 +90,9 @@ def setUp(self):
self.session.commit()


class TestFetchCollection(FetchingTestBase):
"""Tests for fetching a collection of resources defined using single
table inheritance.
class BaseFetchCollection():
"""Tests for fetching a collection of resources defined using
inheritance.

"""

Expand Down Expand Up @@ -155,8 +162,8 @@ def serialize(self, instance, *args, **kw):
assert employees[1]['attributes']['baz'] == 'xyzzy'


class TestFetchResource(FetchingTestBase):
"""Tests for fetching a single resource defined using single table
class BaseTestFetchResource():
"""Tests for fetching a single resource defined using
inheritance.

"""
Expand Down Expand Up @@ -202,14 +209,15 @@ def test_subclass_at_superclass(self):
assert response.status_code == 404


class TestCreating(PolymorphismTestBase):
class BaseTestCreating():
"""Tests for APIs created for polymorphic models defined using
single table inheritance.
inheritance.

"""

def setUp(self):
super(TestCreating, self).setUp()
def post_setup(self):
"""Setup api"""

self.manager.create_api(self.Employee, methods=['POST'])
self.manager.create_api(self.Manager, methods=['POST'])

Expand Down Expand Up @@ -278,11 +286,11 @@ def test_superclass_at_subclass(self):
'type', 'manager', 'employee'])


class TestDeleting(PolymorphismTestBase):
class BaseTestDeleting():
"""Tests for deleting resources."""

def setUp(self):
super(TestDeleting, self).setUp()
def post_setup(self):
"""Setup api and base objects"""

# Create the APIs for the Employee and Manager.
self.manager.create_api(self.Employee, methods=['DELETE'])
Expand Down Expand Up @@ -339,11 +347,12 @@ def test_superclass_at_subclass(self):
assert self.session.query(self.Employee).all() == self.all_employees


class TestUpdating(PolymorphismTestBase):
class BaseTestUpdating():
"""Tests for updating resources."""

def setUp(self):
super(TestUpdating, self).setUp()
def post_setup(self):
"""Setup api and base objects"""


# Create the APIs for the Employee and Manager.
self.manager.create_api(self.Employee, methods=['PATCH'])
Expand Down Expand Up @@ -433,3 +442,106 @@ def test_superclass_at_subclass(self):
response = self.app.patch('/api/manager/1', data=dumps(data))
check_sole_error(response, 404, ['No resource found', 'type',
'manager', 'ID', '1'])


class TestCollectionSingle(BaseFetchCollection, FetchingTestBase,PolymorphismTestBaseSingle):
"""Tests for single table inheritance."""

pass


class TestFetchResourceSingle(BaseTestFetchResource, FetchingTestBase, PolymorphismTestBaseSingle):
"""Tests for single table inheritance."""

pass


class TestCreatingSingle(BaseTestCreating, PolymorphismTestBaseSingle):
"""Tests for single table inheritance."""

pass


class TestDeletingSingle(BaseTestDeleting, PolymorphismTestBaseSingle):
"""Tests for single table inheritance."""

pass


class TestUpdatingSingle(BaseTestUpdating, PolymorphismTestBaseSingle):
"""Tests for single table inheritance."""

pass



class PolymorphismTestBaseJoined(ManagerTestBase):
"""Base class for tests of APIs created for polymorphic models
defined using joined table inheritance.

"""


def setUp(self):
"""Creates polymorphic models using single table inheritance."""
super(PolymorphismTestBaseJoined, self).setUp()

class Employee(self.Base):
__tablename__ = 'employee'
id = Column(Integer, primary_key=True)
type = Column(Enum('employee', 'manager'), nullable=False)
name = Column(Unicode)
__mapper_args__ = {
'polymorphic_on': type,
'polymorphic_identity': 'employee'
}

# Joined Table Inheritance
class Manager(Employee):
__tablename__ = 'manager'
id = Column(Integer, ForeignKey('employee.id'), primary_key=True)
__mapper_args__ = {
'polymorphic_identity': 'manager'
}

self.Employee = Employee
self.Manager = Manager

self.Base.metadata.create_all()

self.post_setup()

def post_setup(self):
"""A post setup step to avoid conflict in inherited tests"""

pass


class TestCollectionJoined(BaseFetchCollection, FetchingTestBase,PolymorphismTestBaseJoined):
"""Tests for joined table inheritance."""

pass


class TestFetchResourceJoined(BaseTestFetchResource, FetchingTestBase, PolymorphismTestBaseJoined):
"""Tests for joined table inheritance."""

pass


class TestCreatingJoined(BaseTestCreating, PolymorphismTestBaseJoined):
"""Tests for joined table inheritance."""

pass


class TestDeletingJoined(BaseTestDeleting, PolymorphismTestBaseJoined):
"""Tests for joined table inheritance."""

pass


class TestUpdatingJoined(BaseTestUpdating, PolymorphismTestBaseJoined):
"""Tests for joined table inheritance."""

pass