Repository: goadesign/goa
Pull request #2348 (2019-10-31 06:52:31)

Fix viewd result type uses unkeyed fields.
# Example design

```go
package design

import (
	. "goa.design/goa/v3/dsl"
)

var MyResult = ResultType("application/add-result+json", func() {
	Attributes(func() {
		Attribute("result", Int)
	})
})

var _ = Service("calc", func() {
	Description("The calc service performs operations on numbers.")

	Method("add", func() {
		Payload(func() {
			Field(1, "a", Int, "Left operand")
			Field(2, "b", Int, "Right operand")
			Required("a", "b")
		})
		Result(MyResult)
		HTTP(func() {
			GET("/add/{a}/{b}")
			Response(StatusOK)
		})
	})
})
```

# goa gen

gen/calc/service.go

**before**
```go
// NewViewedAddResult initializes viewed result type AddResult from result type
// AddResult using the given view.
func NewViewedAddResult(res *AddResult, view string) *calcviews.AddResult {
	var vres *calcviews.AddResult
	switch view {
	case "default", "":
		p := newAddResultView(res)
		vres = &calcviews.AddResult{p, "default"}  // ★★★
	}
	return vres
}
```

**after**
```go
// NewViewedAddResult initializes viewed result type AddResult from result type
// AddResult using the given view.
func NewViewedAddResult(res *AddResult, view string) *calcviews.AddResult {
	var vres *calcviews.AddResult
	switch view {
	case "default", "":
		p := newAddResultView(res)
		vres = &calcviews.AddResult{Projected: p, View: "default"}  //  ★★★
	}
	return vres
}
```

raphael: Thank you! Can you please back port to v2 as well? thanks!

Patch:
diff --git a/codegen/service/service_data.go b/codegen/service/service_data.go
index fa19cd7b..1e894749 100644
--- a/codegen/service/service_data.go
+++ b/codegen/service/service_data.go
@@ -1568,7 +1568,7 @@ const (
 		case {{ printf "%q" .Name }}{{ if eq .Name "default" }}, ""{{ end }}:
 			{{- if $.ToViewed }}
 				p := {{ $.InitName }}{{ if ne .Name "default" }}{{ goify .Name true }}{{ end }}({{ $.ArgVar }})
-				{{ $.ReturnVar }} = {{ if not $.IsCollection }}&{{ end }}{{ $.TargetType }}{ p,  {{ printf "%q" .Name }} }
+				{{ $.ReturnVar }} = {{ if not $.IsCollection }}&{{ end }}{{ $.TargetType }}{Projected: p, View: {{ printf "%q" .Name }} }
 			{{- else }}
 				{{ $.ReturnVar }} = {{ $.InitName }}{{ if ne .Name "default" }}{{ goify .Name true }}{{ end }}({{ $.ArgVar }}.Projected)
 			{{- end }}
diff --git a/http/codegen/client.go b/http/codegen/client.go
index 93bf53a6..06d3f068 100644
--- a/http/codegen/client.go
+++ b/http/codegen/client.go
@@ -608,7 +608,7 @@ func {{ .ResponseDecoder }}(decoder func(*http.Response) goahttp.Decoder, restor
 				{{- else }}
 			view := resp.Header.Get("goa-view")
 				{{- end }}
-			vres := {{ if not $.Method.ViewedResult.IsCollection }}&{{ end }}{{ $.Method.ViewedResult.ViewsPkg}}.{{ $.Method.ViewedResult.VarName }}{p, view}
+			vres := {{ if not $.Method.ViewedResult.IsCollection }}&{{ end }}{{ $.Method.ViewedResult.ViewsPkg}}.{{ $.Method.ViewedResult.VarName }}{Projected: p, View: view}
 			{{- if .ClientBody }}
 				if err = {{ $.Method.ViewedResult.ViewsPkg}}.Validate{{ $.Method.Result }}(vres); err != nil {
 					return nil, goahttp.ErrValidationError("{{ $.ServiceName }}", "{{ $.Method.Name }}", err)


Test patch:
diff --git a/codegen/service/testdata/service_code.go b/codegen/service/testdata/service_code.go
index 8f091a1d..cc57ba18 100644
--- a/codegen/service/testdata/service_code.go
+++ b/codegen/service/testdata/service_code.go
@@ -47,7 +47,7 @@ func NewViewedResultWithSpace(res *ResultWithSpace, view string) *servicewithspa
 	switch view {
 	case "default", "":
 		p := newResultWithSpaceView(res)
-		vres = &servicewithspacesviews.ResultWithSpace{p, "default"}
+		vres = &servicewithspacesviews.ResultWithSpace{Projected: p, View: "default"}
 	}
 	return vres
 }
@@ -438,10 +438,10 @@ func NewViewedMultipleViews(res *MultipleViews, view string) *multiplemethodsres
 	switch view {
 	case "default", "":
 		p := newMultipleViewsView(res)
-		vres = &multiplemethodsresultmultipleviewsviews.MultipleViews{p, "default"}
+		vres = &multiplemethodsresultmultipleviewsviews.MultipleViews{Projected: p, View: "default"}
 	case "tiny":
 		p := newMultipleViewsViewTiny(res)
-		vres = &multiplemethodsresultmultipleviewsviews.MultipleViews{p, "tiny"}
+		vres = &multiplemethodsresultmultipleviewsviews.MultipleViews{Projected: p, View: "tiny"}
 	}
 	return vres
 }
@@ -464,7 +464,7 @@ func NewViewedSingleView(res *SingleView, view string) *multiplemethodsresultmul
 	switch view {
 	case "default", "":
 		p := newSingleViewView(res)
-		vres = &multiplemethodsresultmultipleviewsviews.SingleView{p, "default"}
+		vres = &multiplemethodsresultmultipleviewsviews.SingleView{Projected: p, View: "default"}
 	}
 	return vres
 }
@@ -577,10 +577,10 @@ func NewViewedMultipleViewsCollection(res MultipleViewsCollection, view string)
 	switch view {
 	case "default", "":
 		p := newMultipleViewsCollectionView(res)
-		vres = resultcollectionmultipleviewsmethodviews.MultipleViewsCollection{p, "default"}
+		vres = resultcollectionmultipleviewsmethodviews.MultipleViewsCollection{Projected: p, View: "default"}
 	case "tiny":
 		p := newMultipleViewsCollectionViewTiny(res)
-		vres = resultcollectionmultipleviewsmethodviews.MultipleViewsCollection{p, "tiny"}
+		vres = resultcollectionmultipleviewsmethodviews.MultipleViewsCollection{Projected: p, View: "tiny"}
 	}
 	return vres
 }
@@ -721,10 +721,10 @@ func NewViewedMultipleViews(res *MultipleViews, view string) *resultwithotherres
 	switch view {
 	case "default", "":
 		p := newMultipleViewsView(res)
-		vres = &resultwithotherresultviews.MultipleViews{p, "default"}
+		vres = &resultwithotherresultviews.MultipleViews{Projected: p, View: "default"}
 	case "tiny":
 		p := newMultipleViewsViewTiny(res)
-		vres = &resultwithotherresultviews.MultipleViews{p, "tiny"}
+		vres = &resultwithotherresultviews.MultipleViews{Projected: p, View: "tiny"}
 	}
 	return vres
 }
@@ -873,13 +873,13 @@ func NewViewedRT(res *RT, view string) *resultwithresulttypecollectionviews.RT {
 	switch view {
 	case "default", "":
 		p := newRTView(res)
-		vres = &resultwithresulttypecollectionviews.RT{p, "default"}
+		vres = &resultwithresulttypecollectionviews.RT{Projected: p, View: "default"}
 	case "extended":
 		p := newRTViewExtended(res)
-		vres = &resultwithresulttypecollectionviews.RT{p, "extended"}
+		vres = &resultwithresulttypecollectionviews.RT{Projected: p, View: "extended"}
 	case "tiny":
 		p := newRTViewTiny(res)
-		vres = &resultwithresulttypecollectionviews.RT{p, "tiny"}
+		vres = &resultwithresulttypecollectionviews.RT{Projected: p, View: "tiny"}
 	}
 	return vres
 }
@@ -1230,10 +1230,10 @@ func NewViewedMultipleViews(res *MultipleViews, view string) *streamingresultwit
 	switch view {
 	case "default", "":
 		p := newMultipleViewsView(res)
-		vres = &streamingresultwithviewsserviceviews.MultipleViews{p, "default"}
+		vres = &streamingresultwithviewsserviceviews.MultipleViews{Projected: p, View: "default"}
 	case "tiny":
 		p := newMultipleViewsViewTiny(res)
-		vres = &streamingresultwithviewsserviceviews.MultipleViews{p, "tiny"}
+		vres = &streamingresultwithviewsserviceviews.MultipleViews{Projected: p, View: "tiny"}
 	}
 	return vres
 }
@@ -1339,10 +1339,10 @@ func NewViewedMultipleViews(res *MultipleViews, view string) *streamingresultwit
 	switch view {
 	case "default", "":
 		p := newMultipleViewsView(res)
-		vres = &streamingresultwithexplicitviewserviceviews.MultipleViews{p, "default"}
+		vres = &streamingresultwithexplicitviewserviceviews.MultipleViews{Projected: p, View: "default"}
 	case "tiny":
 		p := newMultipleViewsViewTiny(res)
-		vres = &streamingresultwithexplicitviewserviceviews.MultipleViews{p, "tiny"}
+		vres = &streamingresultwithexplicitviewserviceviews.MultipleViews{Projected: p, View: "tiny"}
 	}
 	return vres
 }
@@ -1661,10 +1661,10 @@ func NewViewedMultipleViews(res *MultipleViews, view string) *streamingpayloadre
 	switch view {
 	case "default", "":
 		p := newMultipleViewsView(res)
-		vres = &streamingpayloadresultwithviewsserviceviews.MultipleViews{p, "default"}
+		vres = &streamingpayloadresultwithviewsserviceviews.MultipleViews{Projected: p, View: "default"}
 	case "tiny":
 		p := newMultipleViewsViewTiny(res)
-		vres = &streamingpayloadresultwithviewsserviceviews.MultipleViews{p, "tiny"}
+		vres = &streamingpayloadresultwithviewsserviceviews.MultipleViews{Projected: p, View: "tiny"}
 	}
 	return vres
 }
@@ -1776,10 +1776,10 @@ func NewViewedMultipleViews(res *MultipleViews, view string) *streamingpayloadre
 	switch view {
 	case "default", "":
 		p := newMultipleViewsView(res)
-		vres = &streamingpayloadresultwithexplicitviewserviceviews.MultipleViews{p, "default"}
+		vres = &streamingpayloadresultwithexplicitviewserviceviews.MultipleViews{Projected: p, View: "default"}
 	case "tiny":
 		p := newMultipleViewsViewTiny(res)
-		vres = &streamingpayloadresultwithexplicitviewserviceviews.MultipleViews{p, "tiny"}
+		vres = &streamingpayloadresultwithexplicitviewserviceviews.MultipleViews{Projected: p, View: "tiny"}
 	}
 	return vres
 }
@@ -2031,10 +2031,10 @@ func NewViewedMultipleViews(res *MultipleViews, view string) *bidirectionalstrea
 	switch view {
 	case "default", "":
 		p := newMultipleViewsView(res)
-		vres = &bidirectionalstreamingresultwithviewsserviceviews.MultipleViews{p, "default"}
+		vres = &bidirectionalstreamingresultwithviewsserviceviews.MultipleViews{Projected: p, View: "default"}
 	case "tiny":
 		p := newMultipleViewsViewTiny(res)
-		vres = &bidirectionalstreamingresultwithviewsserviceviews.MultipleViews{p, "tiny"}
+		vres = &bidirectionalstreamingresultwithviewsserviceviews.MultipleViews{Projected: p, View: "tiny"}
 	}
 	return vres
 }
@@ -2149,10 +2149,10 @@ func NewViewedMultipleViews(res *MultipleViews, view string) *bidirectionalstrea
 	switch view {
 	case "default", "":
 		p := newMultipleViewsView(res)
-		vres = &bidirectionalstreamingresultwithexplicitviewserviceviews.MultipleViews{p, "default"}
+		vres = &bidirectionalstreamingresultwithexplicitviewserviceviews.MultipleViews{Projected: p, View: "default"}
 	case "tiny":
 		p := newMultipleViewsViewTiny(res)
-		vres = &bidirectionalstreamingresultwithexplicitviewserviceviews.MultipleViews{p, "tiny"}
+		vres = &bidirectionalstreamingresultwithexplicitviewserviceviews.MultipleViews{Projected: p, View: "tiny"}
 	}
 	return vres
 }
diff --git a/http/codegen/testdata/result_decode_functions.go b/http/codegen/testdata/result_decode_functions.go
index dfc33de4..8c8e6211 100644
--- a/http/codegen/testdata/result_decode_functions.go
+++ b/http/codegen/testdata/result_decode_functions.go
@@ -67,7 +67,7 @@ func DecodeMethodBodyMultipleViewResponse(decoder func(*http.Response) goahttp.D
 			}
 			p := NewMethodBodyMultipleViewResulttypemultipleviewsOK(&body, c)
 			view := resp.Header.Get("goa-view")
-			vres := &servicebodymultipleviewviews.Resulttypemultipleviews{p, view}
+			vres := &servicebodymultipleviewviews.Resulttypemultipleviews{Projected: p, View: view}
 			if err = servicebodymultipleviewviews.ValidateResulttypemultipleviews(vres); err != nil {
 				return nil, goahttp.ErrValidationError("ServiceBodyMultipleView", "MethodBodyMultipleView", err)
 			}
@@ -110,7 +110,7 @@ func DecodeMethodEmptyBodyResultMultipleViewResponse(decoder func(*http.Response
 			}
 			p := NewMethodEmptyBodyResultMultipleViewResulttypemultipleviewsOK(c)
 			view := resp.Header.Get("goa-view")
-			vres := &serviceemptybodyresultmultipleviewviews.Resulttypemultipleviews{p, view}
+			vres := &serviceemptybodyresultmultipleviewviews.Resulttypemultipleviews{Projected: p, View: view}
 			res := serviceemptybodyresultmultipleview.NewResulttypemultipleviews(vres)
 			return res, nil
 		default:
@@ -165,7 +165,7 @@ func DecodeMethodExplicitBodyPrimitiveResultMultipleViewResponse(decoder func(*h
 			}
 			p := NewMethodExplicitBodyPrimitiveResultMultipleViewResulttypemultipleviewsOK(body, c)
 			view := resp.Header.Get("goa-view")
-			vres := &serviceexplicitbodyprimitiveresultmultipleviewviews.Resulttypemultipleviews{p, view}
+			vres := &serviceexplicitbodyprimitiveresultmultipleviewviews.Resulttypemultipleviews{Projected: p, View: view}
 			if err = serviceexplicitbodyprimitiveresultmultipleviewviews.ValidateResulttypemultipleviews(vres); err != nil {
 				return nil, goahttp.ErrValidationError("ServiceExplicitBodyPrimitiveResultMultipleView", "MethodExplicitBodyPrimitiveResultMultipleView", err)
 			}
@@ -216,7 +216,7 @@ func DecodeMethodExplicitBodyUserResultMultipleViewResponse(decoder func(*http.R
 			}
 			p := NewMethodExplicitBodyUserResultMultipleViewResulttypemultipleviewsOK(&body, c)
 			view := resp.Header.Get("goa-view")
-			vres := &serviceexplicitbodyuserresultmultipleviewviews.Resulttypemultipleviews{p, view}
+			vres := &serviceexplicitbodyuserresultmultipleviewviews.Resulttypemultipleviews{Projected: p, View: view}
 			if err = serviceexplicitbodyuserresultmultipleviewviews.ValidateResulttypemultipleviews(vres); err != nil {
 				return nil, goahttp.ErrValidationError("ServiceExplicitBodyUserResultMultipleView", "MethodExplicitBodyUserResultMultipleView", err)
 			}
@@ -311,7 +311,7 @@ func DecodeMethodTagMultipleViewsResponse(decoder func(*http.Response) goahttp.D
 			tmp := "value"
 			p.B = &tmp
 			view := resp.Header.Get("goa-view")
-			vres := &servicetagmultipleviewsviews.Resulttypemultipleviews{p, view}
+			vres := &servicetagmultipleviewsviews.Resulttypemultipleviews{Projected: p, View: view}
 			if err = servicetagmultipleviewsviews.ValidateResulttypemultipleviews(vres); err != nil {
 				return nil, goahttp.ErrValidationError("ServiceTagMultipleViews", "MethodTagMultipleViews", err)
 			}
@@ -328,7 +328,7 @@ func DecodeMethodTagMultipleViewsResponse(decoder func(*http.Response) goahttp.D
 			}
 			p := NewMethodTagMultipleViewsResulttypemultipleviewsOK(&body)
 			view := resp.Header.Get("goa-view")
-			vres := &servicetagmultipleviewsviews.Resulttypemultipleviews{p, view}
+			vres := &servicetagmultipleviewsviews.Resulttypemultipleviews{Projected: p, View: view}
 			if err = servicetagmultipleviewsviews.ValidateResulttypemultipleviews(vres); err != nil {
 				return nil, goahttp.ErrValidationError("ServiceTagMultipleViews", "MethodTagMultipleViews", err)
 			}
@@ -690,7 +690,7 @@ func DecodeMethodAResponse(decoder func(*http.Response) goahttp.Decoder, restore
 			}
 			p := NewMethodAAResultOK(required, optional, optionalButRequired)
 			view := resp.Header.Get("goa-view")
-			vres := &servicewithheadersblockviewedresultviews.AResult{p, view}
+			vres := &servicewithheadersblockviewedresultviews.AResult{Projected: p, View: view}
 			res := servicewithheadersblockviewedresult.NewAResult(vres)
 			return res, nil
 		default:
@@ -743,7 +743,7 @@ func DecodeMethodAResponse(decoder func(*http.Response) goahttp.Decoder, restore
 			}
 			p := NewMethodAAResultOK(required)
 			view := "default"
-			vres := &validateerrorresponsetypeviews.AResult{p, view}
+			vres := &validateerrorresponsetypeviews.AResult{Projected: p, View: view}
 			res := validateerrorresponsetype.NewAResult(vres)
 			return res, nil
 		case http.StatusBadRequest: