Code Monkey home page Code Monkey logo

skinny-framework / skinny-framework Goto Github PK

View Code? Open in Web Editor NEW
736.0 736.0 73.0 12.51 MB

:monorail: "Scala on Rails" - A full-stack web app framework for rapid development in Scala

Home Page: https://skinny-framework.github.io/

License: MIT License

Scala 69.79% JavaScript 25.77% CSS 0.01% Shell 1.63% CoffeeScript 0.04% HTML 0.42% Java 0.69% Batchfile 0.86% FreeMarker 0.04% Less 0.02% Sass 0.01% SCSS 0.01% Pug 0.40% Scaml 0.27% Mustache 0.07%
http-client mail oauth2-client orm scala validation web-framework

skinny-framework's Introduction

Skinny Framework

CI Build Maven Central

Skinny is a full-stack web app framework to build Servlet applications.

To put it simply, Skinny framework's concept is Scala on Rails. Skinny is highly inspired by Ruby on Rails and it is optimized for sustainable productivity for ordinary Servlet-based app development.

Logo

See the website in detail.

https://skinny-framework.github.io/

Global skinny script via Homebrew

brew update && brew install skinny

Try Skinny Framework now!

Download latest skinny-blank-app.zip and unzip it, then just run ./skinny command on your terminal. That’s all!

If you’re a Windows user, don’t worry. Use skinny.bat on cmd.exe instead.

https://github.com/skinny-framework/skinny-framework/releases

Under The MIT License

(The MIT License)

Copyright (c) skinny-framework.org

skinny-framework's People

Contributors

arakaki avatar argius avatar bitdeli-chef avatar blackprincess avatar cb372 avatar dakatsuka avatar etoriet avatar falmp avatar gakuzzzz avatar grimrose avatar kamekoopa avatar kazuhira-r avatar kuchitama avatar lloydmeta avatar mohno007 avatar namutaka avatar ponkotuy avatar riverpuro avatar roundrop avatar seratch avatar tkawachi avatar tok12 avatar tototoshi avatar tsukaby avatar xuwei-k avatar yuba avatar yuroyoro avatar zaneli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

skinny-framework's Issues

RequestScopeFeature#set should not extract optional values

Currently, using set method extracts optional values if exists and skip appending if absent.

class SomeController extends SkinnyController {
  def index = {
    set("name" -> Option("Alice"))
    render("/some/index")
  }
}

The name is passed as a String value in view templates.

<%@val name: String %>

The name should be passed as a Option[String] value in view templates.

<%@val name: Option[String] %>

SkinnyORM API improvement

  • deprecate FinderFeature#countAll
  • add FinderFeature#count
  • FinderFeature#count with columns(both of Symbol and SQLSyntax?)
  • Rename QueryingFeature#count to QueryingFeature#countOnly
  • CalculationFeature#sum or something?

Merging params into single value easily

For instance, merging

Map("birthday_year" -> "2011", "birthday_month" -> "6", "birthday_day" -> "22")

into the following "birthday" value easily will be useful in many cases.

Map("birthday" -> "2011-06-22")

Too slow test execution

When Many controller tests are added, test execution takes long time. For example, 3 minutes for sbt example/test.

Actually this is not an issue of Skinny Framework (maybe Scalatra's issue). But we should investigate the cause and fix it if possible.

Join condition byDefaultEvenIfAssociated should be in the back for MySQL

The following code works fine with H2 database. However, it fails with MySQL...

build.sbt

libraryDependencies ++= Seq(
  "com.github.seratch" %% "skinny-orm" % "0.9.14",
  "com.h2database" %  "h2" % "1.3.173"
)

initialCommands := """import scalikejdbc._, SQLInterpolation._
Class.forName("org.h2.Driver")
ConnectionPool.singleton("jdbc:h2:mem:example", "sa", "sa")
DB autoCommit { implicit s =>
  sql"create table members   (id bigserial not null primary key, name varchar(255) not null, company_id bigint);".execute.apply()
  sql"create table companies (id bigserial not null primary key, name varchar(255) not null, country_id bigint);".execute.apply()
  sql"create table countries (id bigserial not null primary key, name varchar(255) not null);".execute.apply()
}
val countryId = Country.createWithAttributes('name -> "Japan")
val companyId = Company.createWithAttributes('name -> "CA Advance", 'countryId -> countryId)
val memberId = Member.createWithAttributes('name -> "Arakaki", 'companyId -> companyId)
"""

src/main/scala/models.scala

import org.joda.time._
import skinny._, orm._
import scalikejdbc._, SQLInterpolation._

case class Member(id: Long, name: String, companyId: Option[Long], company: Option[Company] = None)
case class Company(id: Long, name: String, countryId: Option[Long], country: Option[Country] = None)
case class Country(id: Long, name: String)

object Member extends SkinnyCRUDMapper[Member] {
  override val tableName = "members"
  override val defaultAlias = createAlias("m")
  belongsTo[Company](Company, (m, c) => m.copy(company = c)).byDefault
  def extract(rs: WrappedResultSet, m: ResultName[Member]) = new Member(
    rs.long(m.id), rs.string(m.name), rs.longOpt(m.companyId)
  )
}

object Company extends SkinnyCRUDMapper[Company] {
  override val tableName = "companies"
  override val defaultAlias = createAlias("cmp")
  innerJoinWithDefaults(Country, (m, c) => sqls.eq(m.countryId, c.id)).byDefaultEvenIfAssociated
  def extract(rs: WrappedResultSet, m: ResultName[Company]) = new Company(
    id = rs.long(m.id),
    name = rs.string(m.name),
    countryId = rs.longOpt(m.countryId),
    country = rs.longOpt(m.countryId).map(_ => Country(rs))
  )
}

object Country extends SkinnyCRUDMapper[Country] {
  override val tableName = "countries"
  override val defaultAlias = createAlias("cnt")
  def extract(rs: WrappedResultSet, m: ResultName[Country]) = new Country(
    rs.long(m.id), rs.string(m.name)
  )
}

SQL

OK

SELECT m.id           AS i_on_m, 
       m.name         AS n_on_m, 
       m.company_id   AS ci_on_m, 
       cnt.id         AS i_on_cnt, 
       cnt.name       AS n_on_cnt, 
       cmp.id         AS i_on_cmp, 
       cmp.name       AS n_on_cmp, 
       cmp.country_id AS ci_on_cmp 
FROM   members m 
       LEFT JOIN companies cmp 
              ON m.company_id = cmp.id 
       INNER JOIN countries cnt 
               ON cmp.country_id = cnt.id 
ORDER  BY m.id 

NG

SELECT m.id           AS i_on_m, 
       m.name         AS n_on_m, 
       m.company_id   AS ci_on_m, 
       cnt.id         AS i_on_cnt, 
       cnt.name       AS n_on_cnt, 
       cmp.id         AS i_on_cmp, 
       cmp.name       AS n_on_cmp, 
       cmp.country_id AS ci_on_cmp 
FROM   members m 
       INNER JOIN countries cnt 
               ON cmp.country_id = cnt.id 
       LEFT JOIN companies cmp 
              ON m.company_id = cmp.id 
ORDER  BY m.id 

indexUrl of SkinnyResource based Controller makes bad URL

For Example, following class exists.

class PostsController extends SkinnyResource {
  protectFromForgery()
  override def scalateExtension = "scaml"
  override def model = Post
  override def resourcesName = "posts"
  override def resourceName = "post"
// ...
}

url() method given query parameters makes bad URL.

url(FooController.indexUrl, "page" -> "1")  // => "/posts??page=1" 

/posts??page=1 is not parsed correctly.

SkinnyResource definition is

val indexUrl = get(s"${resourcesBasePath}/?")(showResources()).as('index)

Why does SkinnyResource define so ?

Template file missing in Deployed war file

In deployed war file, follwing code does not render template.

render("/root/index")

Because scalatra.scalate.ScalateSupport#findTemplate generates invalid filepath like /WEB-INF/views//root/index.html.ssp, it should be normailzed.

See this PR:
Scalate template path should be normalized by yuroyoro · Pull Request #335
scalatra/scalatra scalatra/scalatra#335

Add FactoryPal to skinny-framework stack

Hey,

I made a few months ago a library that was a port of FactoryGirl for Scala called FactoryPal. It uses Macros and Dynamic to be able to check at compile time that what you're defining is correct.

Maybe we can work together and incorporate that here.

Let me know your thoughts!

url not found when packaging

Even though it works fine in development mode, url is not available when packaging.

[info] Compiling 30 Scala sources to /Users/seratch/tmp/skinny-blank-app-standalone/build/target/scala-2.10/classes...
[error] /Users/seratch/tmp/skinny-blank-app-standalone/build/target/scala-2.10/src_managed/main/scalate/WEB-INF/views/members/_form_html_jade.scala:153: not found: value url
[error]                         url(MembersController.indexUrl)
[error]                         ^
[error] /Users/seratch/tmp/skinny-blank-app-standalone/build/target/scala-2.10/src_managed/main/scalate/WEB-INF/views/members/edit_html_jade.scala:33: not found: value url
[error]                         url(MembersController.updateUrl, "id" -> s.params.id.get.toString)
[error]                         ^
[error] /Users/seratch/tmp/skinny-blank-app-standalone/build/target/scala-2.10/src_managed/main/scalate/WEB-INF/views/members/index_html_jade.scala:52: not found: value url
[error]                                 url(MembersController.showUrl, "id" -> member.id.toString)
[error]                                 ^
[error] /Users/seratch/tmp/skinny-blank-app-standalone/build/target/scala-2.10/src_managed/main/scalate/WEB-INF/views/members/index_html_jade.scala:66: not found: value url
[error]                                 url(MembersController.editUrl, "id" -> member.id.toString)
[error]                                 ^
[error] /Users/seratch/tmp/skinny-blank-app-standalone/build/target/scala-2.10/src_managed/main/scalate/WEB-INF/views/members/index_html_jade.scala:89: not found: value url
[error]                                 url(MembersController.deleteUrl, "id" -> member.id.toString)
[error]                                 ^
[error] /Users/seratch/tmp/skinny-blank-app-standalone/build/target/scala-2.10/src_managed/main/scalate/WEB-INF/views/members/index_html_jade.scala:109: not found: value url
[error]                             url(MembersController.newUrl)
[error]                             ^
[error] /Users/seratch/tmp/skinny-blank-app-standalone/build/target/scala-2.10/src_managed/main/scalate/WEB-INF/views/members/new_html_jade.scala:33: not found: value url
[error]                         url(MembersController.createUrl)
[error]                         ^
[error] /Users/seratch/tmp/skinny-blank-app-standalone/build/target/scala-2.10/src_managed/main/scalate/WEB-INF/views/members/show_html_jade.scala:53: not found: value url
[error]                             url(MembersController.indexUrl)
[error]                             ^
[error] /Users/seratch/tmp/skinny-blank-app-standalone/build/target/scala-2.10/src_managed/main/scalate/WEB-INF/views/members/show_html_jade.scala:63: not found: value url
[error]                             url(MembersController.editUrl, "id" -> member.id.toString)
[error]                             ^
[error] /Users/seratch/tmp/skinny-blank-app-standalone/build/target/scala-2.10/src_managed/main/scalate/WEB-INF/views/members/show_html_jade.scala:86: not found: value url
[error]                             url(MembersController.deleteUrl, "id" -> member.id.toString)
[error]                             ^
[error] 10 errors found
[error] (build/compile:compile) Compilation failed

flash.get("notice") and flash.notice are inconsistent

flash.get("notice") and flash.notice return the different value to the argument of nested Option[T].

package skinny.controller

import org.scalatra.test.scalatest._
import org.scalatra.{ FlashMap => ScalatraFlash }

class FlashSpec extends ScalatraFlatSpec {

  behavior of "BeforeAterFeature"

  it should "wrap scalatra's flash" in {
    val scalatraFlash = new ScalatraFlash()
    scalatraFlash += ("name" -> "skinny")
    scalatraFlash += ("lang" -> Option("scala"))
    scalatraFlash += ("nil" -> Option(None))
    val flash = new Flash(scalatraFlash)

    flash.get("name") should be(Some("skinny"))
    flash.name should be(Some("skinny"))
    flash.get("namae") should be(None)
    flash.namae should be(None)

    flash.get("lung") should be(None)
    flash.lung should be(None)

    // which is right?
    flash.get("lang") should be(Some(Some("scala")))
    flash.lang should be(Some("scala"))

    // which is right?
    flash.get("nil") should be(Some(Some(None)))
    flash.nil should be(Some(None))
  }

}

findAll not working properly?

how is it possible?

> Index.countBy(sqls.isNull(i.deletedAt))
7
> Index.findAll(sqls.isNull(i.deletedAt))
only return one element

Handling Flyway migration failure

[error] (run-main) com.googlecode.flyway.core.api.FlywayException: Schema "PUBLIC" contains a failed migration to version 20140103151600 !
com.googlecode.flyway.core.api.FlywayException: Schema "PUBLIC" contains a failed migration to version 20140103151600 !
    at com.googlecode.flyway.core.command.DbMigrate$1.doInTransaction(DbMigrate.java:175)
    at com.googlecode.flyway.core.command.DbMigrate$1.doInTransaction(DbMigrate.java:135)
    at com.googlecode.flyway.core.util.jdbc.TransactionTemplate.execute(TransactionTemplate.java:72)
    at com.googlecode.flyway.core.command.DbMigrate.migrate(DbMigrate.java:135)
    at com.googlecode.flyway.core.Flyway$1.execute(Flyway.java:872)
    at com.googlecode.flyway.core.Flyway$1.execute(Flyway.java:819)
    at com.googlecode.flyway.core.Flyway.execute(Flyway.java:1200)
    at com.googlecode.flyway.core.Flyway.migrate(Flyway.java:819)
    at skinny.dbmigration.DBMigration$class.migrate(DBMigration.scala:42)
    at skinny.dbmigration.DBMigration$.migrate(DBMigration.scala:10)
    at skinny.task.TaskLauncher$$anonfun$8.apply(TaskLauncher.scala:28)
    at skinny.task.TaskLauncher$$anonfun$8.apply(TaskLauncher.scala:26)
    at skinny.task.TaskLauncher$$anonfun$main$2.apply(TaskLauncher.scala:46)

Official website & documentation

  • GitHub pages
  • skinnyframework.org or .com
  • documentation using GitHub wiki

document agenda

  • Getting started
  • skinny command
  • simple web app (ScalatraBootstrap -> Conroller -> View)
  • How to integerate ORM
  • assets precompilation
  • war packaging
  • Heroku deployment

Specifying database column type when scaffolding

I every time amend type by myself after running g scaffold because scaffold-generator doesn't support BigDecimal type.

i hope i to be able to do it as follows

g scaffold names name field1:BigDecimal:decimal(12,2) field2:String:text field3:Long

will create

create table names (
  id bigserial not null primary key,
  field1 decimal(12,2) not null,
  field2 text not null,
  field3 bigint not null,
  created_at timestamp not null,
  updated_at timestamp
)

Sass support

If SassCompiler runs completely on the JVM is ideal but it's very painful(resolving JRuby gems on sbt is impossible?).

  • Sass compilation
  • AssetsController support

View Helper API

Not sure yet.

  • Rails's way or Twirl's way
  • Form generation
  • ???

orm: select specific fields of model

i want so select specific field to query through find(or where)
e.g. i have Member model that has some fields like id, name, groupId, etc. i just want modify this

  def findAllByGroupId(groupId: Long)(implicit s: DBSession = autoSession): Seq[Member] = {
    findAllBy(sqls.eq(m.groupId, groupId))
  }

to just get Member id and names
there is no documentation about this

Number value without comma

Numeric param values have comma separators. For instance,

12345

will be the following in the text box.

12,345

really REST service

i want to implement web services that pass json, i have do nothing with templates

SkinnyResource extends (via SkinnyController) many traits including TemplateEngineFeature and ScalateTemplateEngineFeature
is that supposed to be so?

Avoidng OOMError(PermGen)

After re-compilation and reloading several times, we get OOMError (java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: PermGen space) and need to restart sbt.

This is a limitation of xsbt-web-plugin but what can we do?

Executable war packaging

New command such as skinny executable-package. This command should generate a war file which has main class to invoke embedded Jetty and some JVM options to cofigure app(env, port and etc.).

orm: parent/child assotiation

i'm trying to create a parent/children model: each record can have many children, and has one or no parent

case class Index(id: Long, name: String, desc: String,
                     parent: Option[Index] = None, children: Seq[Index] = Nil)


object Index extends SkinnyCRUDMapper[Index]{
  override def defaultAlias = createAlias("i")

  belongsTo[Index](Index, (i, p) => i.copy(parent = p))

  val children = hasMany[Index](Index, (i, c) => i.copy(c = c))
}

in the documentation, there is no hasMany example, it's not OK

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.