I didn't yet look at your code too closely, but the idea is that the "field" 
that represents the relationship implements Buffer, so you can add, remove, and 
iterate its elements, which are the other side of the relationship. These 
changes are remembered until you call save, when they are acted on.


-------------------------------------
glenn<[email protected]> wrote:


Naftoli,

I set up my mapper to use your new ManyToMany trait, but I'm not sure
how exactly to use it in a snippet or  view.

Here's what I have so far, a User, Role and UserRole for my model
classes:

class Role extends LongKeyedMapper[Role] with IdPK {

  def getSingleton = Role

  object name extends MappedPoliteString(this, 50) {
    override def setFilter = notNull _ :: trim _ :: super.setFilter
  }
}


class UserRole extends LongKeyedMapper[UserRole] with IdPK {
  def getSingleton = UserRole

  object role extends MappedLongForeignKey(this, Role){
    override def dbIndexed_? = true
  }

  object user extends MappedLongForeignKey(this,User) {
    override def dbIndexed_? = true
  }
}

class User extends MegaProtoUser[User] with ManyToMany[UserRole, Role]
{
  def getSingleton = User // what's the "meta" server

  // define an additional field for a personal essay
  object textArea extends MappedTextarea(this, 2048) {
    override def textareaRows  = 10
    override def textareaCols = 50
    override def displayName = "Personal Essay"
  }

  object role extends MappedManyToMany(UserRole, this, Role)


}

and their corresponding singleton objects.

In the past, without the ManyToMany trait, I would do this in User
object

override def editXhtml(user: User) = {
    (<form method="post" action={S.uri}>
        <table><tr><td colspan="2">{S.??("edit")}</td></tr>
          {localForm(user, true)}
          <tr><td>Roles</td><td><user:roles/></td></tr>
          <tr><td>&nbsp;</td><td><user:submit/></td></tr>
          <tr><td><a href={changePasswordPath.mkString("/", "/",
"")}
                 >{S.??("change.password")}</a></td></tr>
        </table>


     </form>)
  }

and bind this with the following to show the roles for a particular
user as a comma delimited string.

def innerEdit = User.isa_?("admin") match {
      case true => bind("user", editXhtml(theUser),
                         "roles" -> text(roles,
doRolesAndSubmit),
                         "submit" -> SHtml.submit(S.??("edit"),
testEdit _))
      case false => bind("user", editXhtml(theUser),
                         "roles" ->
theUser.showRoles,
                         "submit" -> SHtml.submit(S.??("edit"),
testEdit _))
      }

here roles is defined as

var roles = theUser.roles.map(_.name.is).mkString(", ")

Do you have an example of how to achieve something similar with your
new ManyToMany and MappedManyToMany code?
Appreciate any help you can give me.

Thanks,

Glenn...



On Jul 28, 3:05 pm, Naftoli Gugenheim <[email protected]> wrote:
> Did you update your source jar? Try deleting it from your repository just to 
> be sure, then mvn dependency:sources etc.
> Either way you can access the source on github.
>
> -------------------------------------
>
> glenn<[email protected]> wrote:
>
> Naftoli,
>
> The ManyToMany class is in the new lift-mapper jar, but the source is
> not available in 1.1-SNAPSHOT-sources. Could you provide?
> Thanks,
>
> Glenn...
>
> On Jul 27, 3:50 pm, Naftoli Gugenheim <[email protected]> wrote:
>
> > I committed it last night, so I think it should be there.
> > To use many-to-many, simply mix ManyToMany to your mapper, then create a 
> > MappedManyToMany field like any other field. See the scaladocs for 
> > specifics.
> > Then in your view you can use the field like a collection, e.g., remove an 
> > element with -=, and save the mapper to apply the changes.
>
> > -------------------------------------
>
> > glenn<[email protected]> wrote:
>
> > Sounds great. I've been using hacks such as adding code like this to
> > my mapper classes just to create a Many-to-Many
> > relationship between say, tag and content tables (using an
> > intermediary ContentTag table). Similarly, I've done User/Roles
> > relationships.
>
> >  private object _dbTags extends HasManyThrough(this, Tag, ContentTag,
> > ContentTag.content, ContentTag.tag)
>
> >   private[model] var _tags : List[Tag] = _
>
> >   private val locker = new Object
>
> >   def tags : List[Tag] = locker.synchronized {
> >     if(_tags eq null){
> >       _tags = _dbTags()
> >     }
> >     _tags
> >   }
>
> >   def tags(newTags:String) = locker.synchronized {
> >     _tags = newTags.roboSplit(",").map(Tag.byName(_))
> >     this
> >   }
>
> >   def tags(newTags:List[Tag]) = locker.synchronized {
> >     _tags = newTags
> >     this
> >   }
>
> >   def tagsToo:List[Tag] = ContentTag.findAll(By(ContentTag.content,
> > this.id)).map(_.tag.obj.open_!)
>
> >   def showTags = Text(tags.map(_.name.is).mkString(", "))
>
> > But, then I have to add code like this to the meta-mapper objects:
>
> >  def addTags(entry: Content) {
> >     if(entry._tags ne null){
> >        entry._tags.foreach(ContentTag.join(_, entry))
> >     }
> >   }
>
> >   def delTags(entry:Content) =
> >     ContentTag.findAll(By(ContentTag.content, entry)).foreach
> > (_.delete_!)
>
> > It's not very pretty. Nor easy to duplicate.
>
> > I hope your new code is considerably less messy.
>
> > Is it in the repo-snapshot repository yet.
>
> > On Jul 27, 12:57 pm, Naftoli Gugenheim <[email protected]> wrote:
>
> > > I committed some code last night, which can help building mapper-based 
> > > view snippets, with G-d's help. It includes the following classes:
> > > (1-2) net.liftweb.mapper.OneToMany, ManyToMany: Gives a more 
> > > object-oriented approach to managing related entites. You can manage the 
> > > many side of a 1-n and n-n as a mutable collection of children, and the 
> > > parent of a child can be set directly, instead of via its id. And the 
> > > children are not saved to the database when you add them until you call 
> > > save on it or its parent, nor deleted when you remove tem until you call 
> > > delete_!, which is very helpful when you need to keep track of 
> > > adds/removes through multiple requests. For example, if you are 
> > > displaying a list and you can click delete, but it shouldn't be 
> > > permanently deleted until you click save.
> > > There is a new package, ...mapper.view, which contains a number of 
> > > utilities for mapper-based views:
> > > (3-4) ModelView and ModelSnippet provide a number of building blocks for 
> > > views that are too complex to CRUDify. Inherit ModelSnippet (which 
> > > extends StatefulSnippet) and wrap your entities in ModelView (view is 
> > > used in the sense of a wrapper).
> > > (5) Util provides some more building blocks that just be imported, 
> > > without needing a ModelSnippet context.
> > > (6-7) Paginator makes it easy to create paginated, user sortable 
> > > listings. You can use PaginatedSnippet instead of ModelSnippet to help.
> > > (8-10) ItemsList lets you manage a list of entities with pending 
> > > additions and deletions. It's used by TableEditor, which is a very easy 
> > > to use and customizable snippet to edit tables directly. It's useful for 
> > > editing short lists, e.g., a lookup table like cities. Don't forget to 
> > > register the table in Boot.
> > > (11) Then there's the experimental FormProcessor, if you need your form 
> > > to be processed in one block instead of separate closures, e.g., to 
> > > surround with try.
> > > (12) Also experimental is sitemap.XmlMenu which lets you write menus in 
> > > xml.
> > > (13) I may add CaseEnum, which lets you write case classes that 
> > > automatically double as an Enumeration.
> > > Questions, comments, suggestions, and constructive criticism are more 
> > > than welcome!
> > > Thanks.


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to