Hello, we are 29 Steps. We build software using Ruby.

In a recent rails 3.0 project I was working on I had an interesting dilemma. I have two models, User and Member. Member is a subclass of User.

Now when a user logs into the system the system checks what roles and permissions each user has and then redirects them accordingly. e.g. if the user record has a role of ‘Member’ then we redirect them to the member section.

Now since Member is a subclass of User, we are using STI ( Single table inheritance ) within rails whereby all the member attributes are stored as columns within the single user table. Member has an additional method called active? which determines if the membership level is active or not. However, in the logic which checks where to redirect signins because only User objects are returned, each call to active? is made on the superclass of User and not Member. To fix this I could redefine active? within the User model but it means duplication of the active? method inside Members class.

Another alternative would be to convert the User model into a Member object. ActiveRecord instances have a method called becomes(klass) which takes the name of the class to convert to. The definition of becomes from the API docs as follows:

Returns an instance of the specified klass with the attributes of the current record. This is mostly useful in relation to single-table inheritance structures where you want a subclass to appear as the superclass.

Full link of the api can be found here: http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-becomes

Now we are going the other way round from superclass to subclass which is unorthodox but works in my case here. An example of what I ended up with:

A PhotoSet Posting

Example of refinerycms nested model links with image dialog

In a recent refinerycms project I noticed a strange bug / error after upgrading the system to one of rails’s security patches.

Within a custom engine model, there is a nested form which uses the cocoon gem to show and remove itself. Within the nested form itself, is a link to call the js image picker within refinerycms to select an image for upload. Problem is this: because the nested field is dynamic which means that the image selector link is not generated until the ‘Add This’ link is clicked and the nested form is on the screen, the image selector link does not get instantiated within a new nested model form.

This can be seen with this piece of js code from refinerycms-core ver 1.0.11, in public/javascripts/refinery/admin.js


  $(document).ready(function(){
    // other initialization code
init_modal_dialogs(); })

init_modal_dialogs() is a function which opens up a modal window in an iframe for selecting images or attachments. Since my dialog selectors are not going to be present until the nested fields are added, I bind the click event to the live action once the link is clicked. e.g.


  $('a.add_nested_image_link').live('click', function(e)){
     init_modal_dialogs()
   })

This fixes the dialog open and also shows the currently selected image within the nested form.

To remove the image or to replace it is a bit tricky.

Refinerycms by default uses a class of ‘.remove_picked_image’ to define the remove image link within the dialog. Here we have another problem. Since the dialog is not created until the nested model forms are added, we need to bind the ‘remove_picked_image’ links to the live event too else it won’t work:

Please note that the above only works if you are using a nested model form within your own engine in refinerycms with the cocoon gem.

Some screenshots are attached in the post preceding this.

I have just switched over to using the money and money-rails gems in a recent rails 3.2 app recently after having issues with the formatting and storing of currency values in a Mongoid db. Plus, the money-rails gems comes with some nifty view helpers to transform the values into suitable representations on the front end.

Below are some notes to remind myself how I managed to do this within a Rails 3.2 appli<codebe foRedefine the field within the mongoid document to be of type Money. e.g. Assuming we have a Product document with a field of price, we can define it as follows:

  1. nufield :price, type: Money

    Once defined the currency values will be stored as a hash in the document with the following structure:

    price: {"cents" => "100", "currency_iso" => "GBP"}
    

    The price value is converted into cents automatically by the gem e.g. 1 USD gets converted into 100 cents. The currency_iso sets the country code of the currency according to the iso 4217 standard which maps the country to a specific currency code.

    The price value is converted into cents automatically by the gem e.g. 1 USD gets converted into 100 cents. This is important to remember else you will end up with strange values.

    Since I will be accessing this value quite frequently i also added an index for it.

  2. Use the money-rails gem to help format the currency values inside views. The gem contains useful helper methods such as humanized_money_with_symbol and humanized_money to convert the currency value into a useful string representation for display.

  3. To help validate against the price value since it is set in a form, I still need to add some validations to make sure that the price value is present and valid.

    validates :price, :numericality => {greater_than_or_equal_to: 1.0}, :presence => true

    Money gem provides a numerical validator to catch non-integer values such as strings and this can be found inside the money-rails gem lib folder ‘lib/money-rails/active_model/validator.rb’

  4. Passing in a string value to a money object field through a form does not save it properly for the simple reason that the field is no longer of type string or decimal but of object Money hence any value will need to be converted first before it can be saved.

    To cate for this I created a before_save callback which formats the form value into a money object before saving it:

    before_save :format_price

    def format_price
    self.price = Money.new((BigDecimal.new(self.price.to_s).round(2) * 100).to_i, 'GBP')
    end


    The price value needs to be converted into its cents equivalent and its currency code set in the callback.

  5. To test that the attribute returns a Money object on successful save I have the following structure inside my rspec2 model specs:

    Note that within the tests, the numeric validator within money-rails is testing for the presence of strings and malformed decimal places while the other validations are added by myself.

I hope the above helps someone to get to grips with using Money and money-rails gems in their own projects. Please comment on better ways of doing the above if you have come across similar setup in your own projects.

A PhotoSet Posting

likeafieldmouse:

Sayaka Ganz - Emergence (2011) - Discarded plastic

Reblogged from not shaking the grass
A QUOTE

I’m not gonna sit around and waste my precious divine energy trying to explain and be ashamed of things you think are wrong with me.

Esperanza Spalding (via likeafieldmouse)

Reblogged from not shaking the grass
A Photo Posting
robotcosmonaut:

宇宙怪獣ガメラ
via gurafiku


Back to the eighties again

robotcosmonaut:

宇宙怪獣ガメラ

via gurafiku

Back to the eighties again

Reblogged from Robot Cosmonaut
A PhotoSet Posting

Just completed phase 1 of safagrow.com to make it mobile friendly or responsive. The home and blog sections are working and am working on the other sections of the site. Done using Zurb Foundation. Check it out on your mobile. safagrow.com