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