Skip to content

Instantly share code, notes, and snippets.

@nicholasf
Last active August 29, 2015 14:22
Show Gist options
  • Save nicholasf/1e10301af1599ddeb447 to your computer and use it in GitHub Desktop.
Save nicholasf/1e10301af1599ddeb447 to your computer and use it in GitHub Desktop.
type Repository interface{
Create(model Model) error
Find(model Model, associations ...Association) (Model, error)
FindByID(model Model, id uint, associations ...Association) (Model, error)
FindAll(models interface{}) (interface{}, error)
Update(model Model) error
Delete(model Model) error
}
//A repository object for reuse
type repository struct {
db *gorm.DB
}
// ... etc
func (r *repository) FindByID(model Model, id uint, associations ...Association) (Model, error) {
err := r.db.First(model, id).Error
if err != nil {
return nil, err
}
err = buildAssociations(r.db, model, associations)
return Model(model), err
}
//FindAll wont work via an abstraction using an array of Models. See http://golang.org/doc/faq#convert_slice_of_interface
func (r *repository) FindAll(models interface{}) (interface{}, error) {
err := r.db.Find(models).Error
if err != nil {
return nil, err
}
return models, err
}
// tests ...
func TestRepository(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Repository and Model Test")
}
type Car struct {
ID uint
LicensePlateNumberID uint
LicensePlateNumber LicensePlateNumber //has one
Parts []Part
Destinations []Destination `gorm:"many2many:car_destinations;"`
}
type LicensePlateNumber struct {
ID uint
Name string
}
//Car has many Parts
type Part struct {
ID uint
CarID uint
}
//Car has many to many Destinations
type Destination struct {
ID uint
Name string
Cars []Car `gorm:"many2many:car_destinations;"`
}
var _ = Describe("Lifecycle of a model with has one, has many and many to many associations", func() {
Context("#NewRepository", func(){
It("successfully instantiates a new repository", func(){
_, err := NewRepository()
Expect(err).ToNot(HaveOccurred())
})
Context("Behaviours for models", func(){
var (
repository Repository
car Car
)
BeforeEach(func(){
repository, _ = NewRepository()
tasks.TruncateTables([]string{
"cars",
"license_plate_numbers",
"parts",
"destinations",
})
db, _ := config.DefaultConnection()
//Migrate them
db.AutoMigrate(&Car{})
db.AutoMigrate(&LicensePlateNumber{})
db.AutoMigrate(&Part{})
db.AutoMigrate(&Destination{})
seattle := Destination{
Name: "Seattle",
}
sanFran := Destination{
Name: "San Francisco",
}
car = Car{
LicensePlateNumber: LicensePlateNumber {
Name: "SCHLOMO88",
},
Parts: []Part{
Part{}, Part{},
},
Destinations: []Destination{
seattle,
sanFran,
},
}
})
It("Creation", func(){
err := repository.Create(&car)
Expect(err).ToNot(HaveOccurred())
})
Context("Finding", func(){
BeforeEach(func(){
err := repository.Create(&car)
if err != nil {
panic(err)
}
})
It("the created parent object", func(){
c := &Car{}
carModel, err := repository.FindByID(c, car.ID)
Expect(err).ToNot(HaveOccurred())
Expect(carModel.Identifier()).To(Equal(car.ID))
})
It("via a FindAll", func(){
//Create a second car, so we have > 1
car2 := &Car{}
err := repository.Create(car2)
Expect(err).ToNot(HaveOccurred())
var cars []Car
foundCars, err := repository.FindAll(&cars)
Expect(err).ToNot(HaveOccurred())
c := foundCars.(*[]Car)
foundCar := (*c)[1]
Expect(foundCar.ID).To(Equal(car2.ID))
})
It("the has one association", func(){
c := &Car{}
carModel, err := repository.FindByID(c, car.ID, HasOne("LicensePlateNumber"))
Expect(err).ToNot(HaveOccurred())
foundCar := carModel.(*Car)
Expect(foundCar.LicensePlateNumber.Name).To(Equal("SCHLOMO88"))
})
It("the has many association", func(){
c := &Car{}
carModel, err := repository.FindByID(c, car.ID, HasMany("Parts"))
Expect(err).ToNot(HaveOccurred())
foundCar := carModel.(*Car)
Expect(len(foundCar.Parts)).To(Equal(2))
})
It("the many to many association", func(){
var dests []Destination
c := &Car{ }
ass := ManyToMany{ Name: "Destinations", Collection: &dests }
_, err := repository.FindByID(c, car.ID, ass)
Expect(err).ToNot(HaveOccurred())
Expect(len(dests)).To(Equal(2))
})
})
Context("Updating", func(){
BeforeEach(func(){
err := repository.Create(&car)
if err != nil {
panic(err)
}
})
It("works", func(){
c := &Car{}
carModel, err := repository.FindByID(c, car.ID, HasOne("LicensePlateNumber"))
foundCar := carModel.(*Car)
foundCar.LicensePlateNumber.Name = "88MOFOYOLO"
err = repository.Update(&foundCar.LicensePlateNumber)
Expect(err).ToNot(HaveOccurred())
sw := &LicensePlateNumber{}
wheel, err := repository.FindByID(sw, foundCar.LicensePlateNumber.ID)
Expect(err).ToNot(HaveOccurred())
sw2 := wheel.(*LicensePlateNumber)
Expect(sw2.Name).To(Equal("88MOFOYOLO"))
})
})
Context("Deleting", func(){
BeforeEach(func(){
err := repository.Create(&car)
if err != nil {
panic(err)
}
})
It("works", func(){
carID := car.ID
err := repository.Delete(car)
Expect(err).ToNot(HaveOccurred())
c := &Car{}
_, err = repository.FindByID(c, carID)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(Equal("record not found"))
})
})
})
})
})
func (c Car) Validate() ([]validation.Invalid, error) {
return nil, nil
}
func (c Car) Identifier() uint {
return c.ID
}
func (c Car) TableName() string {
return "cars"
}
func (c LicensePlateNumber) Validate() ([]validation.Invalid, error) {
return nil, nil
}
func (c LicensePlateNumber) Identifier() uint {
return c.ID
}
func (c Destination) Validate() ([]validation.Invalid, error) {
return nil, nil
}
func (c Destination) Identifier() uint {
return c.ID
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment