コード例 #1
0
ファイル: model.go プロジェクト: picatic/norm
func getAllFields(model interface{}) map[field.Name]reflect.Value {
	fields := map[field.Name]reflect.Value{}

	// Value of model
	modelValue := reflect.ValueOf(model)
	if modelValue.Kind() == reflect.Ptr {
		modelValue = modelValue.Elem()
	}

	// Type of Model
	modelType := reflect.TypeOf(model)
	if modelType.Kind() == reflect.Ptr {
		modelType = modelType.Elem()
	}

	for i := 0; i < modelType.NumField(); i++ {
		v := modelValue.Field(i)

		// Straight up struct field of type field.Field
		if v.CanAddr() == true && v.Addr().Type().Implements(fieldType) == true {
			fieldName := field.Name(modelType.Field(i).Name)
			fields[fieldName] = modelValue.Field(i)
		} else if v.Kind() == reflect.Struct {
			//t := modelType.Field(i)
			// Embedded Struct with potential field.Field fields
			fieldName := field.Name(modelType.Field(i).Name)
			fields[fieldName] = modelValue.Field(i)
		}
	}

	return fields
}
コード例 #2
0
ファイル: model.go プロジェクト: picatic/norm
func modelFields(model interface{}) field.Names {
	fields := make(field.Names, 0)

	// Value of model
	ifv := reflect.ValueOf(model)
	if ifv.Kind() == reflect.Ptr {
		ifv = ifv.Elem()
	}

	// Type of Model
	itf := reflect.TypeOf(model)
	if itf.Kind() == reflect.Ptr {
		itf = itf.Elem()
	}

	for i := 0; i < itf.NumField(); i++ {
		v := ifv.Field(i)

		// Straight up struct field of type field.Field
		if v.CanAddr() == true && v.Addr().Type().Implements(fieldType) == true {
			fields = append(fields, field.Name(itf.Field(i).Name))
		} else {
			t := itf.Field(i)
			// Embedded Struct with potential field.Field fields
			if t.Anonymous == true && v.CanAddr() == true && v.Kind() == reflect.Struct {
				fields = append(fields, modelFields(v.Addr().Interface())...)
			} else if t.Anonymous == true && v.CanAddr() == true && v.Kind() == reflect.Interface { // Embedded Model interface
				fields = append(fields, modelFields(v.Elem().Interface())...)
			}
		}
	}

	return fields
}
コード例 #3
0
ファイル: model_test.go プロジェクト: c2h5oh/norm
func (*MockModelCustomPrimaryKey) PrimaryKey() PrimaryKeyer {
	return NewCustomPrimaryKey(field.Names{"Id"}, func(pk PrimaryKeyer, model Model) (field.Names, error) {
		f, _ := ModelGetField(model, field.Name("Id"))
		f.Scan("abc-123-xyz-789")
		return field.Names{"Id"}, nil
	})
}
コード例 #4
0
ファイル: primary_keys_test.go プロジェクト: picatic/norm
func TestPrimaryKeyer(t *testing.T) {
	Convey("PrimaryKeyer", t, func() {
		model := &MockModel{}

		Convey("SinglePrimaryKey", func() {
			pk := NewSinglePrimaryKey(field.Name("Id"))
			So(pk.Fields(), ShouldResemble, field.Names{field.Name("Id")})
			fields, err := model.PrimaryKey().Generator(model)
			So(len(fields), ShouldEqual, 0)
			So(err, ShouldBeNil)
			v, _ := model.Id.Value()
			So(v, ShouldBeNil)
		})

		Convey("MultiplePrimaryKey", func() {
			pk := NewMultiplePrimaryKey(field.Names{"Id", "Org"})
			So(pk.Fields(), ShouldResemble, field.Names{"Id", "Org"})
			fields, err := model.PrimaryKey().Generator(model)
			So(len(fields), ShouldEqual, 0)
			So(err, ShouldBeNil)
			v, _ := model.Id.Value()
			So(v, ShouldBeNil)
			v, _ = model.Org.Value()
			So(v, ShouldBeNil)
		})

		Convey("CustomPrimaryKey", func() {
			pk := NewCustomPrimaryKey(field.Names{"Id", "Org"}, func(pk PrimaryKeyer, model Model) (field.Names, error) {
				f, _ := ModelGetField(model, "Id")
				f.Scan("abc-123")
				return field.Names{"Id"}, nil
			})
			fields, err := pk.Generator(model)
			So(len(fields), ShouldEqual, 1)
			So(err, ShouldBeNil)
			v, _ := model.Id.Value()
			So(v, ShouldEqual, "abc-123")
		})

	})
}
コード例 #5
0
ファイル: example_funcs_test.go プロジェクト: c2h5oh/norm
func ExampleModelGetField_() {

	user := &User{}
	user.Id.Scan(1234)
	modelField, err := norm.ModelGetField(user, field.Name("Id"))
	if err != nil {
		fmt.Println(err.Error())
	}
	outputJson(modelField)

	// Output:
	// 1234
}
コード例 #6
0
ファイル: example_model_test.go プロジェクト: picatic/norm
func (u *User) PrimaryKey() norm.PrimaryKeyer {
	return norm.NewSinglePrimaryKey(field.Name("Id"))
}
コード例 #7
0
ファイル: model.go プロジェクト: picatic/norm
func (u *User) PrimaryKeyFieldName() field.Name {
	return field.Name("Id")
}
コード例 #8
0
ファイル: valid_test.go プロジェクト: picatic/norm
func TestValidator(t *testing.T) {

	Convey("ValidatorCache", t, func() {
		var (
			cache      ValidatorCache = make(ValidatorCache, 1)
			validators []FieldValidator
		)
		Convey("Get", func() {
			Convey("Not set", func() {
				So(cache.Get(&MockModel{}), ShouldBeEmpty)
			})
			Convey("When Set", func() {
				mv := &MockValidator{}
				validators = append(validators, mv)
				cache.Set(&MockModel{}, validators)
				So(cache.Get(&MockModel{}), ShouldContain, mv)
			})
		})

		Convey("Set", func() {
			validators = append(validators, &MockValidator{})
			cache.Set(&MockModel{}, validators)
			So(cache.Get(&MockModel{}), ShouldResemble, validators)
		})

		Convey("Del", func() {
			validators = append(validators, &MockValidator{})
			cache.Set(&MockModel{}, validators)
			cache.Del(&MockModel{})
			So(len(cache.Get(&MockModel{})), ShouldEqual, 0)
		})

		Convey("Clone", func() {
			validators = append(validators, &MockValidator{})
			cache.Set(&MockModel{}, validators)
			So(cache.Clone(), ShouldResemble, cache)
		})

		Convey("Validate", func() {
			var (
				fv1, fv2 FieldValidator
				m        *MockModel
			)
			fv1 = NewFieldValidator(field.Name("FirstName"), "value_match", MockFieldValidatorFunc, "test")
			fv2 = NewFieldValidator(field.Name("Org"), "value_match", MockFieldValidatorFunc, "picatic")
			m = &MockModel{}
			cache.Set(m, []FieldValidator{fv1, fv2})
			Convey("Single Error via Names", func() {
				err := cache.Validate(nil, m, field.Names{"FirstName"})
				So(err, ShouldNotBeNil)
				So(len(err.Errors), ShouldEqual, 1)
			})

			Convey("Multiple Errors", func() {
				err := cache.Validate(nil, m, field.Names{"FirstName", "Org"})
				So(err, ShouldNotBeNil)
				So(len(err.Errors), ShouldEqual, 2)
			})

			Convey("No errors", func() {
				m.FirstName.Scan("test")
				m.Org.Scan("picatic")
				err := cache.Validate(nil, m, field.Names{"FirstName", "Org"})
				So(err, ShouldBeNil)
			})
		})
	})

	Convey("ModelValidator", t, func() {
		normConn := NewConnection(nil, "picatic", nil)
		Convey("nil error follows through", func() {
			m := &MockModel{}
			m.FirstName.Scan("Pete")
			err := ModelValidate(normConn.NewSession(nil), m, nil)
			So(err, ShouldBeNil)
			So(err == nil, ShouldBeTrue)
		})

		Convey("error passed", func() {
			m := &MockModel{}
			m.FirstName.Scan("Not Pete")
			err := ModelValidate(normConn.NewSession(nil), m, nil)
			So(err, ShouldNotBeNil)
		})
	})

	Convey("FieldValidator", t, func() {
		var (
			fv FieldValidator
			m  *MockModel
		)

		fv = NewFieldValidator(field.Name("FirstName"), "value_match", MockFieldValidatorFunc, "test")
		m = &MockModel{}
		Convey("Pass", func() {
			m.FirstName.Scan("test")
			err := fv.Validate(nil, m)
			So(err, ShouldBeNil)
		})

		Convey("Fail", func() {
			m.FirstName.Scan("duck")
			err := fv.Validate(nil, m)
			So(err, ShouldNotBeNil)
			So(err, ShouldHaveSameTypeAs, &FieldValidationError{})
			So(fmt.Sprintf("%s", err), ShouldEqual, "Value [duck] did not equal first argument [test]")
		})
	})

	Convey("ValidationError", t, func() {
		var (
			ve *ValidationError
		)
		Convey("New", func() {
			ve = NewValidationError("id", "alias", "invalid")
			So(ve.Field, ShouldEqual, "id")
			So(ve.Message, ShouldEqual, "invalid")
			So(ve.Alias, ShouldEqual, "alias")
			So(ve.Error(), ShouldEqual, "Field: [id] Alias: [alias] Message: invalid")
		})
	})

	Convey("ValidationErrors", t, func() {
		var (
			ves *ValidationErrors
		)
		ves = &ValidationErrors{}
		Convey("Empty", func() {
			So(ves.Error(), ShouldEqual, "Empty errors")
		})

		Convey("Only ValidationError", func() {
			ves.Add(NewValidationError(field.Name("id"), "alias", "mega message"))
			So(ves.Error(), ShouldEqual, "Field: [id] Alias: [alias] Message: mega message")
		})

		Convey("Not ValidationError", func() {
			ves.Add(fmt.Errorf("not a ValidationError"))
			So(ves.Error(), ShouldEqual, "not a ValidationError")
		})
	})
}
コード例 #9
0
ファイル: model_test.go プロジェクト: c2h5oh/norm
func TestModel(t *testing.T) {
	Convey("Model", t, func() {
		db, mock, _ := sqlmock.New()
		conn := NewConnection(db, "mock_db", nil)

		model := &MockModel{}
		model.Id.Scan("1")
		model.FirstName.Scan("Mock")

		modelWithEmbedded := &MockModelEmbedded{}

		Convey("ModelFields", func() {
			Convey("On Ptr to Struct", func() {
				fields := ModelFields(model)
				So(fields, ShouldContain, field.Name("Id"))
				So(fields, ShouldContain, field.Name("FirstName"))
				So(fields, ShouldContain, field.Name("Org"))
				So(len(fields), ShouldEqual, 3)
			})

			Convey("With embedded struct", func() {
				fields := ModelFields(modelWithEmbedded)
				So(fields, ShouldContain, field.Name("Id"))
				So(fields, ShouldContain, field.Name("FirstName"))
				So(fields, ShouldContain, field.Name("Org"))
				So(fields, ShouldContain, field.Name("Created"))
				So(fields, ShouldContain, field.Name("Modified"))
				So(len(fields), ShouldEqual, 5)
			})

			Convey("With embedded Model interface", func() {
				m := &MockModelInterfaceEmbedded{model}
				fields := ModelFields(m)
				So(fields, ShouldContain, field.Name("Id"))
				So(fields, ShouldContain, field.Name("FirstName"))
				So(fields, ShouldContain, field.Name("Org"))
				So(len(fields), ShouldEqual, 3)
			})

		})

		Convey("ModelGetField", func() {

			Convey("When field exists", func() {
				rawModelField, err := ModelGetField(model, "Id")
				So(err, ShouldBeNil)

				f, ok := rawModelField.(*field.NullString)
				So(ok, ShouldBeTrue)
				So(f.String, ShouldEqual, "1")
			})

			Convey("When field does not exist", func() {
				rawModelField, err := ModelGetField(model, "NotAField")
				So(rawModelField, ShouldBeNil)
				So(err, ShouldNotBeNil)
			})

			Convey("Field from Embedded struct", func() {
				modelWithEmbedded.Id.Scan("12")
				idField, err := ModelGetField(modelWithEmbedded, "Id")
				So(err, ShouldBeNil)
				f, ok := idField.(*field.NullString)
				So(ok, ShouldBeTrue)
				So(f.String, ShouldEqual, "12")
			})

			Convey("Fields from embedded Model interface", func() {
				m := &MockModelInterfaceEmbedded{Model: model}
				rawModelField, err := ModelGetField(m, "Id")
				So(err, ShouldBeNil)

				f, ok := rawModelField.(*field.NullString)
				So(ok, ShouldBeTrue)
				So(f.String, ShouldEqual, "1")
			})
		})

		Convey("ModelTableName", func() {
			Convey("Builds table name with connection database prepended", func() {
				sess := conn.NewSession(nil)
				So(ModelTableName(sess, model), ShouldEqual, "mock_db.mocks")
			})
		})

		Convey("NewSelect", func() {

			Convey("Without fields", func() {
				mock.ExpectQuery("SELECT `id`, `first_name`, `org` FROM mock_db\\.mocks").WillReturnRows(sqlmock.NewRows([]string{"id", "first_name"}).FromCSVString("2,mocker"))
				err := NewSelect(conn.NewSession(nil), model, nil).LoadStruct(model)
				So(err, ShouldBeNil)
			})

			Convey("With fields", func() {
				mock.ExpectQuery("SELECT `id` FROM mock_db\\.mocks").WillReturnRows(sqlmock.NewRows([]string{"id"}).FromCSVString("2"))
				err := NewSelect(conn.NewSession(nil), model, field.Names{"Id"}).LoadStruct(model)
				So(err, ShouldBeNil)
				So(model.Id.String, ShouldEqual, "2")
			})
		})

		Convey("NewInsert", func() {

			Convey("Without fields", func() {
				mock.ExpectExec("INSERT INTO `mock_db`\\.`mocks` \\(`first_name`,`org`\\) VALUES \\('Mock',NULL\\)").WillReturnResult(sqlmock.NewResult(2, 1))

				_, err := NewInsert(conn.NewSession(nil), model, nil).Record(model).Exec()
				So(err, ShouldBeNil)
			})

			Convey("With fields", func() {
				mock.ExpectExec("INSERT INTO `mock_db`\\.`mocks` \\(`first_name`\\) VALUES \\('Mock'\\)").WillReturnResult(sqlmock.NewResult(3, 1))
				_, err := NewInsert(conn.NewSession(nil), model, field.Names{"FirstName"}).Record(model).Exec()
				So(err, ShouldBeNil)
			})

			Convey("With Custom Primary Key", func() {
				modelCust := &MockModelCustomPrimaryKey{}
				modelCust.FirstName.Scan("Custom Key")
				mock.ExpectExec("INSERT INTO `mock_db`\\.`mocks` \\((`id`|,|`first_name`)+\\) VALUES \\(('abc-123-xyz-789'|,|'Custom Key')+\\)").WillReturnResult(sqlmock.NewResult(4, 1))
				_, err := NewInsert(conn.NewSession(nil), modelCust, field.Names{"FirstName"}).Record(modelCust).Exec()
				So(err, ShouldBeNil)
			})
		})

		Convey("NewUpdate", func() {

			Convey("Without fields", func() {
				mock.ExpectExec("UPDATE `mock_db`\\.`mocks` SET (`first_name` = 'Mock'|, |`org` = NULL)+ WHERE \\(id = '1'\\)").WillReturnResult(sqlmock.NewResult(0, 1))

				_, err := NewUpdate(conn.NewSession(nil), model, nil).Where("id = ?", model.Id.String).Exec()
				So(err, ShouldBeNil)
			})

			Convey("With fields", func() {
				mock.ExpectExec("UPDATE `mock_db`\\.`mocks` SET `first_name` = 'Mock' WHERE \\(id = '1'\\)").WillReturnResult(sqlmock.NewResult(0, 1))
				_, err := NewUpdate(conn.NewSession(nil), model, field.Names{"FirstName"}).Where("id = ?", model.Id.String).Exec()
				So(err, ShouldBeNil)
			})
		})

		Convey("ModelLoadMap", func() {
			dataMap := map[string]interface{}{
				"id":         "1234",
				"first_name": "James",
			}
			ModelLoadMap(model, dataMap)
			So(model.Id.String, ShouldEqual, "1234")
			So(model.FirstName.String, ShouldEqual, "James")
		})

		Convey("ModelChangedFields", func() {
			model := &MockModel{}
			model.Id.Scan("1")
			model.FirstName.Scan("James James James")
			Convey("No changed fields", func() {
				f, err := ModelDirtyFields(model)
				So(len(f), ShouldEqual, 0)
				So(err, ShouldBeNil)
			})

			Convey("Changed", func() {
				model.FirstName.Scan("Santa")
				f, err := ModelDirtyFields(model)
				So(len(f), ShouldEqual, 1)
				So(err, ShouldBeNil)
			})
		})

		Convey("ModelGetSetFields", func() {
			model := &MockModel{}

			Convey("No set fields", func() {
				f, err := ModelGetSetFields(model)
				So(len(f), ShouldEqual, 0)
				So(err, ShouldBeNil)
			})

			Convey("Changed", func() {
				model.Id.Scan("1")
				model.FirstName.Scan("James James James")
				f, err := ModelGetSetFields(model)
				So(len(f), ShouldEqual, 2)
				So(err, ShouldBeNil)
			})
		})

		Convey("ModelValidate", func() {

			Convey("With validation error", func() {
				err := ModelValidate(conn.NewSession(nil), model, nil)
				So(err, ShouldNotBeNil)
				So(err, ShouldHaveSameTypeAs, &ValidationErrors{})
				So(err.Error(), ShouldEqual, "Field: [FirstName] Alias: [matches] Message: Value [Mock] did not equal first argument [Pete]")
			})

			Convey("Without validation error", func() {
				model.FirstName.Scan("Pete")
				err := ModelValidate(conn.NewSession(nil), model, nil)
				So(err, ShouldBeNil)
			})

		})
	})
}
コード例 #10
0
ファイル: model_test.go プロジェクト: c2h5oh/norm
func (MockModel) Validators() []FieldValidator {
	validators := make([]FieldValidator, 1)
	validators[0] = NewFieldValidator(field.Name("FirstName"), "matches", MockFieldValidatorFunc, "Pete")
	return validators
}
コード例 #11
0
ファイル: model_test.go プロジェクト: c2h5oh/norm
func (*MockModel) PrimaryKey() PrimaryKeyer {
	return NewSinglePrimaryKey(field.Name("Id"))
}