Repository: gobuffalo/buffalo
Pull request #2072 (2020-12-24 00:23:57)

Development


Patch:
diff --git a/Dockerfile.build b/Dockerfile.build
index 0f83c15d..e9cd1259 100644
--- a/Dockerfile.build
+++ b/Dockerfile.build
@@ -32,7 +32,7 @@ RUN npm install -g --no-progress yarn \
 # Install golangci
 RUN curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.24.0
 # Installing buffalo binary
-RUN curl -sf https://gobinaries.com/gobuffalo/buffalo/buffalo@v0.16.16 | sh 
+RUN curl -sf https://gobinaries.com/gobuffalo/buffalo/buffalo@v0.16.18 | sh 
 RUN go get github.com/gobuffalo/buffalo-pop/v2
 RUN buffalo version
 
diff --git a/Dockerfile.slim.build b/Dockerfile.slim.build
index 4badb0df..10097ddd 100644
--- a/Dockerfile.slim.build
+++ b/Dockerfile.slim.build
@@ -17,7 +17,7 @@ RUN npm i -g --no-progress yarn \
     && yarn config set yarn-offline-mirror-pruning true
 
 # Pulling docker binary from releases
-RUN curl -sf https://gobinaries.com/gobuffalo/buffalo/buffalo@v0.16.16 | sh 
+RUN curl -sf https://gobinaries.com/gobuffalo/buffalo/buffalo@v0.16.18 | sh 
 RUN go get github.com/gobuffalo/buffalo-pop/v2
 RUN buffalo version
 
diff --git a/render/template.go b/render/template.go
index 7d2daf8b..b67641d3 100644
--- a/render/template.go
+++ b/render/template.go
@@ -119,29 +119,7 @@ func (s templateRenderer) exec(name string, data Data) (template.HTML, error) {
 	name = fixExtension(name, ct)
 
 	// Try to use localized version
-	templateName := name
-	if languages, ok := data["languages"].([]string); ok {
-		ll := len(languages)
-		if ll > 0 {
-			// Default language is the last in the list
-			defaultLanguage := languages[ll-1]
-			ext := filepath.Ext(name)
-			rawName := strings.TrimSuffix(name, ext)
-
-			for _, l := range languages {
-				var candidateName string
-				if l == defaultLanguage {
-					break
-				}
-				candidateName = rawName + "." + strings.ToLower(l) + ext
-				if _, err := s.resolve(candidateName); err == nil {
-					// Replace name with the existing suffixed version
-					templateName = candidateName
-					break
-				}
-			}
-		}
-	}
+	templateName := s.localizedName(name, data)
 
 	// Set current_template to context
 	if _, ok := data["current_template"]; !ok {
@@ -158,7 +136,11 @@ func (s templateRenderer) exec(name string, data Data) (template.HTML, error) {
 	for k, v := range s.Helpers {
 		helpers[k] = v
 	}
-	helpers["partialFeeder"] = s.partialFeeder
+
+	// Allows to specify custom partialFeeder
+	if helpers["partialFeeder"] == nil {
+		helpers["partialFeeder"] = s.partialFeeder
+	}
 
 	helpers = s.addAssetsHelpers(helpers)
 
@@ -178,6 +160,37 @@ func (s templateRenderer) exec(name string, data Data) (template.HTML, error) {
 	return template.HTML(body), nil
 }
 
+func (s templateRenderer) localizedName(name string, data Data) string {
+	templateName := name
+
+	languages, ok := data["languages"].([]string)
+	if !ok || len(languages) == 0 {
+		return templateName
+	}
+
+	ll := len(languages)
+	// Default language is the last in the list
+	defaultLanguage := languages[ll-1]
+	ext := filepath.Ext(name)
+	rawName := strings.TrimSuffix(name, ext)
+
+	for _, l := range languages {
+		var candidateName string
+		if l == defaultLanguage {
+			break
+		}
+
+		candidateName = rawName + "." + strings.ToLower(l) + ext
+		if _, err := s.resolve(candidateName); err == nil {
+			// Replace name with the existing suffixed version
+			templateName = candidateName
+			break
+		}
+	}
+
+	return templateName
+}
+
 func (s templateRenderer) exts(name string) []string {
 	exts := []string{}
 	for {
diff --git a/response.go b/response.go
index 81f9c757..77ed0297 100644
--- a/response.go
+++ b/response.go
@@ -18,9 +18,18 @@ type Response struct {
 }
 
 // WriteHeader sets the status code for a response
-func (w *Response) WriteHeader(i int) {
-	w.Status = i
-	w.ResponseWriter.WriteHeader(i)
+func (w *Response) WriteHeader(code int) {
+	if code == w.Status {
+		return
+	}
+
+	if w.Status > 0 {
+		fmt.Printf("[WARNING] Headers were already written. Wanted to override status code %d with %d", w.Status, code)
+		return
+	}
+
+	w.Status = code
+	w.ResponseWriter.WriteHeader(code)
 }
 
 // Write the body of the response
diff --git a/runtime/version.go b/runtime/version.go
index 9ec0a5fa..8d41ab85 100644
--- a/runtime/version.go
+++ b/runtime/version.go
@@ -1,4 +1,4 @@
 package runtime
 
 // Version is the current version of the buffalo binary
-var Version = "v0.16.16"
+var Version = "v0.16.18"


Test patch:
diff --git a/render/partials_test.go b/render/partials_test.go
index 82420d04..d158ac9b 100644
--- a/render/partials_test.go
+++ b/render/partials_test.go
@@ -29,6 +29,39 @@ func Test_Template_Partial(t *testing.T) {
 	r.Equal("Foo > Mark", strings.TrimSpace(bb.String()))
 }
 
+func Test_Template_PartialCustomFeeder(t *testing.T) {
+	r := require.New(t)
+
+	box := packd.NewMemoryBox()
+	r.NoError(box.AddString("base.plush.html", `<%= partial("foo.plush.html") %>`))
+	r.NoError(box.AddString("_foo.plush.html", "other"))
+
+	e := NewEngine()
+	e.TemplatesBox = box
+
+	t.Run("Custom Feeder", func(t *testing.T) {
+		e.Helpers["partialFeeder"] = func(path string) (string, error) {
+			return "custom", nil
+		}
+
+		bb := &bytes.Buffer{}
+
+		re := e.HTML("base.plush.html")
+		r.NoError(re.Render(bb, Data{}))
+		r.Equal("custom", strings.TrimSpace(bb.String()))
+	})
+
+	t.Run("Default Feeder", func(t *testing.T) {
+		e.Helpers["partialFeeder"] = nil
+
+		bb := &bytes.Buffer{}
+
+		re := e.HTML("base.plush.html")
+		r.NoError(re.Render(bb, Data{}))
+		r.Equal("other", strings.TrimSpace(bb.String()))
+	})
+}
+
 func Test_Template_Partial_WithoutExtension(t *testing.T) {
 	r := require.New(t)
 
diff --git a/response_test.go b/response_test.go
new file mode 100644
index 00000000..1dbd60fe
--- /dev/null
+++ b/response_test.go
@@ -0,0 +1,22 @@
+package buffalo
+
+import (
+	"net/http"
+	"net/http/httptest"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func Test_Response_MultipleWrite(t *testing.T) {
+	r := require.New(t)
+	resWr := httptest.NewRecorder()
+	res := Response{
+		ResponseWriter: resWr,
+	}
+
+	res.WriteHeader(http.StatusOK)
+	res.WriteHeader(http.StatusInternalServerError)
+
+	r.Equal(res.Status, http.StatusOK)
+}