http://blog.merbivore.com/articles.rss
News about Merb
Last checked 3 months ago.
1 person has subscribed to this feed.
post frequency (last month)
PostRank™
From Merb, 3 months ago,
0 comments
Apologies for the delay in posting about this. I was enjoying the fantastic Ajax Experience and jQuery Camp out in Boston, where I got a chance to hang with my jQuery compatriots as the huge Microsoft and Nokia announcement broke.
Now that I’m back, I want to talk about the cool new features we’ve been adding to Merb’s server. Let’s take a look at them one at a time:The most important thing to keep in mind is that Merb has been significantly tuned for Ruby Enterprise, and with regular Ruby, there is a bit of overhead for the master processes. All of the features above will work correctly with standard Ruby, but you’ll get them for free (memory-wise), as well as quite a bit of improved memory overall in a cluster by using Ruby Enterprise.
Please please please check it out.
From Merb, 3 months ago,
0 comments
MiniGems is a lightweight drop-in replacement for rubygems to facilitate faster loading of gems as well as reducing memory consumption considerably. Depending on the amount of gems you have installed about 10-20 MB less RAM will be used, compared to the full rubygems library version, which keeps a cache of all gems and files referenced by them.
Minigems handles loading of required gems from your scripts. If however, other functionality is needed, the full rubygems library will be loaded automatically to continue normal operation. Therefor, it's completely backwards compatible with RubyGems.
There's currently a pending patch on RubyForge that integrates minigems into the standard RubyGems system. You can find more information at the tracker page; if you like minigems, please post a vote/followup there.
That said, the current standalone release of MiniGems is based on the same concepts, but implemented in such a way that it can be used without touching RubyGems itself. We've decided to release it in the wild, in the advent of the patch being included in the forthcoming RubyGems release. It's mainly meant for people to play around with it, so we can find bugs and other issues.
Also, the way you use the standalone version is quite different to what the RubyGems patch provides; see the RubyForge tracker for the actual use. For now, you will mostly use the following features, exposed by the minigem command.
To get started run: sudo minigem setup
Then, to let the 'merb' command utilize minigems.rb run: sudo minigem prepare merb-core
In case you want to revert back to plain rubygems: sudo minigem remove merb-core
If you're on a Mac, you can easily check out the difference in memory consumption between the two in Activity Monitor.
The standalone minigems gem can be found on Github and you can use rake install to install it.
From Merb, 3 months ago,
0 comments
Highlights of this release are:
We did a short (5 days) release cycle to fix all the problems after some large merges right before 0.9.6.
Merb 0.9.8 will feature a new, very powerful but backwards incompatible router and (hopefully) a new merb-cache.
You can read about the at the wiki:
Also, read about the new cache at Merbunity:
Merb 0.9.8 is expected in about a week, around September 20th. Merb 0.9.9, expected to be released approximately September 27, will entail an API freeze. After 0.9.9, we will be adding additional spit-polish and fixing bugs only.
Merb 1.0 is going to be released at MerbCamp on Oct 11th to 12th. More information at merbcamp.com.
If you want to help out with polishing merb, it’s right about time to give gems in merb-more some love. ;)
From Merb, 4 months ago,
0 comments
As we approach 1.0 and work toward locking the API, we’re trying to figure out what sorts of things drive people nuts in Rails.
Basically, we’re looking for your top one or two gripes that drive you crazy. Because Merb borrows so heavily from Rails’ philosophy of convention over configuration and MVC model, it’s entirely possible that we’ve inadvertently borrowed some of the things that frustrate people.
So, gripe away!
From Merb, 4 months ago,
0 comments
Over the past few releases, there have been a number of breaking changes, which has frustrated a few people who have been working with Merb.
Let me explain exactly what’s going on. As I posted previously, we’re currently working towards Merb 1.0, which we intend to release on October 11, at Merb Camp. As part of Merb’s underlying philosophy about our public API, we intend to avoid breaking the public API, except for extremely urgent reasons, before the next major release (2.0).
As a result, it’s extremely important that the API that we expose for 1.0 is actually an API we’re comfortable standing by for the long haul. There’s still quite a few parts of Merb that were dragged in from Merb 0.5, and possibly even from Rails. As we march toward 1.0, we’re doing a full audit of the merb codebase and shoring things up.
Sometimes, as in the case of our ground-up rewrite of the form helpers or router, this requires some API changes. In other cases, as in the case of our ground-up rewrite of the dispatcher or sessions, this has virtually no public API effects.
So again, while it may seem as though a lot of things are changing quickly, those changes are in the service of post 1.0 stability. Once we get there, feel free to judge us for how successful we are at remaining stable. For now, use 0.9.x if you’re willing to put up with some changes. Otherwise, it’s a short jaunt to 1.0.
Also keep in mind that you can freeze to a specific version of Merb, and wait to upgrade all at once in October.
From Merb, 4 months ago,
0 comments
Following up with our 2-week release cycle, we’ve released Merb 0.9.5. In anticipation of the next release, “Time Machine,” which will allow for fool-proof code reloading and instant deploy restarts via Kernel.fork, we’re calling this release Spoons and Knives.
We know that some of you guys have been a bit frustrated with the more common API changes than there have been in the past. By way of explanation, we’re hoping to get Merb 1.0 released by MerbCamp on October 11, so we’re focusing on breaking what needs to be broken now, so that Merb can remain relatively stable after 1.0.
Some changes in 0.9.5:
From Merb, 5 months ago,
0 comments
Over the past week, Merb has been working on merging our core extension library with DataMapper’s, to provide a single non-conflicting library for both Merb and DataMapper to use. Unfortunately, it has caused some confusion for people who use edge merb but do not really dive into development process.
Here’s what changed and why:
In the meantime, expect edge to be a bit unstable as we make this transition.
From Merb, 5 months ago,
0 comments
The new generator has (almost) the same user interface as previous one but uses named arguments. Run merb-gen to see the list of generators and merb-gen to see its options and description. If you want to take a look at the new generators, make sure you’re operating against HEAD, as the released gems do not yet include the Templater-based generators.
Merb’s extensions of Ruby core classes now live in a separate library, called merb-extlib (github.com/wycats/merb-extlib). This is the first step towards merging Merb and DataMapper’s core extension libraries into a single small, fast library. Because Merb profiles and benchmarks extensively, our core extensions library is extremely fast. Even though Merb and DataMapper do not have significant overlap in our extension libraries, we believe that it’s important to create a single library that developers can work against, and avoid duplicating work (or, even worse, having two different implementations of the same extension).
Once Merb hits 1.0, no serious changes or breakages will be allowed (at least until 2.0). As a result, Merb’s contributors decided to make all necessary breakages in the 0.9 series, which is a developer release. Between 0.9.0 and 0.9.3, we have made significant enhancements to the framework, with only minor breaking changes to the public API, but there are some changes to come in the upcoming months.
Some things on the roadmap between 0.9.3 and 1.0:
We also plan to do a complete code audit as well as performance benchmarks before 1.0 to be sure that the codebase is as solid and reliable. Finally, we will lock down the public, plugin, and private API differences so that the 1.x series will be unlikely to cause major API breakage.
If you’re interested in getting involved or helping out, now’s the time!
Stay tuned.
From Merb, 6 months ago,
0 comments
From Merb, 6 months ago,
0 comments
The latest change to edge Merb doesn’t so much change the end-user functionality as it fixes a long-standing issue with how inheritable accessors work. If you’re mostly interested in how Merb work for an end-user, and not so much with Merb’s internals, it’s safe to skip this post.
Let’s start easy, with regular accessors:
class Foo attr_accessor :bar end @foo = Foo.new @foo.bar = 7 @foo.bar #=> 7
Regular attr_accessors are part of Ruby proper, and allow you to easily create accessor methods for instance variables in a class. The above code roughly converts to:
class Foo
def bar
@bar
end
def bar=(obj)
@bar = obj
end
end
This works great for simple instance variables. However, Ruby also has class variables, and Rails (as well as Merb) provides a simple way to bind methods to class variables:
class Foo cattr_accessor :bar end Foo.bar = 7 Foo.bar #=> 7
That works great too, subject to the normal rules of class variables. Specifically, class variables are shared by a class and all of its subclasses, so they cannot be used to implement behavior specific to different subclasses (for instance, specific Controllers). Here’s a quick demonstration:
class Merb::Controller cattr_accessor :blinking end class First < Merb::Controller self.blinking = true end class Second < Merb::Controller self.binking = false end First.blinking #=> false
As you can see, cattr_accessors cannot be used for controller-specific behavior. The next thing to try would be class instance variables:
class Merb::Controller
class << self
attr_accessor :blinking
end
end
class First < Merb::Controller
self.blinking = true
end
class Second < Merb::Controller
self.binking = false
end
First.blinking #=> true
Second.blinking #=> false
At first glance, this seems like the ticket. Sadly, this is not the way these sorts of accessors are usually used. What Merb (and Rails) wants to do is be able to set a preference on Merb::Controller and have it automatically inherit onto the child controllers unless specifically overridden. Like:
class Merb::Controller attr_inheritable_accessor :blinking self.blinking = false end class First < Merb::Controller self.blinking = true end class Second < Merb::Controller end First.blinking #=> true Second.blinking #=> false
In particular, we use this for things like layout location, which we want to allow to be declared in the Application controller, and have automatically percolate down to other controllers. This is also used in plugins quite a bit, where Merb::Controller will get a default inheritable attribute, which can be overridden at a lower level.
Rails comes with an inheritable accessor, which, until now, Merb used. Unfortunately, it has the following behavior:
class Merb::Controller; end class First < Merb::Controller; end class Merb::Controller class_inheritable_accessor :blinking self.blinking = true end First.blinking #=> nil
To make a long story short, the reason for this is that the accessor gets inherited at the same time as the class gets inherited, which is before the accessor was defined (in this case). In practice, this leads to extremely brittle load order, as it is fairly common practice for plugins to add inheritable_accessors, and if the plugin is loaded in after the application’s controllers, very difficult-to-debug behavior can result.
A survey of #merb revealed that this enigmatic issue had struck quite frequently, so it was time to resolve the issue.
In attacking the issue, we decided that the new inheritable accessor had to support the following behaviors:
We were able to achieve all of the above, with one caveat:
Parent.foo = "Hello" Child.foo Parent.foo = "Goodbye" Child.foo #=> "Hello"
This is because the way the above behavior is implemented is by storing the parent value on the first READ, which turns out to be much more versatile and correct that storing the parent on inherit. As it turns out, it’s almost always the case that the first read of an inheritable attribute happens at runtime, while the writes happen at boot-time, which makes this a perfectly reasonable tradeoff.
Of course, as I said above, this is a fairly esoteric change that doesn’t affect the average user of the framework, but it does dramatically reduce certain strange behavior from plugins.
From Merb, 6 months ago,
0 comments
We try hard not to break public APIs in Merb, but in the lead-up to 1.0, we’ll probably be doing a bit more breakage than we have in the past in an effort to reduce breakage post 1.0.
Today is one of those days. In order to improve the way ERB handles blocks, we were forced to make a substantial change that I will detail here.
First, some background.
Frequently, you’ll want to write a helper that takes a block. An example of such a helper is the form_for helper, which looks something like this in Rails:
<% form_for :foo do |f| %> <%= f.text_field(:zoo) %> <% end %>
The semantics you want are something like this:
<%= f.text_field(:zoo) %>)<form ...><%= contents of block %></form>)But wait! As it turns out, those are only the semantics you want if you are being called from ERB. Let’s take another example, the gentle content_tag helper.
In ERB, it works like this:
<% content_tag(:div, :id => "foo") do %> Hello, my name is Foo <% end %>
The above semantics still work just fine, so all is well. But lots of people use content_tag in regular Ruby code, as in:
def link(text, url)
content_tag(:a, :href => url) { text }
end
which will be called from ERB as:
<%= link("A Link", "http://example.com/foo") %>
Now look back over the semantics below. Step 3 is “Concatenate the results of the entire thing into the buffer”. But wait. What buffer? If we do a concat onto the ERB buffer, the results of the #link function will still get concatenated, as well as the results of the content_tag function.
I won’t go any deeper, but suffice it to say that the fundamental problem here is that helpers that take a block cannot simply return a string. In other words, the following doesn’t work:
<%= form_for :foo do |f| %> <%= f.text_field(:zoo) %> <% end %>
The reasons for this are kind of arcane, but the bottom line is that since it doesn’t work, we’re forced to use the concat hack, which then has the problem of having to deal with figuring out whether it was called from ERB (and thus should concat) or a regular helper (and thus should return a String).
When confronting issues such as these, the first step is usually to investigate how Rails handles the problem. In general, they do tackle the problem in some way or other, and so it’s usually worth figuring out what their approach is.
Let’s whip up the latest tag_helper.rb on Rails edge and pull up content_tag
def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
if block_given?
options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
content_tag = content_tag_string(name, capture(&block), options, escape)
if block_called_from_erb?(block)
concat(content_tag)
else
content_tag
end
else
content_tag_string(name, content_or_options_with_block, options, escape)
end
end
The important part is the middle section, beginning with block_called_from_erb?. Let’s take a look at the implementation of block_called_from_erb?:
BLOCK_CALLED_FROM_ERB = 'defined? __in_erb_template' # Check whether we're called from an erb template. # We'd return a string in any other case, but erb <%= ... %> # can't take an <% end %> later on, so we have to use <% ... %> # and implicitly concat. def block_called_from_erb?(block) eval(BLOCK_CALLED_FROM_ERB, block) end
So effectively, every time you use content_tag, or any helper that uses content_tag, Rails executes an eval inside the block to check whether __in_erb_template is defined. This is sort of an acceptable solution, but it means that any helper that does a concat needs to handle this case.
Feel free to skip this section if you just want to kno
I alluded to the solution above:
<%= form_for :foo do |t| %> <%= f.text_field(:zoo) %> <% end %>
If this would compile, then all would be well. Unfortunately, Erubis (like ERB) doesn’t support multiline. As I dug into why, it became messier and messier. To get a sense, the following two cases need to be treated differently:
<%= form_for :foo do |t| %> <%= f.text_field(:zoo) %> <% end %> <% if @foo %> <%= @bar %> <% end %>
The first case needs to be compiled into something like @_out_buf << (form_for(:foo) {|f| @_out_buf << f.text_field(:zoo)} ).to_s. The second case gets compiled into if @foo; @_out_buf << (@bar).to_s; end.
The bottom line is that with a lot of hacking, I was able to get Erubis to compile blocks correctly, in the following form.
<%= form_for :foo do |t| %> <%= f.text_field(:zoo) %> <% end =%>
Note the =%> on the last line. That tells Erubis that this end is the end of a block opened up via <%= previously. This provides a bit of symmetry from multi-line expression in Erubis (they open in <%= %> and close in <% =%>).
Effective today’s edge, helpers that take blocks are to be instantiated via the <%= %>...<% =%> pattern. If you make a new helper that takes a block, use #capture to get the contents of the block, and simply return a String. Let that sink in for a moment. Helpers that take blocks simply return a String.
Also coming very soon to edge are completely rebuilt Form Helpers. The new helpers were refactored with modularity in mind, making it very easy to create your own Form classes to use in your application with as little code as possible. Stay tuned for more on this.
From Merb, 8 months ago,
0 comments
Merb 0.9.3 is out. Check Ezra’s announcement for the details.