Showing posts with label Ruby on Rails. Show all posts
Showing posts with label Ruby on Rails. Show all posts

Sunday, 6 November 2011

Bits of Code #2 - Ordering records through index page with AJAX (powered by jQuery) in a Rails 3.1 App

In one of the projects that I worked in I had to make it possible for users to easily change the order in which the records of a table would appear in their index page. I knew that there were a few gems out there that could handle this for me, but I thought that it was such a simple functionality that it was probably not a strong enough reason to add another dependency to the project; so I went about building it.

In this example I've added this functionality to a Product model. I started by creating a migration to add the column that would keep the order between products, I decided to call this column sort_index.

Then I added a few methods to the Product model. Some methods to check the position of a product, others to move the product up and down in the 'ranking' of products, and a before_create callback to set the initial sort_index of each new product. Note that the upper position in my implementation is the position with sort_index equal to 0, so moving a product up is actually reducing its sort_index by 1.

These methods were tested with RSpec (might not be 100% coverage, let me know if that is the case). I've moved the RSpec file to the end of the post because is quite a long file.

Having these methods working I implemented the functionality and the interface to allow the users to actually change the ordering of the products.

Created the necessary routes.

Created the controller methods.

Followed by the views. The index page.

Which calls the _ordering partial

And then the js views to process the result of the requests. To move down.

And to move up.

If you need to use this in more than one model you can move some bits into a Module and then include the Module where necessary. I haven't had the need to do it. But if I do, I'll probably do a post about it.

Hope these bits of code are useful for you some day, I've already used in two projects. If you find any issues or have any suggestions to improve this code please let me know.

And now for the RSpec file:

Friday, 4 November 2011

Bits of Code - Nested Attributes

Yesterday I had the need to implement a form with some nested attributes and so I did what I often do: I went back to a previous project and copy&pasted the necessary code and then changed it to match the new project's needs.

While I was doing this I thought that it would be useful to get this, and other bits of code in a place that I can easily refer to, instead of having to remember in which project I've used what. This is the reasoning behind this post.

Bare in mind that this is not a post about life changing bits of code, but rather bits of code that I need now and then and that are easier to just copy&paste&edit than to have to rewrite from scratch. Some of these bits can be easily found in different websites, but having them here will make my life easier than having to search again. I'll make sure I'll refer to the websites that I've used.

So these first bits of code are meant to build a form with nested attributes.

Imagine that you have a model named Content that has many Attachments and when you are adding or editing a content, you want to be able to manage that content's attachments. This allows you to easily do it.

This code uses Rails accepts_nested_attributes_for and then it manages the different attachments with javascript methods (using jQuery framework), allowing you to add, remove and edit them accordingly.

The Content model:



The Attachment model (notice the accepts_nested_attributes_for method):



The ApplicationHelper, with the methods used in the views:


Part of the Content form view (notice the use of the method fields_for, and the helper method link_to_add_fields):


The attachment_fields partial (notice the use of the helper method link_to_remove_field):


And the javascript methods (notice that if the position of the elements in the attachment_fields partial changes this code might need to be updated):


 These bits of code are based on (or were copied from):

Tuesday, 20 September 2011

Asset Pipeline and Upgrading to Rails 3.1

One of the main changes in Rails 3.1 is the Asset Pipeline, which is, in the words of the Rails guide:
"The asset pipeline provides a framework to concatenate and minify or compress JavaScript and CSS assets. It also adds the ability to write these assets in other languages such as CoffeeScript, Sass and ERB.
Prior to Rails 3.1 these features were added through third-party Ruby libraries such as Jammit and Sprockets. Rails 3.1 is integrated with Sprockets through ActionPack which depends on the sprockets gem, by default.
By having this as a core feature of Rails, all developers can benefit from the power of having their assets pre-processed, compressed and minified by one central library, Sprockets. This is part of Rails’ “Fast by default” strategy as outlined by DHH in his 2011 keynote at Railsconf."
This looks like a really nice addition to Rails, and I look forward to enjoy its benefits. Unfortunately so far it has only brought me a slight feeling of pain, maybe because I have not started any Rails 3.1 application from scratch, but have only tried it by upgrading existing Apps from Rails 3.0 (or even from Rails 2.3.5) to Rails 3.1.

I first tried to upgrade to Rails 3.1 before the final release. It was a day to try new things at work and I had decided to upgrade an app from Rails 2.3.10 to Rails 3.1.rc1, and from Ruby 1.8.7 to Ruby 1.9.2. I started by upgrading the Ruby version, which wasn't an issue. Just had to recompile the gems I was using with the new version of Ruby and it all worked quite well.

Then I upgraded the Rails version to 3.0 by following Ryan Bates' Railscasts on the subject, and by using the Rails upgrade plugin. This took a bit longer as the application is relatively big, and quite a few things changed from Rails 2.3.x to Rails 3.0. I also had to add bundler as I was not using it before, but in the end I managed to do it.

Next step was upgrading to Rails 3.1. I thought it would be a challenge but it turned up to be quite simple... except for the Asset Pipeline. At that time not even the guide that I link to in the top was available, or at least I didn't find it, and I struggled to get my javascripts and css stylesheets to work. As the day was coming to an end I stopped there and haven't gone back to it since.

This week I had another go at upgrading an App to Rails 3.1. This time the application was in Rails 3.0.x, and once again everything went smoothly except for the Asset Pipeline.

My issue, I have found out, was related with the way I was using the application.js and application.css files. These files are used by Sprockets, the library that powers the Asset Pipeline, to know which js and css files are required by the application, they are named manifest files. In the different guides and documentation the examples of these files were something like:

So, in a noob action, I thought that the require_tree . directive would be enough to have all my javascript/css files properly included in the application. It turns out that, that, is not true. As some of my javascript files are dependent on other files my application was not working as expected, I needed to declare them in order in the manifest file for Sprockets to place them in order in the generated application.js file, and for the application to work.

I know this was probably my fault, but all the examples looked so tidy, and I didn't see any warning to be aware of this, that I was truly believing that Sprockets would make it all work. Like if it was magic!

Fortunately now I think that I got the hang of it and hopefully will be able to enjoy the power of the Asset Pipeline and of Rails 3.1.

For reference here are my manifest files, and they are not as tidy... If you know of a way to make them look better please let me know:


-----------------
Post-post: It seems that the guides state "For some assets (like CSS) the compiled order is important. You can specify individual files and they are compiled in the order specified:"... Guess another lesson is to try and read everything that is written in the Guides. :D Thanks to Décio to have pointed this out. =)

Tuesday, 16 August 2011

I must not forget what I've read #1

It might be lame to make a post with links to other people's text, and maybe that's Google+, Facebook, Twitter and GooglReader's job, but I just thought that it might be useful (at least to me) to keep track of some of the articles that I've read. For future reference or simply to spread the word. =)

* Vendor everything still applies: This strategy for using bundler and manage gems in a Rails project has been really useful for me, and has saved me plenty of time in deployment, and project sharing.

* A successful git branching model: Git is amazing and this branching model has been the one that has made more sense to me and which I have been using more often. The article also helped me understand Git better.

* Performance Testing Rails Applications - How To?: Looking forward to use this on my applications. Have a few in need of performance improvements.

* Dev Checks – Improving code quality by getting developers to look at each other’s work: I find it really interesting to learn how other people improve their programming skills and their code quality. I believe that showing our code to others will help us improve it, and don't worry if something embarrassing comes up... it's part of the fun. ;)

* Rails Best Practices 68: Annotate your models: I've been following this best practice in every project, this is really useful and saves loads of time when trying to figure out what's inside a model!

Thursday, 26 May 2011

Choosing the best way #1

Yesterday I was building a method to populate my chart, with Ruby on Rails, and was trying to think of the best way to get the array of years and the array of series to my view. Both would be obtained from a set of 'arrangements' associated with the current user.


I didn't want a messy controller so most of the action would happen in the model. Still I was not sure if I should have two instance variables (one array for the years and an hash for the series) or only one (an hash with information about the years and the series). So I defined three ways to do this and asked for opinions from my colleagues to help me decide.



The first alternative would need two methods in the model. The second one and the third would need only one method. But the third way could make it a bit confusing, some said.

I ended up going for the second alternative, but I must say that the third one also attracted me for it's use of that interesting ruby functionality (returning multiple results from a method).

Which one would you choose? A completely different way to do this?