github.com/lenfree/buffalo@v0.7.3-0.20170207163156-891616ea4064/buffalo/cmd/generate/action.go (about)

     1  package generate
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  
    11  	"github.com/markbates/gentronics"
    12  	"github.com/markbates/inflect"
    13  	"github.com/spf13/cobra"
    14  )
    15  
    16  var runningTests = false
    17  
    18  //ActionCmd is the cmd that generates actions.
    19  var ActionCmd = &cobra.Command{
    20  	Use:     "action [name] [actionName...]",
    21  	Aliases: []string{"a", "actions"},
    22  	Short:   "Generates new action(s)",
    23  	RunE: func(cmd *cobra.Command, args []string) error {
    24  		if len(args) < 2 {
    25  			return errors.New("you should provide action name and handler name at least")
    26  		}
    27  
    28  		if _, err := os.Stat("actions"); err != nil {
    29  			return errors.New("actions directory not found, ensure you're inside your buffalo folder")
    30  		}
    31  
    32  		name := args[0]
    33  		actions := args[1:]
    34  
    35  		data := gentronics.Data{
    36  			"filename":  inflect.Underscore(name),
    37  			"namespace": inflect.Camelize(name),
    38  		}
    39  
    40  		filePath := filepath.Join("actions", fmt.Sprintf("%v.go", data["filename"]))
    41  		actionsTemplate := buildActionsTemplate(filePath)
    42  		testFilePath := filepath.Join("actions", fmt.Sprintf("%v_test.go", data["filename"]))
    43  		testsTemplate := buildTestsTemplate(testFilePath)
    44  		actionsToAdd := findActionsToAdd(name, filePath, actions)
    45  		testsToAdd := findTestsToAdd(name, testFilePath, actions)
    46  
    47  		data["actions"] = actionsToAdd
    48  		data["tests"] = testsToAdd
    49  
    50  		g := gentronics.New()
    51  		g.Add(gentronics.NewFile(filepath.Join("actions", fmt.Sprintf("%s.go", data["filename"])), actionsTemplate))
    52  		g.Add(gentronics.NewFile(filepath.Join("actions", fmt.Sprintf("%s_test.go", data["filename"])), testsTemplate))
    53  		g.Add(&gentronics.Func{
    54  			Should: func(data gentronics.Data) bool { return true },
    55  			Runner: func(root string, data gentronics.Data) error {
    56  				routes := []string{}
    57  				for _, a := range actions {
    58  					routes = append(routes, fmt.Sprintf("app.GET(\"/%s/%s\", %s)", name, a, data["namespace"].(string)+inflect.Camelize(a)))
    59  				}
    60  				return addInsideAppBlock(routes...)
    61  			},
    62  		})
    63  		addTemplateFiles(actionsToAdd, data)
    64  
    65  		if !runningTests {
    66  			g.Add(Fmt)
    67  		}
    68  
    69  		return g.Run(".", data)
    70  	},
    71  }
    72  
    73  func buildActionsTemplate(filePath string) string {
    74  	actionsTemplate := rActionFileT
    75  	fileContents, err := ioutil.ReadFile(filePath)
    76  	if err == nil {
    77  		actionsTemplate = string(fileContents)
    78  	}
    79  
    80  	actionsTemplate = actionsTemplate + `
    81  {{#each actions as |action|}}
    82  // {{namespace}}{{camelize action}} default implementation.
    83  func {{namespace}}{{camelize action}}(c buffalo.Context) error {
    84  	return c.Render(200, r.HTML("{{filename}}/{{underscore action}}.html"))
    85  }
    86  {{/each}}`
    87  	return actionsTemplate
    88  }
    89  
    90  func buildTestsTemplate(filePath string) string {
    91  	testsTemplate := `package actions_test
    92  
    93  import (
    94  	"testing"
    95  
    96  	"github.com/stretchr/testify/require"
    97  )
    98  	`
    99  	fileContents, err := ioutil.ReadFile(filePath)
   100  	if err == nil {
   101  		testsTemplate = string(fileContents)
   102  	}
   103  
   104  	testsTemplate = testsTemplate + `
   105  {{#each tests as |action|}}
   106  func Test_{{namespace}}_{{camelize action}}(t *testing.T) {
   107  	r := require.New(t)
   108  	r.Fail("Not Implemented!")
   109  }
   110  
   111  {{/each}}`
   112  	return testsTemplate
   113  }
   114  
   115  func addTemplateFiles(actionsToAdd []string, data gentronics.Data) {
   116  	for _, action := range actionsToAdd {
   117  		vg := gentronics.New()
   118  		viewPath := filepath.Join("templates", fmt.Sprintf("%s", data["filename"]), fmt.Sprintf("%s.html", inflect.Underscore(action)))
   119  		vg.Add(gentronics.NewFile(viewPath, rViewT))
   120  		vg.Run(".", gentronics.Data{
   121  			"namespace": data["namespace"],
   122  			"action":    inflect.Camelize(action),
   123  		})
   124  	}
   125  }
   126  
   127  func findActionsToAdd(name, path string, actions []string) []string {
   128  	fileContents, err := ioutil.ReadFile(path)
   129  	if err != nil {
   130  		fileContents = []byte("")
   131  	}
   132  
   133  	actionsToAdd := []string{}
   134  
   135  	for _, action := range actions {
   136  		funcSignature := fmt.Sprintf("func %s%s(c buffalo.Context) error", inflect.Camelize(name), inflect.Camelize(action))
   137  		if strings.Contains(string(fileContents), funcSignature) {
   138  			fmt.Printf("--> [warning] skipping %v%v since it already exists\n", inflect.Camelize(name), inflect.Camelize(action))
   139  			continue
   140  		}
   141  
   142  		actionsToAdd = append(actionsToAdd, action)
   143  	}
   144  
   145  	return actionsToAdd
   146  }
   147  
   148  func findTestsToAdd(name, path string, actions []string) []string {
   149  	fileContents, err := ioutil.ReadFile(path)
   150  	if err != nil {
   151  		fileContents = []byte("")
   152  	}
   153  
   154  	actionsToAdd := []string{}
   155  
   156  	for _, action := range actions {
   157  		funcSignature := fmt.Sprintf("func Test_%v_%v(c buffalo.Context) error", inflect.Camelize(name), inflect.Camelize(action))
   158  		if strings.Contains(string(fileContents), funcSignature) {
   159  			fmt.Printf("--> [warning] skipping Test_%v_%v since it already exists\n", inflect.Camelize(name), inflect.Camelize(action))
   160  			continue
   161  		}
   162  
   163  		actionsToAdd = append(actionsToAdd, action)
   164  	}
   165  
   166  	return actionsToAdd
   167  }
   168  
   169  const (
   170  	rActionFileT = `package actions
   171  import "github.com/gobuffalo/buffalo"`
   172  
   173  	rViewT       = `<h1>{{namespace}}#{{action}}</h1>`
   174  	rActionFuncT = `
   175  // {{namespace}}{{action}} default implementation.
   176  func {{namespace}}{{action}}(c buffalo.Context) error {
   177  	return c.Render(200, r.HTML("{{namespace_under}}/{{action_under}}.html"))
   178  }
   179  `
   180  )