| item |
| Stomach Contents: Structure - array
|
| 1 |
| Stomach Contents: Structure - struct |
| category |
| Stomach Contents: Structure - array
|
| 1 |
| Stomach Contents: Structure - struct |
| value |
clojure
|
|
| 2 |
| Stomach Contents: Structure - struct |
| value |
coldfusion
|
|
|
| description |
| Stomach Contents: Structure - struct |
| value |
<p>I'll be at <a href="http://cfobjective.com">cf.Objective()</a> this coming week, manning the <a href="http://getrailo.com">Railo</a> booth - we're Gold sponsors again! - and, for once, <strong>not speaking</strong>! However, if you want to learn more about <a href="http://clojure.org">Clojure</a>, especially how we're using it at <a href="http://worldsingles.com">World Singles</a> integrated into CFML, feel free to track me down and ask me about it. I'll be easy to find: I'll be at the Railo booth nearly all the time (during the day - I'm only planning to attend a handful of sessions; I expect other Railo team members will be attending many of the sessions - Christian Ready, Gert Franz and Mark Drew are all giving talks).<p>
<p>These are the only sessions I'm planning to attend, so you'll know where I am when I'm not at the Railo booth:</p>
<ul>
<li>The TDD List - Bill Shelton (Thursday, 10:15am)</li>
<li>Concurrency Zen - Marc Esher (Thursday, 1:45pm)</li>
<li>Railo 4Ever - Gert Franz / Mark Drew (Thursday, 4:15pm) - come and hear about all the cool new stuff in Railo 4.0!</li>
<li>Getting closure on Closures - Mark Mandel (Friday, 9:00am) - probably</li>
<li>CFML Mythbusters - Mark Drew (Friday, 1:45am) - probably</li>
<li>A/B Testing with Squabble - Mark Mandel (Saturday, 10:15am)</li>
</ul>
<p>I'll also probably go to the Birds of a Feather sessions: either CFML Frameworks or Agile (Friday, 7:00pm) and either CFML Code Editors or Ideas for the Future of CFML (Friday, 8:00pm).</p>
<p>Given the sessions I'm planning to attend, it won't surprise you that I'll also be more than happy to talk about those topics in a Clojure context too - clojure.test, the Expectations framework and the autoexpect continuous testing tool, generative testing; concurrency the easy way (in a side-effect free functional language); closures and what a functional language brings to the table!</p>
<p>See y'all in Minneapolis!</p>
|
|
| guid |
| Stomach Contents: Structure - struct |
| isPermaLink |
NO
|
| value |
http://corfield.org/blog/post.cfm/clojure-at-cf-objective
|
|
| link |
http://corfield.org/blog/post.cfm/clojure-at-cf-objective
|
| pubDate |
Sat, 12 May 2012 20:52:37 GMT
|
| title |
Clojure at cf.Objective()?
|
|
| 2 |
| Stomach Contents: Structure - struct |
| category |
| Stomach Contents: Structure - array
|
| 1 |
| Stomach Contents: Structure - struct |
| value |
clojure
|
|
| 2 |
| Stomach Contents: Structure - struct |
| value |
coldfusion
|
|
|
| description |
| Stomach Contents: Structure - struct |
| value |
<p>Your application is live but it isn't quite behaving the way you
expect - what do you do? You'd like to instrument the code, you'd
like to be able to run parts of your production code in the live
environment and look at the output, you might even like to replace
functions with updated code. How can you do that?</p>
<p>With most languages, this would be very difficult. Lisp languages
tend to make this possible and Clojure makes this possible on the
JVM.</p>
<p>You can run Clojure on Heroku and they've recently published a great
<a href="https://devcenter.heroku.com/articles/debugging-clojure">article
about debugging an application remotely</a> using a REPL (Read Eval
Print Loop) over HTTP. At World Singles, we've necessarily taken a
slightly different tack. Our main web applications are built in CFML
(powered by the JBoss community project Railo) and we dynamically
load Clojure code for the model. We also have long-running processes
that are pure Clojure (which are not web applications). The approach
in the Heroku article won't work for us.</p>
<p>By simply making <tt>swank-clojure 1.4.2</tt> a dependency and
calling <tt>(swank.swank/start-server :host "0.0.0.0" :port
n)</tt>, you get a REPL over SLIME (Superior Lisp Interaction Mode
for Emacs) and therefore you can connect from your development
environment direct into your live, running application.</p>
<p>We don't have Swank running all the time. We can start and stop the
Swank server at will. When it is running, we can connect from Emacs
with <tt>M-x slime-connect</tt> and then specifying the server IP
address and port. At that point, we have a live connection from our
IDE (Emacs) directly into our running, production application, so we
can run database queries, execute code and even replace code in the
live image.</p>
<p>Whilst that might sound a little scary, it's also very empowering. You can
execute any function in your code base directly in the production
context. SQL queries (and updates) are the obvious first step but
any business logic functions are also accessible. You can either
type them into the REPL or from existing code with <tt>c-x c-e</tt>
which transfers code from an edit buffer across the REPL to the live
server.</p>
<p>This allows you to do full debugging in a live context,
investigating the data and behavior of your application. If you find
a bug, you can formulate new versions of the functions in your
application and then apply those definitions live as well.</p>
<p>Very few technologies provide you with this level of power. A power
that comes with commensurate responsibility - debug carefully young man!</p>
|
|
| guid |
| Stomach Contents: Structure - struct |
| isPermaLink |
NO
|
| value |
http://corfield.org/blog/post.cfm/remote-debugging
|
|
| link |
http://corfield.org/blog/post.cfm/remote-debugging
|
| pubDate |
Tue, 08 May 2012 07:38:12 GMT
|
| title |
Remote Debugging
|
|
| 3 |
| Stomach Contents: Structure - struct |
| category |
| Stomach Contents: Structure - array
|
| 1 |
| Stomach Contents: Structure - struct |
| value |
clojure
|
|
| 2 |
| Stomach Contents: Structure - struct |
| value |
fw1
|
|
|
| description |
| Stomach Contents: Structure - struct |
| value |
<p>With Clojure 1.4.0 available and Leiningen 2 in preview, I felt it was time to update <a href="https://github.com/seancorfield/fw1-clj">FW/1</a> and the <a href="https://github.com/seancorfield/fw1-template">FW/1 template</a> to have updated dependencies.</p>
<p>FW/1 now uses Clojure 1.4.0, Ring 1.0.2 and Enlive 1.0.0. The FW/1 template has been updated and verified for use with Leiningen 2 (as well as Leiningen 1.x).</p>
<p>Both FW/1 and the FW/1 template are now at version 0.1.0 and available from Clojars. See the README on the respective Github repos for more details.</p>
|
|
| guid |
| Stomach Contents: Structure - struct |
| isPermaLink |
NO
|
| value |
http://corfield.org/blog/post.cfm/fw-1-for-clojure-updated
|
|
| link |
http://corfield.org/blog/post.cfm/fw-1-for-clojure-updated
|
| pubDate |
Wed, 18 Apr 2012 06:42:43 GMT
|
| title |
FW/1 (for Clojure) Updated
|
|
| 4 |
| Stomach Contents: Structure - struct |
| category |
| Stomach Contents: Structure - array
|
| 1 |
| Stomach Contents: Structure - struct |
| value |
clojure
|
|
|
| description |
| Stomach Contents: Structure - struct |
| value |
<p>A very small maintenance release: thrown exceptions are automatically unwrapped so you should no longer need to catch a RuntimeException when you're trying to catch a SQLException!</p>
|
|
| guid |
| Stomach Contents: Structure - struct |
| isPermaLink |
NO
|
| value |
http://corfield.org/blog/post.cfm/clojure-java-jdbc-0-1-4
|
|
| link |
http://corfield.org/blog/post.cfm/clojure-java-jdbc-0-1-4
|
| pubDate |
Mon, 16 Apr 2012 04:57:44 GMT
|
| title |
clojure.java.jdbc 0.1.4
|
|
| 5 |
| Stomach Contents: Structure - struct |
| category |
| Stomach Contents: Structure - array
|
| 1 |
| Stomach Contents: Structure - struct |
| value |
clojure
|
|
|
| description |
| Stomach Contents: Structure - struct |
| value |
<p>Clojure 1.4.0 has been released and it includes <a href="https://github.com/clojure/clojure/blob/master/changes.md">several nice enhancements and some bug fixes</a>. Everyone will have their favorites but mine include (in no particular order):</p>
<ul>
<li>mapv and filterv (which return vectors) and reduce-kv (can treat a vector as a collection of indexed pairs)</li>
<li>require can take :refer and a list of symbols - or :all - so you no longer need to blanket 'use' a namespace</li>
<li>*compiler-options* so you can disable locals clearing to improve the debugging experience</li>
<li>= on char arguments, removing the reflection warning and improving performance</li>
<li>wrapping exceptions in RuntimeException no longer happens so you can catch the underlying exception more easily</li>
<li>syntactically broken tests using clojure.test/are no longer silently pass - this bit me with a patch submitted to CongoMongo!</li>
</ul>
<p>So, yes, it's a small release (I didn't mention the new reader literals - I'm not ready to use those yet but I'm sure some people will find them very useful). Planning for 1.5.0 has already started. This is all part of the plan to have more frequent, digestible releases of Clojure - now that the big breakage of the 1.2 => 1.3 transition is out of the way (changes to numerics; changes to contrib).</p>
<p>Hopefully, you were already testing your code against 1.4.0 builds? Now you can update your "lein multi" tests (or lein2 profiles) to test against 1.4.0 final and 1.5.0-master-SNAPSHOT!</p>
<p><a href="https://github.com/seancorfield/clj-time">clj-time</a> and <a href="https://github.com/aboekhoff/congomongo">congomongo</a> have both been updated to test against 1.2.1, 1.3.0, 1.4.0 and 1.5.0-master-SNAPSHOT. The next release of clj-time will be 0.4.0 since its main dependency has changed from 1.2.1 to 1.3.0 now.</p>
|
|
| guid |
| Stomach Contents: Structure - struct |
| isPermaLink |
NO
|
| value |
http://corfield.org/blog/post.cfm/clojure-1-4-0-clj-time-congomongo
|
|
| link |
http://corfield.org/blog/post.cfm/clojure-1-4-0-clj-time-congomongo
|
| pubDate |
Mon, 16 Apr 2012 00:59:37 GMT
|
| title |
Clojure 1.4.0, clj-time, congomongo
|
|
| 6 |
| Stomach Contents: Structure - struct |
| category |
| Stomach Contents: Structure - array
|
| 1 |
| Stomach Contents: Structure - struct |
| value |
coldfusion
|
|
|
| description |
| Stomach Contents: Structure - struct |
| value |
<p>Yesterday I posted that we're looking for a back end / data-centric developer, today we've posted a new req for a front end developer!</p>
<p>As before: World Singles is looking for a smart, motivated developer to join our small, fully distributed team of engineers, working on our multi-lingual, multi-tenant Internet dating platform.</p>
<p>This new job "involves a focus on UI/UX design, with the ability to realize it in HTML, CSS and Javascript. Design would need to be integrated in the CFML front end. The applicant will be required to design and implement front-end UIs within an existing ColdFusion application, as well as optimize them for maximum performance across different browsers and platforms."</p>
<p>For more details, and to apply, see our Craig's List post: <a href="http://bit.ly/worldsinglesuijob">http://bit.ly/worldsinglesuijob</a></p>
|
|
| guid |
| Stomach Contents: Structure - struct |
| isPermaLink |
NO
|
| value |
http://corfield.org/blog/post.cfm/world-singles-is-hiring-again
|
|
| link |
http://corfield.org/blog/post.cfm/world-singles-is-hiring-again
|
| pubDate |
Tue, 10 Apr 2012 21:56:00 GMT
|
| title |
World Singles is Hiring! Again!
|
|
| 7 |
| Stomach Contents: Structure - struct |
| category |
| Stomach Contents: Structure - array
|
| 1 |
| Stomach Contents: Structure - struct |
| value |
clojure
|
|
| 2 |
| Stomach Contents: Structure - struct |
| value |
coldbox
|
|
| 3 |
| Stomach Contents: Structure - struct |
| value |
coldfusion
|
|
| 4 |
| Stomach Contents: Structure - struct |
| value |
mongodb
|
|
| 5 |
| Stomach Contents: Structure - struct |
| value |
programming
|
|
|
| description |
| Stomach Contents: Structure - struct |
| value |
<p>World Singles is looking for a smart, motivated developer to join our small, fully distributed team of engineers, working on our multi-lingual, multi-tenant Internet dating platform. We're after someone with strong data management skills who can help us mine and analyze data in both MySQL and MongoDB, as well as help us leverage both more effectively. For more details: <a href="http://bit.ly/worldsinglesjob">http://bit.ly/worldsinglesjob</a></p>
<p>The World Singles code base is a blend of CFML and Clojure - this role would be mainly on the Clojure side of the house but the primary skills needed are MySQL / MongoDB.</p>
|
|
| guid |
| Stomach Contents: Structure - struct |
| isPermaLink |
NO
|
| value |
http://corfield.org/blog/post.cfm/world-singles-is-hiring
|
|
| link |
http://corfield.org/blog/post.cfm/world-singles-is-hiring
|
| pubDate |
Mon, 09 Apr 2012 21:24:34 GMT
|
| title |
World Singles is Hiring!
|
|
| 8 |
| Stomach Contents: Structure - struct |
| category |
| Stomach Contents: Structure - array
|
| 1 |
| Stomach Contents: Structure - struct |
| value |
clojure
|
|
|
| description |
| Stomach Contents: Structure - struct |
| value |
<p>When I wrote my summary of the conference, I forgot something very important: you can download nearly all of the <a href="https://github.com/strangeloop/clojurewest2012-slides">Clojure/West 2012 presentations</a> from github. Some of the files are quite large so you may not be able to simply view the raw PDF on github - you will probably have to clone the repo locally.</p>
|
|
| guid |
| Stomach Contents: Structure - struct |
| isPermaLink |
NO
|
| value |
http://corfield.org/blog/post.cfm/clojure-west-2012-presentations
|
|
| link |
http://corfield.org/blog/post.cfm/clojure-west-2012-presentations
|
| pubDate |
Tue, 27 Mar 2012 03:41:56 GMT
|
| title |
Clojure/West 2012 Presentations
|
|
| 9 |
| Stomach Contents: Structure - struct |
| category |
| Stomach Contents: Structure - array
|
| 1 |
| Stomach Contents: Structure - struct |
| value |
clojure
|
|
|
| description |
| Stomach Contents: Structure - struct |
| value |
<p>My team recently attended the
first <a href="http://clojurewest.org/">Clojure/West conference</a>
in San Jose, organized by Alex Miller, the man behind the incredible
<a href="https://thestrangeloop.com/">Strange Loop conference</a>.
Back in November, I attended the
second <a href="http://clojure-conj.org/">Clojure/conj
conference</a> (my first) with one of my team, who took the three
day Clojure training course. The training course was a bit of a
firehose and during one of the conference sessions, my colleague
asked me whether he was supposed to understand these (mostly very advanced)
talks. The conj is an inspiring event: a single track of sessions
that cover the leading edge of work in the Clojure community,
philosophical deep dives, technical exploration, possible future
directions.</p>
<p>Clojure/West, by contrast, had three tracks which focused on
production usage, core language / library concepts and some left
field stuff respectively. This was where the rubber met the road. My
colleagues and I greatly enjoyed the sessions and learned a lot from
them. All three of us attended a session on Friday morning
that introduced
the <a href="https://github.com/functional-koans/clojure-koans">Clojure
Koans</a> and that got us hooked. Between the Koans
and <a href="http://www.4clojure.com/">4clojure</a> there are plenty
of puzzles that you can use to learn Clojure. Phil Hagelberg ran a
90 minute swarm coding session on Saturday - and the Overtone guys
organized a hackfest on Friday evening. Lots of opportunities for
hands on Clojure coding with other eager developers.</p>
<p>Rich Hickey explained Datomic (I haven't gotten my head around it
yet). Craig Andera provided an excellent grounding on namespaces,
symbols and the whole "var" concept. BG gave an excellent overview
of "deftype" and associated concepts. Friday afternoon saw three
consecutive sessions on testing (load testing, generative testing
and continuous testing) which I enjoyed - and took a lot of notes.
We're already putting changes into effect at World Singles based on
those sessions! Carin Meier took us down the rabbit hole to see if
Alice could figure out what a monad is all about (when the videos of
the talks become available, you have to see this one!). Richard
Gabriel closed out Friday's sessions with a philosophical look at
when engineering and (computer) science started to walk along
separate paths (I loved this talk but I don't think it was
everybody's cup of tea).</p>
<p>Bradford Cross kicked off Saturday with a tale of high performance
Clojure. Allen Rohner told us how painful it was to mix JRuby and
Clojure (I was particularly interested because of our work at World
Singles integrating Clojure into another dynamic scripting language
on the JVM - CFML, using Railo). Colin Jones gave a
thought-provoking analysis of how to apply OO's "SOLID" principles
to Clojure / functional programming. After lunch I talked briefly
about how World Singles is using Clojure (and why it helps us), then
I took a break to discuss libraries, tooling and community in the
hallway. Those hallway discussions lasted longer than I expected so
I only caught the last session of the conference: Stuart Halloway
shared his experiences creating straightforward solutions to large
scale problems - in the context of developing Datomic, taking a
data-centric approach has lead to clear, simple designs.</p>
<p>And that was just the sessions that I attended. My colleagues
attended some of the same sessions and several other sessions. They
were equally positive about the sessions they attended. The
conference proved to be great value for all of us, learning as
beginners and intermediate developers. My takeaway from the
conference is that the Clojure ecosystem is expanding, the community
is growing and lots of people are successfully tackling a wide
variety of real world problems with Clojure. And that's great news!</p>
<p>The highlight of the conference for me was absolutely Carin Meier's
talk on monads (and writing desks). Hugely entertaining and
creative, as well as educational, she took a really gnarly topic and
made it engaging and fun. I think I might finally understand monads!</p>
|
|
| guid |
| Stomach Contents: Structure - struct |
| isPermaLink |
NO
|
| value |
http://corfield.org/blog/post.cfm/summary-clojure-west-2012
|
|
| link |
http://corfield.org/blog/post.cfm/summary-clojure-west-2012
|
| pubDate |
Fri, 23 Mar 2012 07:03:01 GMT
|
| title |
(summary :Clojure/West 2012)
|
|
| 10 |
| Stomach Contents: Structure - struct |
| category |
| Stomach Contents: Structure - array
|
| 1 |
| Stomach Contents: Structure - struct |
| value |
cfobjective
|
|
| 2 |
| Stomach Contents: Structure - struct |
| value |
coldfusion
|
|
|
| description |
| Stomach Contents: Structure - struct |
| value |
<p>I've attended every cf.Objective() since the first one in 2006.
That
first <a href="http://corfield.org/blog/post.cfm/cfObjective__Wow">cf.Objective()
was awesome</a>! Every one since has also been awesome. Since the
demise of CFUnited, cf.Objective() is the biggest CFML event on the
calendar. It offers the best CFML content in the world - and these
days it offers a lot more than CFML - and it offers a unique
combination of well-known speakers and new voices, something the
conference has always prided itself on.</p>
<p>So why should you attend this particular year? Every year, our
world of web development moves forward at what sometimes may seem
like an ever-increasing pace. This is reflected in the sessions
every year at cf.Objective(). This year sees an increased focus on
JavaScript with topics covering Node.js, Angular, jQuery Mobile,
Bootstrap, performance and testing. Even in the CFML topics, we're
seeing an increased focus on automation, performance and testing as
our community grows. cf.Objective() has always tried to offer
material for intermediate and advanced developers and this year we
have sessions on concurrency, collaborative code review, A/B
testing, advanced scalability and caching techniques. Another big
plus this year is the return of Adobe as platinum sponsor with
several sessions talking about "Zeus" - ColdFusion 10 - which is
currently in public beta.</p>
<p>cf.Objective() is all about helping you "up your game", to become a
better developer. That's why you should attend - to become a better
developer, to learn about new techniques and new technology.</p>
<p>This year we have ColdFusion 10 and Railo 4 and a lot of CFML
developers working across multiple technologies. cf.Objective() will
cover all of that so, if you aren't already registered, head over to
the <a href="http://www.cfobjective.com/">cf.Objective() website</a>
and get yourself signed up - it'll do you, and your career, a power
of good!</p>
|
|
| guid |
| Stomach Contents: Structure - struct |
| isPermaLink |
NO
|
| value |
http://corfield.org/blog/post.cfm/cf-objective-2012-why-you-should-attend
|
|
| link |
http://corfield.org/blog/post.cfm/cf-objective-2012-why-you-should-attend
|
| pubDate |
Fri, 23 Mar 2012 05:00:06 GMT
|
| title |
cf.Objective() 2012 - Why You Should Attend
|
|
| 11 |
| Stomach Contents: Structure - struct |
| category |
| Stomach Contents: Structure - array
|
| 1 |
| Stomach Contents: Structure - struct |
| value |
clojure
|
|
|
| description |
| Stomach Contents: Structure - struct |
| value |
<p><a href="https://github.com/clojure/java.jdbc">clojure.java.jdbc</a> 0.1.3 has been released. This includes support for SQLite 3 and improves support for Microsoft SQL Server, as well as a bug fix for prepared statements and some documentation improvements.</p>
<ul>
<li>Release 0.1.3 on 2012-02-29
<ul>
<li>Fix generated keys inside transactions for SQLite3 <a href="http://dev.clojure.org/jira/browse/JDBC-26">JDBC-26</a>
</li>
</ul>
</li>
<li>Release 0.1.2 on 2012-02-29
<ul>
<li>Handle prepared statement params correctly <a href="http://dev.clojure.org/jira/browse/JDBC-23">JDBC-23</a>
</li>
<li>Add support for SQLite3 <a href="http://dev.clojure.org/jira/browse/JDBC-26">JDBC-26</a>
</li>
<li>Replace replicate (deprecated) with repeat <a href="http://dev.clojure.org/jira/browse/JDBC-27">JDBC-27</a>
</li>
<li>Ensure MS SQL Server passes tests with both Microsoft and jTDS drivers</li>
<li>Build server now tests derby, hsqldb and sqlite by default</li>
<li>Update README per Stuart Sierra's outline for contrib projects</li>
</ul>
</li>
</ul>
|
|
| guid |
| Stomach Contents: Structure - struct |
| isPermaLink |
NO
|
| value |
http://corfield.org/blog/post.cfm/clojure-java-jdbc-0-1-3
|
|
| link |
http://corfield.org/blog/post.cfm/clojure-java-jdbc-0-1-3
|
| pubDate |
Thu, 01 Mar 2012 21:52:07 GMT
|
| title |
clojure.java.jdbc 0.1.3
|
|
| 12 |
| Stomach Contents: Structure - struct |
| category |
| Stomach Contents: Structure - array
|
| 1 |
| Stomach Contents: Structure - struct |
| value |
coldfusion
|
|
| 2 |
| Stomach Contents: Structure - struct |
| value |
fw1
|
|
| 3 |
| Stomach Contents: Structure - struct |
| value |
openbd
|
|
|
| description |
| Stomach Contents: Structure - struct |
| value |
<p>A problem was with reported running FW/1 1.2 on OpenBD 2.0.2. It turned out to be a bug in how OpenBD resolves Java method calls and it only manifests in two of the example Application.cfc files (not in the framework itself). You can now <a href="https://github.com/seancorfield/fw1/tags">download v1.2.1.zip</a> which contains the updated examples. Note that the User Manager example has never run on OpenBD (and, obviously, the Flex test in the remoting example won't run either).</p>
<p>Further, the problem with <tt>onError()</tt> still seems to be present in OpenBD 2.0.2 so if your FW/1 application hits an exception and triggers <tt>onError()</tt>, it'll fail with a message about "Variable EXCEPTION does not exist". Just rename framework.cfc's <tt>onError()</tt> method to disable it's exception handling (you'll see there's a comment above that method explaining this long-standing problem).</p>
|
|
| guid |
| Stomach Contents: Structure - struct |
| isPermaLink |
NO
|
| value |
http://corfield.org/blog/post.cfm/fw-1-1-2-and-open-bluedragon
|
|
| link |
http://corfield.org/blog/post.cfm/fw-1-1-2-and-open-bluedragon
|
| pubDate |
Wed, 15 Feb 2012 03:25:29 GMT
|
| title |
FW/1 1.2 and Open BlueDragon
|
|
| 13 |
| Stomach Contents: Structure - struct |
| category |
| Stomach Contents: Structure - array
|
| 1 |
| Stomach Contents: Structure - struct |
| value |
clojure
|
|
| 2 |
| Stomach Contents: Structure - struct |
| value |
fw1
|
|
|
| description |
| Stomach Contents: Structure - struct |
| value |
<p>I was chatting with <a href="http://twitter.com/iorayne">@iorayne</a> a.k.a. Raynes (IRC) a.k.a. Anthony Grimes today in #leiningen about changes required for plugins in the upcoming Leiningen 2.0 release. I was interested in updating my <a href="https://github.com/seancorfield/lein-fw/">lein-fw1</a> plugin so it would work with both Leiningen 1.x and Leiningen 2.0. Raynes pointed out that lein-fw1 was really just a template - it generates new skeleton FW/1 projects - and that Leiningen 2.0 was incorporating his <a href="https://github.com/Raynes/lein-newnew">lein-newnew</a> plugin as the default 'new' task. He suggested I rewrite lein-fw1 as a template that would work with Leiningen 2.0 and, if you install the lein-newnew plugin for Leiningen 1.x, it will work with that too. The result is <a href="https://github.com/seancorfield/fw1-template/">fw1-template</a>. The usage instructions are on that Github page but it installs just like a regular Leiningen plugin (<tt>lein plugin install</tt>...) and if you already have lein-newnew installed, you're good to go. Since lein-newnew is part of the migration path for moving from Leiningen 1.x to 2.0, I'm declaring lein-fw1 deprecated and recommending folks use fw1-template instead (and, yes, use lein-newnew!).</p>
|
|
| guid |
| Stomach Contents: Structure - struct |
| isPermaLink |
NO
|
| value |
http://corfield.org/blog/post.cfm/another-option-for-fw-1
|
|
| link |
http://corfield.org/blog/post.cfm/another-option-for-fw-1
|
| pubDate |
Sun, 12 Feb 2012 03:16:57 GMT
|
| title |
Another option for FW/1
|
|
| 14 |
| Stomach Contents: Structure - struct |
| category |
| Stomach Contents: Structure - array
|
| 1 |
| Stomach Contents: Structure - struct |
| value |
clojure
|
|
| 2 |
| Stomach Contents: Structure - struct |
| value |
fw1
|
|
| 3 |
| Stomach Contents: Structure - struct |
| value |
jquery
|
|
|
| description |
| Stomach Contents: Structure - struct |
| value |
<p>About a week ago, I blogged
about <a href="http://corfield.org/entry/getting-started-with-clojurescript-and-fw-1">how
to get started with ClojureScript and FW/1</a> and I showed some
basic DOM manipulation functions that go down to the JavaScript
metal. In any real world project, you're not going to want to do
that - you'll want to leverage a battle-tested, industrial-strength library
for that... something like <a href="http://jquery.com">jQuery</a>
for example. Using an external JavaScript library with ClojureScript
isn't entirely straightforward, unfortunately, mostly due to how
names are exported and how the Google Closure compiler munges them
in its efforts to produce minified code.</p>
<p>Fortunately, <a href="https://github.com/ibdknox/">Chris
Granger</a> has created a number of projects to make
ClojureScript development easier and we're going to look at his
jQuery wrapper, jayq, in this post.</p>
<p>As before, I'm going to assume you've already
got <a href="https://github.com/technomancy/leiningen">Leiningen</a>
installed, along with
the <a href="https://github.com/seancorfield/fw1-template">FW/1
template</a> (which we installed in the previous blog post):</p>
<pre>
lein plugin install fw1-template 0.0.6
</pre>
<p>If you installed
the <a href="https://github.com/emezeske/lein-cljsbuild">lein-cljsbuild</a>
before, you'll want to upgrade it to the latest version (see the
note at the end
of this blog post for why!):</p>
<pre>
lein plugin uninstall lein-cljsbuild 0.0.11
lein plugin install lein-cljsbuild 0.0.12
</pre>
<p>We'll start by creating a skeleton FW/1 application and then add
jQuery to it:</p>
<pre>
lein new fw1 fw1jq
</pre>
<p>Drop into the new <strong>fw1jq</strong> folder, and
edit <strong>project.clj</strong> as before to add the ClojureScript
compilation magic:</p>
<pre>
:cljsbuild {
:source-path "src-cljs"
:compiler {
:output-to "src/fw1jq/assets/js/main.js"
:optimizations :whitespace
:pretty-print true}}
</pre>
<p>You also need to add a dependency for <strong>jayq</strong>:</p>
<pre>
[jayq "0.1.0-SNAPSHOT"]
</pre>
<p>For production usage, see the important caveat below about changing <strong>:optimizations</strong>!</p>
<p>Create
the <strong>src-cljs</strong> folder in the project and
an <strong>example</strong> subfolder:</p>
<pre>
mkdir -p src-cljs/example
</pre>
<p>Now we can start up FW/1 in one window:</p>
<pre>
PORT=8888 lein run
</pre>
<p>and then start up the ClojureScript compiler in another:</p>
<pre>
lein cljsbuild auto
</pre>
<p>Now
create <strong>src-cljs/example/core.cljs</strong> containing this
code:</p>
<pre>
(ns example.core
(:use [jayq.core :only [$ inner]]))
(defn ^:export play []
(let [foo ($ :#foo)
paras ($ :p)]
(inner foo "Hello")
(js/alert "ClojureScript says 'Boo!'")
(doseq [p paras] (inner p "Gone!"))))
</pre>
<p>When you save it, the ClojureScript compiler will go to work and
create <strong>main.js</strong> containing the compiled (to
JavaScript) version. This is very similar to our
previous <strong>example/core.cljs</strong> file but it now uses the
jQuery wrapper and functions instead of my custom DOM functions.
Note in particular that <strong>foo</strong> is bound to <tt>($
:#foo)</tt> which is the jQuery selector for an ID of "foo" - #foo
identifies an ID, .foo identifies a class and plain foo identifies a tag.</p>
<p>Now let's update the default view in our FW/1 application to call this
JavaScript.
Edit <strong>src/fw1jq/views/main/default.html</strong>. We'll add
these two lines to the bottom of the file, as before:</p>
<pre>
<p><a href=""
onclick="example.core.play(); return false;">
Surprise me</a>!</p>
<p id="foo"></p>
</pre>
<p>We've added an empty paragraph tag with an ID of "foo" and we've
added a clickable link that
calls <strong>example.core.play()</strong>, the function we defined
above. Now let's include jQuery and the generated JavaScript file:
edit <strong>src/fw1jq/layouts/main/default.html</strong> and add
the following lines between the <strong>link</strong> and the end of
the <strong>head</strong> section:</p>
<pre>
<script
src="http://code.jquery.com/jquery-1.7.1.min.js">
</script>
<script src="/assets/js/main.js"></script>
</pre>
<p>Visit the FW/1 app in your
browser: <a href="http://localhost:8888">http://localhost:8888</a>
(or, if you need to reload it, use <a href="http://localhost:8888?reload=secret">http://localhost:8888?reload=secret</a>)</p>
<p>Click <u>Surprise me</u> and you should see "Hello" appear below
that paragraph and then a JavaScript alert containing "ClojureScript
says 'Boo!'".
Click <strong>OK</strong> and you should see all four paragraphs
replaced with "Gone!". Success! <em>[Setting the foo element to
Hello doesn't seem to work on Safari for me but it works in Firefox
and Chrome - go figure!]</em></p>
<p>As before, if you edit views, layouts or controller code while Jetty is
running, simply
click <a href="http://localhost:8888?reload=secret">http://localhost:8888?reload=secret</a>
to
force FW/1 to reload the changes. If you edit the ClojureScript
files, the compiler will automatically regenerate the JavaScript so
just reload the page in the browser to load the new source.</p>
<p><strong>:optimizations</strong> - in the previous blog post, I
noted that you could change this to <strong>:advanced</strong> for
production usage (and change <strong>:pretty-print</strong>
to <strong>false</strong>). When you're using external JavaScript libraries,
there's an additional step! Because the Google Closure compiler
munges names that are not specifically declared for exporting, we
need to update our compiler options to include declarations for our
library:</p>
<pre>
:cljsbuild {
:source-path "src-cljs"
:compiler {
:output-to "src/fw1jq/assets/js/main.js"
:externs ["externs/jquery.js"]
:optimizations :advanced
:pretty-print false}}
</pre>
<p>The <strong>externs/jquery.js</strong> file is inside
the <strong>jayq</strong> JAR file and is loaded from your class
path automatically. After you've made these changes to
your <strong>project.clj</strong>, quit the ClojureScript compiler
process and run:</p>
<pre>
lein cljsbuild clean
lein cljsbuild auto
</pre>
<p>That will delete any generated files (including cached versions of
the jQuery wrapper etc) and then restart the compiler. It'll take a bit longer
to compile your ClojureScript now since it is running optimizations,
and the resulting <strong>main.js</strong> file will be much harder
to debug - but it will also be much, much smaller.</p>
<p><em>Note: it is important to upgrade the lein-cljsbuild plugin to 0.0.12
since that includes the necessary fixes for the externs file to be
picked up from the class path - if you try to do this with the
0.0.11 build, you'll have problems (which can be solved by manually
extracting the externs folder from the JAR file - but you're better
off just upgrading to the new plugin version!)</em></p>
|
|
| guid |
| Stomach Contents: Structure - struct |
| isPermaLink |
NO
|
| value |
http://corfield.org/blog/post.cfm/getting-started-with-clojurescript-and-jquery-and-fw-1
|
|
| link |
http://corfield.org/blog/post.cfm/getting-started-with-clojurescript-and-jquery-and-fw-1
|
| pubDate |
Sat, 11 Feb 2012 19:54:50 GMT
|
| title |
Getting Started with ClojureScript and jQuery (and FW/1)
|
|
| 15 |
| Stomach Contents: Structure - struct |
| category |
| Stomach Contents: Structure - array
|
| 1 |
| Stomach Contents: Structure - struct |
| value |
clojure
|
|
| 2 |
| Stomach Contents: Structure - struct |
| value |
fw1
|
|
|
| description |
| Stomach Contents: Structure - struct |
| value |
<p>There's been quite a bit of buzz
about <a href="http://clojure.com/blog/2011/07/22/introducing-clojurescript.html">ClojureScript</a>
since it's launch last July but it is a fast-moving target and a but
daunting to get started with. Fortunately, there's a
simple <a href="https://github.com/emezeske/lein-cljsbuild">Leiningen
plugin called lein-cljsbuild</a> that can make it pretty simple to
get up and running!</p>
<p>I'm going to assume you've already
got <a href="https://github.com/technomancy/leiningen">Leiningen</a>
installed so let's get a small
<a href="https://github.com/seancorfield/fw1-clj">FW/1</a>
application up and running and then add some ClojureScript to
it.</p>
<p>First off, we'll install
the <a href="https://github.com/seancorfield/fw1-template">Leiningen
template for FW/1</a> (assumes you have <a href="https://github.com/Raynes/lein-newnew">lein-newnew</a> installed):</p>
<pre>
lein plugin install fw1-template 0.0.6
</pre>
<p>Now let's create a skeleton FW/1 application:</p>
<pre>
lein new fw1 fw1cljs
</pre>
<p>If we drop into our new <strong>fw1cljs</strong> folder, we can
fire up our new application:</p>
<pre>
cd fw1cljs
PORT=8888 lein run
</pre>
<p>Once you see Jetty started on port 8888, you can visit the
application: <a href="http://localhost:8888">http://localhost:8888</a></p>
<p>You should see a bare bones "Welcome to FW/1" page - success!</p>
<p>Now we're going to add ClojureScript to our project. Kill the Jetty
process (press control-C in that terminal window to terminate
<strong>lein run</strong>) then edit
your <strong>project.clj</strong> file to add the following
lines (between the <strong>:dependencies</strong> block and the <strong>:main</strong>):</p>
<pre>
:cljsbuild {
:source-path "src-cljs"
:compiler {
:output-to "src/fw1cljs/assets/js/main.js"
:optimizations :whitespace
:pretty-print true}}
</pre>
<p>This setup is fine for development. When you're ready for
production, change the <strong>:optimizations</strong>
to <strong>:advanced</strong> and <strong>:pretty-print</strong>
to <strong>false</strong>. That will create a heavily optimized
and minified JavaScript file.</p>
<p>Install the cljsbuild plugin:</p>
<pre>
lein plugin install lein-cljsbuild 0.0.11
</pre>
<p>That will download a <em>lot</em> of stuff including ClojureScript
itself and the Google Closure "compiler". Now we can start the
compiler-watcher (in the <strong>fw1cljs</strong> folder):</p>
<pre>
lein cljsbuild auto
</pre>
<p>Leave that running. In another terminal window, we need to create
the <strong>src-cljs</strong> folder in the project and
an <strong>example</strong> subfolder:</p>
<pre>
mkdir -p src-cljs/example
</pre>
<p>Now we'll create <strong>src-cljs/example/util.cljs</strong>
containing this code:</p>
<pre>
(ns example.util)
(defn length [nodes] (. nodes -length))
(defn item [nodes n] (.item nodes n))
(defn as-seq [nodes]
(for [i (range (length nodes))] (item nodes i)))
(defn by-id [id]
(.getElementById js/document (name id)))
(defn by-tag [tag]
(as-seq
(.getElementsByTagName js/document (name tag))))
(defn html [dom] (. dom -innerHTML))
(defn set-html! [dom content]
(set! (. dom -innerHTML) content))
</pre>
<p>When you save that file, you'll see the ClojureScript compiler
spring into life and compile it
to <strong>src/fw1cljs/assets/js/main.js</strong>. I'll walk thru
this code in a minute but for now we'll
create <strong>src-cljs/example/core.cljs</strong> containing this
code:</p>
<pre>
(ns example.core
(:use [example.util :only [by-id by-tag set-html!]]))
(defn ^:export play []
(let [foo (by-id :foo)
paras (by-tag :p)]
(set-html! foo "Hello")
(js/alert "ClojureScript says 'Boo!'")
(doseq [p paras] (set-html! p "Gone!"))))
</pre>
<p>Again, the ClojureScript compiler will go to work and
recreate <strong>main.js</strong> containing the compiled (to
JavaScript) version of both <strong>.cljs</strong> files
together.</p>
<p>Let's update the default view in our FW/1 application to call this
JavaScript.
Edit <strong>src/fw1cljs/views/main/default.html</strong>. We'll add
these two lines to the bottom of the file:</p>
<pre>
<p><a href=""
onclick="example.core.play(); return false;">
Surprise me</a>!</p>
<p id="foo"></p>
</pre>
<p>We've added an empty paragraph tag with an ID of "foo" and we've
added a clickable link that
calls <strong>example.core.play()</strong>, the function we defined
above. Now let's include the generated JavaScript file:
edit <strong>src/fw1cljs/layouts/main/default.html</strong> and add
the following line between the <strong>link</strong> and the end of
the <strong>head</strong> section:</p>
<pre>
<script src="/assets/js/main.js"></script>
</pre>
<p>Let's start the FW/1 application again:</p>
<pre>
PORT=8888 lein run
</pre>
<p>Now you'll see the new text <u>Surprise me</u>! so go ahead and
click it... You should see "Hello" appear below that paragraph and
then a JavaScript alert containing "ClojureScript says 'Boo!'".
Click <strong>OK</strong> and you should see all four paragraphs
replaced with "Gone!". Success! <em>[Setting the foo element to
Hello doesn't seem to work on Safari for me but it works in Firefox
and Chrome - go figure!]</em></p>
<p>If you edit views, layouts or controller code while Jetty is
running, simply add <strong>?reload=secret</strong> to the URL to
force FW/1 to reload the changes. If you edit the ClojureScript
files, the compiler will automatically regenerate the JavaScript so
just reload the page in the browser to load the new source.
Enjoy!</p>
<p>So what does all that ClojureScript code actually do?</p>
<pre>
(ns example.core
(:use [example.util :only [by-id by-tag set-html!]]))
</pre>
<p>A namespace declaration that pulls in three specific functions from
the utility namespace (the first <strong>.cljs</strong> file we created).</p>
<pre>
(defn ^:export play []
</pre>
<p>Define a function, <strong>play</strong> that takes no arguments.
We declare it <strong>^:export</strong> so that the Google Closure
compiler won't munge the name in <strong>:optimizations
:advanced</strong> mode (which minifies the JavaScript).</p>
<pre>
(let [foo (by-id :foo)
paras (by-tag :p)]
</pre>
<p>These give us handles on some DOM elements: <strong>foo</strong>
refers to the element with the ID of "foo" (the paragraph we added)
and <strong>paras</strong> refers to all the <strong>p</strong> tag elements.</p>
<pre>
(set-html! foo "Hello")
</pre>
<p>This sets the inner HTML of the <strong>foo</strong> element.</p>
<pre>
(js/alert "ClojureScript says 'Boo!'")
</pre>
<p>This runs the JavaScript function <strong>alert</strong></p>
<pre>
(doseq [p paras] (set-html! p "Gone!"))))
</pre>
<p>This loops over all the elements in <strong>paras</strong> and sets
the inner HTML of each one.</p>
<p>Given that information, I'll leave comprehension
of <strong>example/util.cljs</strong> as an exercise for the reader.
If you've seen Java interop in Clojure, you'll recognize the
notation for JavaScript interop in ClojureScript (forms that start
with a dot).</p>
|
|
| guid |
| Stomach Contents: Structure - struct |
| isPermaLink |
NO
|
| value |
http://corfield.org/blog/post.cfm/getting-started-with-clojurescript-and-fw-1
|
|
| link |
http://corfield.org/blog/post.cfm/getting-started-with-clojurescript-and-fw-1
|
| pubDate |
Mon, 06 Feb 2012 02:32:30 GMT
|
| title |
Getting Started with ClojureScript (and FW/1)
|
|
|