#oh and for the coding i just followed the directions of the scripts and api im using lol
Explore tagged Tumblr posts
sheepboychibi · 4 months ago
Text
i made the silly some models!! :0
Tumblr media Tumblr media
19 notes · View notes
nullset2 · 8 years ago
Text
How to model Posts with Tags (Grails 3 example)
A common use case which I haven't seen covered elsewhere is how to model a Post to Tag association when developing a relational database-backed Application (whether of the Web persuasion or otherwise)
This comes in handy when developing software where you want to allow people to upload and share pieces of content (from here onwards referred to as Posts) associating those pieces of content with metadata for some kind of trend or reporting purpose (from here onwards referred to as Tags). For example: blog posts.
I want to share my technique in case anyone needs to do something similar, in this case, with Grails 3. However the knowledge disclosed here is applicable to any other way to structure your application.
Introduction
Now then, a quick refresher: Grails allows you to easily code an MVC stack using groovy, a (beautiful) language for the JVM, to develop an application.
By MVC stack I mean that your repository will have fully working pieces of logic related to the model, view and controller layers of web applications.
It may sound complicated for newbies, but all that I'm talking about is that by using grails we're strongly following a design principle called separation of concerns, which establishes that certain parts of your code should only have a single, certain, intended purpose.
The clear advantage of this is that it makes your systems layerized and easy to grok in the long term. It also helps replacing parts of your system for better parts (for example, a new, optimized templating engine in place of your old one, faster data structures, or a better ORM, to say the least)
Also, when combined with the convention-over-configuration school of thought that Grails and other such frameworks adhere to, this results in humongous productivity and an elevated level of agility in your response as a developer.
The Schema
So back on track: to model posts with tags, we need two models (which grails calls domain classes), one for Post, and one for Tag. Then, the relationship between both becomes obvious: whenever you publish a post, you can associate many (or no) tags to it. So then it is said that each tag can belong to many posts.
Remember you can get nice empty domain classes by using a command such as grails create-domain-class Post.
The way that I see it, each post should, to begin with, at least have a title and content, where the first one should be a string of sensible length, and the second should be something more robust (postgres has a text type which I like, and a tag should be defined by a name. We can add other fields in the database besides that for some housekeeping too :D
You may already be well knowledgeable that to associate one database-backed model to another (or, rather, to associate records on a relational database) in a many to many relation, you need something that is called a join table, which consists of a series of records constituted by two foreign keys, both pointing to the primary keys of their respective tables.
In our case we can determine a join table called post_tags which relates a post_id foreign key pointing at the posts table with a tag_id foreign key pointing at the tags table. Then, whenever you need your relationships you can simply query this table on the database.
This is a quick and dirty schema that describes this database:
The thing is, that with grails, getting this is a simple as expressing as coding your domain classes in a certain way:
package blog class Post { String title String content Date dateCreated Date lastUpdated static hasMany = [tags: Tag] static mapping = { content type: "text" } static constraints = { title maxSize: 255, blank: false content blank: false } }
package blog class Tag { String name Date dateCreated Date lastUpdated static belongsTo = Post static hasMany = [posts: Post] static constraints = { name maxSize: 30, blank: false, unique: true } String toString(){ name } }
Notice, in both cases, the presence of static hasMany and belongsTo class members. These link your two domain classes in a snap. The good thing is that grails will also know how to create the join table for both models and will indeed do it automatically on your database.
The view
So, assuming you have your domain classes in check now it's time to create nice views for your stuff.
If you scaffold your views and controllers with grails generate-all you will now notice that your create view for Post are now prepared with a hasMany record selector:
Which will send the ids of your selected options (on a computer you can ctrl-click the elements of the selector) to your controller, where GORM will process them into nice join table records, all automagically. In this way your Post domain will maintain itself updated with its associated Tags.
Again, this is all provided by the framework! Oh joy! Right?
Well, so what if you want to replace the multiselect with some other kind of UI element? Something that comes to mind is checkboxes. Checkboxes are a pretty natural way to tell your application that you want to add n different associated records to your Post, and simpler to use than the selector.
So to do that you can dig into your grails-app/views/post directory and let's isolate the code representing the model form for the Post domain into its own partial. The last few tags before closing longest-enclosing div will create checkmarks per each Tag you currently have on your database and will show them checked if and only if an association has already been persisted, and otherwise if the relationship is available but doesn't exist yet:
<%@ page import="blog.Post" %> <%@ page import="blog.Tag" %> <div class="fieldcontain ${hasErrors(bean: post, field: 'title', 'error')} "> <label for="title"> <g:message code="post.title.label" default="Title" /> </label> <g:textField name="title" value="${post.title}" /> </div> <div class="fieldcontain ${hasErrors(bean: post, field: 'content', 'error')} "> <label for="title"> <g:message code="post.content.label" default="Content" /> </label> <g:textArea name="content" value="${post.content}" rows="30" cols="160" class="big-textarea"/> </div> <div class="fieldcontain"> <g:each in="${Tag.list()}" var="tag"> <label>${tag.name}</label><g:checkBox name="tags" value="${tag.id}" checked="${post.tags.find { it.id == tag.id }}" /> </g:each> </div>
The partial should be saved to the same directory that the create.gsp file is saved to and its name should begin with an underscore, such as _form.gsp. Then you can just invoke the partial with a very simple directive on the create.gsp and edit.gsp templates with a very simple g:render statement: ``. If you're familiar with ruby on rails partials, this should come second nature, all nice and easy.
GSP?
A quick refresher on GSP: GSP stands for Groovy Server Pages and it's the name of the template engine for the Grails ecosystem. It's the Grails analogous of JSP, ERB, Jade, Haml, Slim, or whatever other templating engine you like. Through succint combination of binding of objects to view patterns, and by providing you the ability to compose views with the template engine by reusing smaller snippets of code over and over, you can instruct the grails runtime on how to produce really nice HTML documents on the fly whenever a user requests it. This takes very little time and is done very easily, and without having to write any heavy front-end code. This can work wonders for some apps, depending on the level of UI design and UX focus that you have. Some other apps may prefer to go for a SPA kind of approach and throw some fancy schmanzy javascript framework in there that consumes and provides data as JSON or XML documents from and to a RESTful or SOAP API, and those are very exciting domains of course, however just bear in mind that grails helps us solve those problems faster.
Bring it home
So finally after remembering about GSP, keeping in mind that there's plentiful documentation for GSP elsewhere and that any html tags beggining with g: are actual backend code that will get process by your runtime, we can form our partial such as this:
Where we're basically telling the backend to give us checked checkboxes for each record of Tag that corresponds to an already existing join_table record for posts to tags, and otherwise draw available checkboxes for all those who aren't.
And now not only should you have a kind of nicer post create form, but actual checkmarks in your code!
So, cool, right? you have a quick and dirty working blog which should had only taken you the most of an hour to pull off... I hope you like it and send me any questions you may have!
1 note · View note