Ruby on Rails provides a large API for web development, including adding new methods to Ruby's base classes. One method I don't see used that often is Hash#except. From the Rails API documentation:
Return a hash that includes everything but the given keys. This is useful for limiting a set of parameters to everything but a few known toggles:
@person.update_attributes(params[:person].except(:admin))
A great use I found for it is to help test validation methods on Model objects. By defining a method that will return all the valid attributes on a model, you can easily exclude the ones you want to test with Hash#except.
I'm using RSpec in this example but the same idea works with Test::Unit or any other testing framework. I created a method valid_attributes that will return the attributes my Model needs to be valid. In this case my SystemNotification object needs a body, subject, and some users.
module SystemNotificationSpecHelper
def valid_attributes
user1 = mock_model(User, :mail => 'user1@example.com')
user2 = mock_model(User, :mail => 'user2@example.com')
return {
:body => 'a body',
:subject => 'a subject line',
:users => [user1, user2]
}
end
end
I used mocks for the users because I don't care about them, only that they are present. So to test if my object is valid, I can easily just pass in valid_attributes to my new method:
describe SystemNotification, "valid?" do
include SystemNotificationSpecHelper
it 'should be valid with the body, subject, and users' do
system_notification = SystemNotification.new(valid_attributes)
system_notification.valid?.should be_true
end
end
Now I want to write some more specs to make sure if a SystemNotification is invalid if it's missing any of the required attribute. Since valid_attributes is a Hash, I can use Hash#except to remove each attribute individually and make sure the object is invalid for each case.
describe SystemNotification, "valid?" do
include SystemNotificationSpecHelper
it 'should be valid with the body, subject, and users' do
system_notification = SystemNotification.new(valid_attributes)
system_notification.valid?.should be_true
end
it 'should be invalid without a subject' do
system_notification = SystemNotification.new(valid_attributes.except(:subject))
system_notification.valid?.should be_false
end
it 'should be invalid without a body' do
system_notification = SystemNotification.new(valid_attributes.except(:body))
system_notification.valid?.should be_false
end
it 'should be invalid without any users' do
system_notification = SystemNotification.new(valid_attributes.except(:users))
system_notification.valid?.should be_false
end
end
This is just a simple example but you can use Hash#except in many other places:
- updating attributes like the Rail documentation sample
- copying values from one object to another
- extracting options from a argument
If you'd like some extra practice, refactor my specs to make sure SystemNotification#errors is populated based on what attribute failed. You can find the full code on GitHub, just send me a pull request when you're done.
Eric
Tagged: rails rspec ruby testing
One problem I've noticed with fast paced projects is that details can get lost in all the activity. Shane and Peter noticed that with their Redmine, many times a question would be asked but someone would never answer it. To solve this problem, they sponsored the development of Redmine Question plugin. This plugin will help users keep track of the questions they are asking and what questions others are asking them.
Features
- User can ask a question with an issue note
- Question can be assigned to be answered by a project member
- Filters for the issue list:
- Question is assigned to
- Question was asked by
- Question column for the Issue list showing a preview of all the open questions asked on an issue
- Email notification when questions are asked and answered
Getting the plugin
A copy of the plugin can be downloaded from Little Stream Software or from GitHub.
Usage
The question plugin is very easy to use. Just update an issue and select a Member from the question select box right below the issue notes.
License
This plugin is licensed under the GNU GPL v2.
Project help
If you need help you can contact me or create an issue in the Bug Tracker.
Thanks
I would like to thank Shane and Peter for sponsoring this plugin. If you find it useful, send your appreciation their way.
If you are currently working on a Redmine plugin and need help or have an idea for a plugin you would like developed, please contact me. My company, Little Stream Software, specializes in the development of custom Redmine features and Redmine plugins.
Eric
Tagged: open source redmine redmine plugins
Every business has slow times, with freelancing it's the "famine" part of the feast and famine cycle. Since most freelancers are just a single person, a slow period can easily affect your lifestyle and cause a lot of stress. Once you are in the famine stage, you have to admit to yourself that it's only temporary and take action to work through it faster. I've found there are three things I tend to do when I get slow:
1. Marketing
The number one thing I do when business is slow is to market more. The more marketing you do the faster you can pull through the famine stage. Some ideas that I've found to work great are:
- Write an interesting comment on blog that your customers read.
- Write to your own blog. Don't have one yet, start one!
- Connect with past customers and see if they need help with anything. If it's something you can't do, tap your network and find someone who can.
- Have some guts and send a personalized message to a company you would like to work with. This can be an email, letter, or even a gift. Just try to get noticed.
- Connect with other business people on your favorite social network like Twitter. Focus on having interactions and building relationships.
- Review your website copy to make it easier to skim and understand.
- Find a volunteer organization that you can contribute time to. Many of them are hurting for help, especially a freelancer specialist.
- Find an Open Source project and ask what you can do to help out. They don't just need code anymore; they need graphics, public relations, user support, and leadership.
2. Hone your skills
Another thing I do during slow time is to hone my skills. When given the choice of marketing or honing your skills I try to market but not everyone can market themselves all the time. There is one idea that you can use to actually hone your skills and also get some marketing in for free:
Hone your skills in public
Learning (and failing) in public will let you show off your ideas, improve it over time, and will also give you something you can point to later on. Since I mostly work with web developers and web designers, here's a few ideas:
Web Developers
- Pick a new technology you want to learn, create a small library, and Open Source it. Publish the code on GitHub and write about what you learned.
- Start a single serving site using a new web framework. The is____yet.com sites seem to be really popular now.
- Pick up a new programming language and try to start a side project in it. Try to make it generate valid XHTML from an input.
- Create a plugin for your favorite project and publish it online (e.g. Rails, Redmine, Radiant, Wordpress).
- Review someone else's code and start a conversation about what it does and how it can be improved.
Web Designers
- Find a non-profit or community website and redesign their homepage. Offer to work with them to complete the redesign (for free or paid, your choice).
- Pick an Open Source application you use and talk to them about a site redesign. I've seen hundreds of project websites that still look like they are from 1995.
- Pick a popular site and comp out a few updates to improve the UI. 37signals did this early on and it got them bit of publicity.
- Try out a new technique in your favorite tools and create a short tutorial on how it works.
3. Relax
Finally if you have done everything above, then just let yourself relax. There are hundreds of projects starting every day, sometimes you just need to wait for them to you. Try to find a way to relax that will help you in the long run,
- Read a book
- Go for a jog
- Write a letter to an old friend (yes, on paper... no email doesn't count.. neither does Facebook)
- Take a nap in the sun
- Spend the day at the library or other public
If you have any other ideas that help you work through the slow times, let me know in the comments.
Eric
Tagged: business freelance marketing
Some of you may have noticed the new design here and on LittleStreamSoftware.com. For the past two years, both sites have been using free templates for their design. The templates were good but they were not showing off the quality of work I do. So with the help from Selene from iDesignStudios, we created an completely custom design that ties both sites together. Selene created a few beautiful HTML templates which I then sliced into the webgen and Mephisto backends. The process wasn't difficult but was time consuming porting all my content over. During this time, I took the opportunity to update my copy and add tons of new screenshots to my portfolio.
I'm planning on writing up a few posts about customizing webgen for Little Stream Software. It's a really good system if you are just want static HTML pages but the documentation is hard to find and follow. A few of the customizations I did was to automatically resize images, generate a htaccess file for redirects, and dynamically pull in pages of content.
I've also setup a UserVoice forum with the list of writing ideas I've had. I'd love to get some feedback on which ideas would be the most useful or even if you have a question about Ruby on Rails, Redmine, or software contracting. Just click on the blue Feedback button on the right side of the page.
Eric
Tagged: blog theadmin website
I offer computer programming, testing, and deployment for websites, web applications, and business tools using Ruby on Rails and the Ruby programming language.
Here are some benefits of using my services:
- Ruby expert who will work with you to create the software you need
- Easy to use, high quality software
- Throughly tested applications, no more crashes stopping your business for weeks
- Professional project management
- Cost savings from not having to hire an in-house development staff
Tagged: business rails ruby
I've used rcov for a long time to check the code coverage on my Ruby applications. Code coverage shows what parts of an application have not been tested. It can be abused if it's used as an absolute metric (must be 99%+) but it's great to see where fragile parts might be located. A problem I've had though, is rcov will not add a file to it's report unless it has been loaded. This means if you just run rcov out of the box, you could get a high coverage report because the untested files are not counted.
After searching, I've found a post by Jamie Flournoy that had a simple chunk of code to require all Ruby files when rcov is run. I've adapted it for my Redmine plugins (Rails Engines) and it's been really useful as I refactor the code.
if defined?(Rcov)
all_app_files = Dir.glob('{app,lib}/**/*.rb')
all_app_files.each{|rb| require rb}
end
All I had to do was to put this into my spec_helper.rb file and rerun rcov. Now the coverage report is loading the entire application correctly. If you want to see a more complex example, check out Jamie Flournoy's original post where he filters out a file files.
Eric
Tagged: rcov ruby testing
I was recently asked how do create a link in a Redmine plugin hook. The answer is you can use the Ruby on Rails helper link_to but you need a few additional fields for Rails to know where to link to.
The standard link_to will generate an ActionView::TemplateError:
link_to("My Link", {
:controller => 'my_controller',
:action => 'index'
})
ActionView::TemplateError (Missing host to link to! Please provide :host parameter or set default_url_options[:host]) on line #7 of issues/_sidebar.rhtml:
Redmine has a Setting that stores the host the server is running on, so you can change the link_to method to:
link_to("My Link", {
:controller => 'my_controller',
:action => 'index',
:host => Setting.host_name
})
You might also want to add the :protocol option, otherwise the generated link will always be http even if the rest of the site is using https. Once again, Redmine has a setting for this:
link_to("My Link", {
:controller => 'my_controller',
:action => 'index',
:host => Setting.host_name,
:protocol => Setting.protocol
})
I hope this helps explain how to add links into Redmine's plugin hooks. If you have any questions, ask me in the comments on this article.
Update: Peter just posted an easier way to create a link using the only_path option. According to my Rails API docs it it supposed to default to true but the documentation might be wrong (wouldn't be the first time)
link_to("My Link", {
:controller => 'my_controller',
:action => 'index',
:only_path => true
})
Eric
Tagged: plugin redmine ruby on rails
To keep up with all my Redmine plugins, I've Open Sourcing a new plugin, the Stuff To Do plugin. If you have ever run a project and had to consistently tell people what to work on next, this plugin is for you. It will let a user to order and prioritize the issues they are doing into a specific order across multiple Redmine projects.
Features
- Sorting and prioritizing of cross-project To Do lists
- Easy to use drag and drop interface
- Editing other user lists for Administrators
- Filtering of issues based on user, priority, or status
- Notification emails based on low issue counts
Getting the plugin
A copy of the plugin can be downloaded from Little Stream Software or from GitHub
Usage
There are three panes that can be sorted:
What I'm doing now
This pane lists the next 5 issues a user is supposed to be working on. These issues should be the most important issues assigned to the user. As the user closes an issue, the items lower in the list will rise up and fill in this pane.
What's recommended to do next
This pane lists up to 10 extra tasks for the user. These tasks are used as overflow for the What I'm doing now.
What's available
This pane lists all the open issues that are assigned to the user. They are the pool of issues that a user can draw on as they work on issues.
Workflow
The standard workflow for this plugin is as follows:
- A user will drag issues from the What's Available pane to the What I'm doing now and What's recommended to do next
- Once 15 issues have been dragged (5 Now, 10 Next) the user would prioritize and sort the issues in order of importance
- The user would use the rest of Redmine and work on the #1 issue
- Once the #1 issue is complete (or blocked) the user would continue and work on the #2 issue
If the user is an Administrator, they have the permission to edit other users' lists. This allows them to act as the system Project Manager.
License
This plugin is licensed under the GNU GPL v2.
Project help
If you need help you can contact me or create an issue in the Bug Tracker.
Thanks
I would like to thank Tim Haskins from Copious Creative for sponsoring this plugin. If you find it useful, send your appreciation his way.
If you are currently working on a Redmine plugin and need help or have an idea for a plugin you would like developed, please contact me. My company, Little Stream Software, specializes in the development of custom Redmine features and Redmine plugins.
Eric
Tagged: open source redmine redmine plugins
A new release of the Redmine Timesheet plugin has been released for Redmine. This release has several major changes that will make it more useful for anyone managing a large team.
Download
The plugin can be download from the Little Stream Software project or from GitHub.
Changes
There have been several new features and bug fixes implemented. The notable ones are:
You can see more details on the Activity and Roadmap pages.
Plugin Hooks
This version of the Timesheet plugin adds a few hooks for other developers to use. Hooks allow a developer to modify how Timesheets works without having to change the plugin code. The available hooks are:
:plugin_timesheet_model_timesheet_conditions
:plugin_timesheet_view_timesheets_context_menu
:plugin_timesheet_view_timesheets_report_header_tags
:plugin_timesheet_view_timesheets_report_bottom
:plugin_timesheet_controller_report_pre_fetch_time_entries
What's next
Michele Franzin has been working on a fork of the Timesheet plugin that has a really nice calendar view and summary features. I'm planning on pulling in those changes and some others for the 0.5.0 release.
Help
If you need help you can leave a comment here or enter an issue directly into the bug tracker.
If you are currently working on a Redmine plugin and need help or have an idea for a plugin you would like developed, please contact me. My company, Little Stream Software, specializes in the development of custom Redmine features and Redmine plugins.
Eric
Tagged: open source redmine redmine plugins
Everyone's talking about their 2009 goals now, I guess the New Year tends to do that to people. Not to feel left out, I'm posting my 2009 goals. As a freelancer and a software developer, a lot of them are about building new software applications and learning technology. One thing I learned in 2008, was it's best to phrase future goals as past tense. Something about how the brain is wired subconsciously.
1. I earn 20% more Revenue than in 2008
2008 was a pretty good year for my business but I've still got a lot of room to grow in 2009. The great thing about this number is I've already mapped out how to get there, I just have to take action now.
2. I created $2,000 passive income
I've decided to start working on generating some passive income in order to separate my income from my time. Given a year, I figure I could make $2,000.
3. I doubled my followers (RSS, Email, Twitter)
I don't see the difference between RSS subscribers and Twitter followers so I'm going to work to have more people interested in what I'm doing in 2009. If you haven't yet subscribed to this blog or followed me on Twitter, could you?
4. I wrote an ebook
I have two niche ebook ideas that I think will be really useful. I've found a lot of my favorite books last year were smaller books, so I'm going to keep the ebooks on the short side.
5. I invested $8,000 to IRA
I'm not getting any younger so it's time to start reinvesting into my IRA. With the US stock market being so cheap, it's a good time to start dollar cost averaging again.
6. I created an application with Sinatra
I've used Sinatra a bit but I want to get some more experience hacking on it. And according Jason Seifer, Sinatra will be assimilated as part of Rails 5 (or was it Rails 10)...
7. I created an application with Datamapper
I enjoy working with ActiveRecord but I think Datamapper will let me be a bit more flexible with how I structure my applications.
8. I created an application with Merb Rails 3.0
I also have a few ideas where a slim Merb Rails 3.0 application would work quite nice. Plus it's enjoyable to try out another non-Rails Ruby framework now and then.
9. I created an application with Cucumber
Cucumber has a good syntax for writing integration tests. I've already done a bit of work on a Redmine plugin using Cucumber but I'd like to create another.
10. I used memcached with an application
My personal applications haven't had a need of anything more than page caching so far but I'd like to build an application using memcached so I can learn how to prepare for some heavier caching. It might also be useful to start implementing some caching into Redmine.
11. I created a jQuery plugin
In 2008 I did quite of bit of JavaScript development and fell in love with jQuery. I'd like to solidify that knowledge by building a jQuery plugin. It doesn't look that hard and I've even found a few tutorials on how to do it.
12. I created an application with jQuery UI
jQuery UI is a set of libraries that enhance jQuery to add several visual elements. I've worked with a few of them in 2008 but I'd like to get some more experience with them by building a more interactive application.
13. I know the Erlang syntax
One language I want to pick up in 2009 is Erlang. Not having a lot of experience with concurrency or functional programming I think this will be a nice stretch for me. It probably will not replace Ruby as my favorite language but I'm positive I could learn several concepts from Erlang.
14. I created an application with Erlang, web
Since I specialize in web development, it's only natural that I try to build an Erlang powered application for the web. I'm not sure what I'd want to build but I think a web service server might be fun.
15. I created an application with Erlang, database
I'd also like to get Erlang talking to a database. Ideally this would be a ActiveRecord type database so I can have Erlang and Ruby on Rails coexist. Like the goal above, I'm still thinking about what I want to build specifically.
I'm interested in seeing what other people are working on so if you've posted your 2009 goals, please add a link in the comments. Also if you happen to have a project on one of the technologies here and need some help, please contact me.
Eric
Tagged: 2009 business goals merb rails ruby