1

I've got a Scala def that takes parameters from an HTTP POST and parses the data. I'm pulling a "job" object from the database (the query was successful as verified in the debugger, and parameters are just as they need to be) and I'm trying to update that job object with the new parameters. However, trying to assign values are proving useless since the job object retains all original values.

All database objects are from Squeryl. Code below:

Edit: added class below and Job object to help give context in this Play! app

object Job {
  def updateFromParams(params:Params) = {
    val job = Job.get( params.get("job_id").toLong ).get

    val comments =  params.get("comments")
    val startTime = parseDateTime(params.get("start_time") + " " + params.get("date"))
    val endTime = parseDateTime(params.get("end_time") + " " + params.get("date"))
    val clientId = params.get("client_id").toLong
          val client = Client.get(clientId).get
    val name = params.get("job_name")
    val startAddressType = params.get("start_address_type")
    var startLocationId:Option[Long] = None
    val (startAddress, startCity, startProvince) = startAddressType match {
      case "client" => getClientAddress(clientId)
      case "custom" => (params.get("start_custom_address"),
                params.get("start_custom_city"),
                params.get("start_custom_province"))
      case id => {
      startLocationId = Some(id.toLong)
        getLocationAddress(startLocationId.get)
      }
    }

    job.comments ->  comments
    job.startTime -> startTime
    job.endTime -> endTime
    job.clientId -> clientId
    job.name -> name
    job.startAddressType -> startAddressType
    job.startAddress -> startAddress
    job.startCity -> startCity
    job.startProvince -> startProvince


    Job.update(job)
  }
}

I'm stumped because if I try job.name -> name nothing happens and if I try job.name = name then I get a Scala reassignment to val error. I get the same error when trying var name instead of val name.

It's obviously a syntax issue on my part, what's the proper way to handle this? Thanks!

More Info: if this helps, here's the Job class used in our Play! app:

class Job(
  val id: Long,

  @Column("name")
  val name: String,

  @Column("end_time")
  val endTime: Timestamp,

  @Column("start_time")
  val startTime: Timestamp,

  @Column("client_id")
  val clientId: Long,

  @Column("start_address_type")
  var startAddressType:String,

  @Column("start_address")
  var startAddress: String,
  /* LOTS MORE LIKE THIS */
) extends KeyedEntity[Long] {
}
crockpotveggies
  • 12,682
  • 12
  • 70
  • 140

2 Answers2

4

job.name is an immutable property, so you cannot change its value with job.name = name. You can see in the definition of the Job class that name is declared with val, meaning its value is immutable and can never be changed. The only way to "change" the values of the job object is to actually create a totally new instance and discard the old one. This is standard practice when dealing with immutable objects.

Changing your local name from val to var won't matter, since you are only reading the value of that variable.

Dan Simon
  • 12,891
  • 3
  • 49
  • 55
  • Interesting, thanks for fully explaining everything! I was having difficulty connecting the class to the problem. I changed the class and now it works! – crockpotveggies Feb 13 '12 at 20:37
0

val are immutable, in fat the whole Job class is immutable (since all fields are).

What could be done is to create a case class JobW and a bit of pimping to allow the use of copy. That said:

class Job(val id:Long, val name:String) {}

case class JobW(override val id:Long, override val name:String) extends Job(id, name){
  def ok:String = name + id
}

implicit def wrapJob(job:Job):JobW = JobW(job.id, job.name)

val job:Job = new Job(2L, "blah")

println(job.ok)

println(job.copy(name="Blob"))

What I've done, is to wrap a (spimplified for the exercise) Job into a case class wrapper, and define the implicit conversion.

Using this implicit conversion (what is called pimping), you'll have access to the ok method but also the copy one.

The copy method is an injected one on case classes, that takes as much arguments as the case class as fields and produces a new instance of the case class.

So you have now the ability to change only one value of you class, very simply I mean, and retrieve an new object (as functional programming arges for immutability).

Andy Petrella
  • 4,345
  • 26
  • 29