I initially had this idea for reducing the Ruby code in the views. That manifested itself as the Stage plugin. I was never really satisfied with the result, passing the form variable around was such a hack.
Thanks to the action_name instance variable, I've now cleaned it up and am much happier with the result.
Check out the RubyForge page for a quick how-to or the updated original post for more information.
Saturday, April 26, 2008
Sunday, April 20, 2008
Merb: Stage gem
I've just written a little code template generator for Merb called Stage. This idea was originally implemented as a plugin for Rails, but has been refactored as a gem. This new version is for Merb + DataMapper only. Extended support for Rails and other ORMs are planned.
There appears to be some quirk with the DataMapper generator, so I had to essentially copy that generator into Stage. I will revert to using the "model" dependency in the generator when this is corrected. Sorry, I haven't had the time to dig into the issue.
More details here.
There appears to be some quirk with the DataMapper generator, so I had to essentially copy that generator into Stage. I will revert to using the "model" dependency in the generator when this is corrected. Sorry, I haven't had the time to dig into the issue.
More details here.
Wednesday, April 16, 2008
github and public key
If you haven't heard, everyone is moving to git. Not really sure why yet, I like svn, but felt like I should probably keep in touch. I have a need to create a Stage generator for Merb, so I thought this would be a good opportunity. Quick note: the Stage generator for Merb will be a refactor which I will port to Rails later.
The account setup at github was easy and I followed the directions for providing my public key. Checked and double checked.
I then added my repository and followed the following steps (also from github):
I get to the last step and try the push. Ooops:
I knew it was a configuration issue, just wasn't sure if it was a git thing or not. After a minute or two of thinking it through, all I needed to do was:
I then re-tried the push command, and it worked. Cool.
The account setup at github was easy and I followed the directions for providing my public key. Checked and double checked.
I then added my repository and followed the following steps (also from github):
$ mkdir stage
$ cd stage
$ git init
$ touch README
$ git add README
$ git commit -m 'first commit'
$ git remote add origin git@github.com:stonean/stage.git
$ git push origin master
I get to the last step and try the push. Ooops:
$ git push origin master
Permission denied (publickey).
fatal: The remote end hung up unexpectedly
error: failed to push to 'git@github.com:stonean/stage.git'
I knew it was a configuration issue, just wasn't sure if it was a git thing or not. After a minute or two of thinking it through, all I needed to do was:
$ cd ~/.ssh
$ ssh-add id_rsa
I then re-tried the push command, and it worked. Cool.
Labels:
git
Merb Assets updated
The merb-assets post has been updated with information on css and javascript helpers.
Labels:
Merb
Merb Helpers
$ sudo gem install merb_helpers
This will get you the merb_helpers gem. This handy gem has the helpers I found really useful in Rails. Methods such as form_for, error_messages_for and the like are included in this gem.
Not all the methods are exactly the same as the Rails helpers. Take a look at the documentation for a list of available helpers.
Don't forget to add the dependencies line in your init.rb:
dependencies "merb_helpers"
I'll be posting more information on helpers as I use them. I don't like using too many helper methods, but what I do like I use a lot.
back to Merb index
Labels:
Merb
Merb Assets - clarified
So, I had some confusion at the start between assets and helpers. While merb-assets provides the link_to method, it's not the same as what I would consider "helpers". Assets are, well, asset oriented. By this I mean images, javascripts and stylesheets. Please refer to the merb-more documentation for assets to get a list of methods.
For form helpers you'll need to install the merb_helpers gem.
For form helpers you'll need to install the merb_helpers gem.
Labels:
Merb
Friday, April 11, 2008
Merb Routing update
I've updated the Merb Routing post with information on how to use your defined resources with link_to.
Labels:
Merb
Thursday, April 10, 2008
Merb boot order
So, for the better part of a day, I've been really focused on the load sequence of Merb to understand the order in which the resources are loaded. Here's a summary of my understanding of the bootloader code.
The BootLoader class has a clean design for defining the initialization sequence, it just took me a while to get that 'ahhh' moment. Probably because I'm a moron.
In bootloader.rb, there are several sub-classes of Merb::BootLoader defined. As each subclass is instantiated, they are pushed into an array of subclasses via the inherited method on the Merb::BootLoader class. When the run method in Merb::BootLoader is called the subclass array is processed and the run method of each subclass is called. Very nice setup.
So, here's a list of the classes in the order they will be processed. The names should be decriptive enough to give you an idea of their functionality:
The Merb::BootLoader::Dependencies class does a few actions that can't be inferred from the name. The run method on this class calls the following (in this order):
What was confusing me was the reference to app. It seems clear now, but I was thinking this included everything: the Merb framework classes and the application classes (models, controllers, etc...) you write. This actually refers to your application code. Do stuff before Merb loads your code or do it after.
The before_app callbacks are processed in the run method of Merb::BootLoader::BeforeAppRuns. As you can see from above, this is before the Merb::BootLoader::LoadClasses. This is the class that processes everything in the load paths for your application. The Merb::BootLoader::AfterAppLoads processes the after_load callbacks.
My initializers post has been updated to reflect this new information.
I hope someone will find this useful.
back to Merb index
The BootLoader class has a clean design for defining the initialization sequence, it just took me a while to get that 'ahhh' moment. Probably because I'm a moron.
In bootloader.rb, there are several sub-classes of Merb::BootLoader defined. As each subclass is instantiated, they are pushed into an array of subclasses via the inherited method on the Merb::BootLoader class. When the run method in Merb::BootLoader is called the subclass array is processed and the run method of each subclass is called. Very nice setup.
So, here's a list of the classes in the order they will be processed. The names should be decriptive enough to give you an idea of their functionality:
- Merb::BootLoader::Logger
- Merb::BootLoader::DropPidFile
- Merb::BootLoader::BuildFramework
- Merb::BootLoader::Dependencies
- Merb::BootLoader::BeforeAppRuns
- Merb::BootLoader::LoadClasses
- Merb::BootLoader::Templates
- Merb::BootLoader::MimeTypes
- Merb::BootLoader::AfterAppLoads
- Merb::BootLoader::MixinSessionController
- Merb::BootLoader::ChooseAdapter
- Merb::BootLoader::RackUpApplication
- Merb::BootLoader::ReloadClasses
- Merb::BootLoader::ReloadTemplates
The Merb::BootLoader::Dependencies class does a few actions that can't be inferred from the name. The run method on this class calls the following (in this order):
- load_initfile
- load_env_config
- enable_json_gem
- load_dependencies
- update_logger
Merb::BootLoader.before_app_loads do
#Stuff you want to do before your application loads
end
Merb::BootLoader.after_app_loads do
#Stuff you want to do after you application loads
end
What was confusing me was the reference to app. It seems clear now, but I was thinking this included everything: the Merb framework classes and the application classes (models, controllers, etc...) you write. This actually refers to your application code. Do stuff before Merb loads your code or do it after.
The before_app callbacks are processed in the run method of Merb::BootLoader::BeforeAppRuns. As you can see from above, this is before the Merb::BootLoader::LoadClasses. This is the class that processes everything in the load paths for your application. The Merb::BootLoader::AfterAppLoads processes the after_load callbacks.
My initializers post has been updated to reflect this new information.
I hope someone will find this useful.
back to Merb index
Labels:
Merb
Merb Sessions
By default, Merb uses a cookie session store. Straight from the Merb docs:
I have more than 4k and I don't want the data visible (most important aspect). So, since I'm using DataMapper, I'll use their session store. To do this, modify your config/init.rb as such:
No need to manually create the sessions table, DataMapper handles this for you.
Memcache and memory session storage options are also available if you so desire.
back to Merb index
If you have more than 4K of session data or don’t want your data to be visible to the user, pick another session store.
I have more than 4k and I don't want the data visible (most important aspect). So, since I'm using DataMapper, I'll use their session store. To do this, modify your config/init.rb as such:
Merb::Config.use do |c|
### Sets up a custom session id key, if you want to piggyback sessions of other applications
### with the cookie session store. If not specified, defaults to '_session_id'.
# c[:session_id_key] = '_session_id'
c[:session_secret_key] = '1d838e01a42847e044416d0764dc76d2b50b1045'
#c[:session_store] = 'cookie'
c[:session_store] = 'datamapper'
end
No need to manually create the sessions table, DataMapper handles this for you.
Memcache and memory session storage options are also available if you so desire.
back to Merb index
Labels:
DataMapper,
Merb
Tuesday, April 8, 2008
Initializers in Merb
Note: A lot has been learned since I posted this. Please read the boot order post for more detailed information.
I was a fan of the config/initializers directory functionality recently added into Rails. I want it in Merb. So, to get this add the following into the Merb::BootLoader.before_app_loads block in config/init.rb.
This code was taken from the Rails source (modified slightly of course).
back to Merb index
I was a fan of the config/initializers directory functionality recently added into Rails. I want it in Merb. So, to get this add the following into the Merb::BootLoader.before_app_loads block in config/init.rb.
Merb::BootLoader.before_app_loads do
Dir["#{Merb.root}/config/initializers/**/*.rb"].sort.each do |initializer|
require(initializer)
end
end
This code was taken from the Rails source (modified slightly of course).
back to Merb index
Labels:
Merb
Monday, April 7, 2008
Merb Routing
Routing is very similar to Rails:
In your config/router.rb define your routes as such:
Update 2008.04.11:
The Rails way adds a bunch of methods for you after defining a resource (like I did with :folders). However, Merb operates differently. I actually think I prefer Merb's approach because it funnels all url generation to the "url" method instead of giving a bunch of different ways to do the same thing.
So, after you define your :folders resource you can do the following:
As I learn more, the information will be posted here.
back to Merb index
In your config/router.rb define your routes as such:
Merb::Router.prepare do |r|
r.resources :pages
r.resources :contents
r.resources :folders
r.resources :functions
r.resources :messages
#Allows me to call link_to('Home', :home)
r.resource :home, {:controller => 'home', :action => 'index'}
end
Update 2008.04.11:
The Rails way adds a bunch of methods for you after defining a resource (like I did with :folders). However, Merb operates differently. I actually think I prefer Merb's approach because it funnels all url generation to the "url" method instead of giving a bunch of different ways to do the same thing.
So, after you define your :folders resource you can do the following:
<%= link_to "List Folders", url(:folders)%>
<%= link_to "Show Folder", url(:folder, @folder)%>
<%= link_to "Create Folder", url(:new_folder)%>
<%= link_to "Edit Folder", url(:edit_folder, @folder)%>
<%= link_to "Delete Folder", url(:delete_folder, @folder)%>
As I learn more, the information will be posted here.
back to Merb index
Labels:
Merb
Merb-Assets
The gem is merb-assets.
In order to take advantage of the merb-assets you need to modify your config/init.rb and add:
Now you can use link to:
If you have a :home route defined, you can:
For your css and javascripts you have the following:
The cool thing about this is that, in production mode, this assets get combined into a single file. So you'll end up with an all.css and and all.js. You can specify the name of the bundle:
This will create a base.js and base.css to be included. Nice.
More info to be added as I come across asset oriented features.
back to Merb index
In order to take advantage of the merb-assets you need to modify your config/init.rb and add:
dependencies "merb-assets"
Now you can use link to:
link_to("Home","/home/index")
If you have a :home route defined, you can:
link_to("Home",:home)
For your css and javascripts you have the following:
<%= css_include_tag 'reset.css', 'master.css', 'jquery.treeview.css', :bundle => true %>
<%= js_include_tag 'jquery-1.2.3.pack', 'jquery.cookie.js', 'jquery.treeview.pack.js', 'application.js', :bundle => true %>
The cool thing about this is that, in production mode, this assets get combined into a single file. So you'll end up with an all.css and and all.js. You can specify the name of the bundle:
<%= css_include_tag 'reset.css', 'master.css', 'forms.css', 'jquery.treeview.css', :bundle => :base %>
<%= js_include_tag 'jquery-1.2.3.pack', 'jquery.cookie.js', 'jquery.treeview.pack.js', 'application.js', :bundle => :base %>
This will create a base.js and base.css to be included. Nice.
More info to be added as I come across asset oriented features.
back to Merb index
Labels:
Merb
Merb Index
This will be the one page I'll reference for all my Merb notes.
There will be a link in each of the above pages back to this page. ...and yeah, the styling is crap, but I'll worry about that when I get more content.
- Installing
- Load sequence
- Assets
- Routing
- Sessions
- Initializers
- Basic stuff
- Extensions
There will be a link in each of the above pages back to this page. ...and yeah, the styling is crap, but I'll worry about that when I get more content.
Labels:
Merb
Thursday, April 3, 2008
Merb Installing
I recently started updating an application I wrote called Easel (yes it's a CMS) to version 2.1 of Rails. It was originally written pre-1.0 Rails, so it needed some serious updates and I wanted to open source the application.
Today I talked with some co-workers bringing them up to speed on the 2.x updates as they had last used Rails somewhere around 1.1.6. While talking with them, the conversation led to competitors and my belief that Merb has great potential. I've loved the pluggable architecture and overall direction taken by Ezra and the Merb team from the beginning.
So, shortly after the meeting I decided to stop my update of Easel and migrate the application to Merb. I know what I'm after for functionality, I knew the code needed updating so I thought this was a great time to switch.
So, I'm going to post what I learn as I switch to Merb. This first post is about installing the gems, creating a basic app structure and adding one resource.
The resource generator just creates place holder files without any template form code like the Rails generator. From the Merb point of view, I completely understand. From the developer point of view, I'll have to write a more complete generator to save me some time.
There will be a lot more to come, but this post is super long already. :)
Today I talked with some co-workers bringing them up to speed on the 2.x updates as they had last used Rails somewhere around 1.1.6. While talking with them, the conversation led to competitors and my belief that Merb has great potential. I've loved the pluggable architecture and overall direction taken by Ezra and the Merb team from the beginning.
So, shortly after the meeting I decided to stop my update of Easel and migrate the application to Merb. I know what I'm after for functionality, I knew the code needed updating so I thought this was a great time to switch.
So, I'm going to post what I learn as I switch to Merb. This first post is about installing the gems, creating a basic app structure and adding one resource.
# Substitute vi for your favorite editor command
#
# --include-dependencies or -y is now default
#
$ sudo gem install merb
#
# output from gem install merb
#
Successfully installed merb-core-0.9.2
Successfully installed merb-action-args-0.9.2
Successfully installed merb-assets-0.9.2
Successfully installed merb-gen-0.9.2
Successfully installed merb-haml-0.9.2
Successfully installed merb-builder-0.9.2
Successfully installed merb-mailer-0.9.2
Successfully installed merb-parts-0.9.2
Successfully installed merb-cache-0.9.2
Successfully installed merb-more-0.9.2
Successfully installed merb-0.9.2
<snip>
#
# end output
#
#
# Install the Datamapper ORM
#
$ sudo gem install merb_datamapper
#
# Create an application skeleton
#
$ merb-gen app easel
#
# output from merb-gen app easel
#
RubiGen::Scripts::Generate
create app
create app/controllers
create app/helpers
create app/views
create app/views/exceptions
create app/views/layout
create autotest
create config
create config/environments
create public
create public/images
create public/stylesheets
create spec
create app/controllers/application.rb
create app/controllers/exceptions.rb
create app/helpers/global_helpers.rb
create app/views/exceptions/internal_server_error.html.erb
create app/views/exceptions/not_acceptable.html.erb
create app/views/exceptions/not_found.html.erb
create app/views/layout/application.html.erb
create autotest/discover.rb
create autotest/merb.rb
create autotest/merb_rspec.rb
create config/rack.rb
create config/router.rb
create config/init.rb
create config/environments/development.rb
create config/environments/production.rb
create config/environments/rake.rb
create config/environments/test.rb
create public/merb.fcgi
create public/images/merb.jpg
create public/stylesheets/master.css
create spec/spec.opts
create spec/spec_helper.rb
create /Rakefile
#
# end output
#
$ cd easel
$ vi config/init.rb
#Uncomment for DataMapper ORM
use_orm :datamapper
$ cp config/database.yml.sample config/database.yml
$ vi config/database.yml
#
# Edit to your database settings
#
#
# if using mysql, install the DataObjects::Mysql Driver
#
$ sudo gem install do_mysql
# Output from gem install do_mysql
#
Building native extensions. This could take a while...
Successfully installed data_objects-0.2.0
Successfully installed do_mysql-0.2.3
<snip>
#
# end output
#
# Let's run to make sure we can. You should get the not_found.html.erb
# exception page.
$ merb
# merb defaults to port 4000 so go to:
#
# http://localhost:4000
#
#
# So, lets generate a resource (controller, model, view)
#
$ merb-gen resource page content:text permanent_url:string is_enabled:boolean is_featured:boolean show_in_footer:boolean
#
# Output from merb-gen command
#
dependency model
exists app
create app/models
create app/models/page.rb
dependency merb_model_test
exists spec
create spec/models
create spec/models/page_spec.rb
dependency resource_controller
exists app
exists app/controllers
exists app/helpers
exists app/views
create app/views/pages
create app/controllers/pages.rb
create app/helpers/pages_helper.rb
create app/views/pages/edit.html.erb
create app/views/pages/index.html.erb
create app/views/pages/new.html.erb
create app/views/pages/show.html.erb
dependency merb_resource_controller_test
create spec/controllers/
create spec/helpers/
exists spec
exists spec/controllers
exists spec/helpers
create spec/views
create spec/views/pages
create spec/controllers/pages_spec.rb
create spec/helpers/pages_helpers.rb
create spec/views/pages/delete.html.erb_spec.rb
create spec/views/pages/edit.html.erb_spec.rb
create spec/views/pages/index.html.erb_spec.rb
create spec/views/pages/new.html.erb_spec.rb
create spec/views/pages/show.html.erb_spec.rb
#
# end output
#
#
# Check out the model, just for a looksee
#
$ vi app/models/page.rb
#
# Page model
#
class Page < DataMapper::Base
property :show_in_footer, :boolean
property :is_featured, :boolean
property :is_enabled, :boolean
property :content, :text
property :permanent_url, :string
end
#
# end page model
#
#
# Add pages to routes file
#
$ vi config/router.rb
#
# in Merb::Router.prepare do |r|
#
r.resources :pages
#
# Startup merb and access your new resource
#
# http://localhost:4000/pages
#
The resource generator just creates place holder files without any template form code like the Rails generator. From the Merb point of view, I completely understand. From the developer point of view, I'll have to write a more complete generator to save me some time.
There will be a lot more to come, but this post is super long already. :)
Labels:
DataMapper,
Merb
Subscribe to:
Posts (Atom)
