Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the Scala + sbt workflow equivalent of Ruby + Bundler with a Gemfile?

I'm having a good time learning Scala, but I'm having the hardest time grasping how to set up a development environment.

In Ruby

  • File hierarchy

    my_app/
      |
      +-- Gemfile
      +-- app.rb
    
  • Gemfile

    source :rubygems
    gem "mechanize"
    
  • app.rb

    require "mechanize"
    agent = Mechanize.new
    page = agent.get("http://google.com")
    
  • Install dependencies and run it

    $ bundle install
    $ ruby app.rb
    

What's the Scala equivalent with sbt?

I'm reading about sbt and how packages/imports/jar dependencies work in Java/Scala, but I can't seem to filter out the bare bones necessities.

  • What's the minimal file hierarchy to replicate the above with Scala?
  • Here's the Java Mechanize lib available on Maven: http://search.maven.org/#search|ga|1|mechanize
  • Once you run sbt and download the Mechanize dependencies, how to you discern the necessary import statements you need to get this to work?

    val agent = new MechanizeAgent
    val page: HtmlDocument = agent.get("http://www.google.com")
    

I got the above working in Eclipse by manually importing the .jars and then importing packages from the libraries until the compiler/runtime errors stopped and the agent worked. But that experience was discouraging and I've come here to repent.

Intent of this question: The Java ecosystem/workflow is overwhelming to me as someone that's used to Ruby's effortless, IDEless workflow. I think a bare bones equivalent would give me a place to start building upon.

Ideally, I'd like to get Scala development working with just Vim and the command line before becoming dependent on Eclipse.

like image 940
danneu Avatar asked Nov 28 '12 21:11

danneu


2 Answers

sbt uses a library called ivy to import projects from the main maven repository. There are a few repositories sbt is preconfigured to work with, including the main maven repository.

Once these libraries are "resolved" (downloaded to your computer and hooked up to your project), the eclipse plugin will create dependencies to each jar in the eclipse project generated.

Here is how you configure it.

sbt Managed Dependencies

http://www.scala-sbt.org/release/docs/Getting-Started/Basic-Def.html#adding-library-dependencies

Add a dependency in your project's build.sbt file. If you add a dependency that depends on a specific version of scala, use two %% between the group and artifact name. Don't forget to add an empty line between each command in your build.sbt file.

libraryDependencies += "com.gistlabs" % "mechanize" % "0.11.0"

libraryDependencies += "org.scalatest" %% "scalatest" % "1.6.1" % "test"

Update the dependencies by running the update command:

$ sbt update

sbt Eclipse Plugin

https://github.com/typesafehub/sbteclipse/wiki/Installing-sbteclipse

You can install the sbt eclipse plugin globally by creating a file at ~/.sbt/plugins/plugins.sbt and putting this line into it:

addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0")

Whenever you add or update a dependency, run the following command and refresh your eclipse project:

$ sbt eclipse
like image 150
Frederick F. Kautz IV Avatar answered Oct 13 '22 18:10

Frederick F. Kautz IV


I'd like to go a step farther than ffk's answer, do much more hand-holding, and actually provide the direct translation of the Ruby example to Scala + sbt.

  • File hierarchy

    Crawler/
      +- build.sbt
      +- src/
         +- main/
            +- scala/
               +- Crawler.scala
    
  • build.sbt

    libraryDependencies += "com.gistlabs" % "mechanize" % "0.11.0"
    
  • Crawler.scala

    import com.gistlabs.mechanize.MechanizeAgent
    import com.gistlabs.mechanize.document.Document
    
    object Crawler extends App {
      val agent = new MechanizeAgent
      val page: Document = agent.get("http://google.com")
    }
    
  • Install dependencies and run it

    $ sbt run
    

To make the project importable into Eclipse or IntelliJ, you need the sbteclipse-plugin or sbt-idea plugin. But rather than having to declare these plugins in every build.sbt for every new project, you can declare them in a global build.sbt:

// in ~/.sbt/plugins/build.sbt
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0")
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.2.0")

Then, back in your Scala app's root directory:

$ sbt eclipse
or
$ gen-idea

Afterwards, you should be able to open it in the respective IDE.

Note: Whenever you add dependencies in your build.sbt, you'll need to rerun the sbt eclipse/gen-idea command so the IDE can pick it up.

like image 41
danneu Avatar answered Oct 13 '22 19:10

danneu