0

As I'm pretty much a beginner with Rails I wanted to know how best to loop through an array and modify some values. The array is being rendered to a view where the jQuery will receive the data and display it. I want to do the hard work in the Controller (or I might switch to the model at a later date).

The array is called @invoices but in the array is a timestamp which I want to format.

The code to format is:

Time.at(@invoice.date).strftime("%d/%m/%Y")

Could someone show me how to loop through and overwrite the timestamp value

4 Answers 4

2

One possible syntax for a ruby loop would be.-

@invoices.each do |invoice|
    invoice.date = Time.at(invoice.date).strftime("%d/%m/%Y")
end
Sign up to request clarification or add additional context in comments.

6 Comments

thanks - I actually had this at one point - its the DO YOUR STUFF bit that is going wrong!
would it be @invoices.date = Time.at(invoice.date).strftime("%d/%m/%Y")
@tommyd456 not @invoice, just invoice. The block's variable is defined by |invoice|, nothing is setting @invoice for you.
that's it - I was soooo close! ha ha - I will tick as correct when it lets me
I said I would tick it on my previous comment! ha ha
|
1

Actually what you concerned is how to present the data. This is not the logic belongs to controller.

A better way is to do it in model. Suppose you using JSON to render data to jQuery, you just need to add a present method and override as_json

class Invoice < ActiveRecord::Base
  # Add a method to present the original date
  def formatted_date
    Time.at(self.date).strftime("%d/%m/%Y")
  end

  # Include above method in Controller's to_json and remove old :date
  def as_json(options)
    super(method: :formatted_date, except: :date)
  end
end

Then in controller you need to do nothing.

13 Comments

Yeah I mentioned that I might shift logic to model in my question so this is great - thanks
but which bit goes where? I'm not quite sure about your second comment in your sample code
I should mention that the data I'm using is from an API which is already formatted to json
Tommy, your controller will call to_json, so what you need to do it to manipulate the to_json output in model level which will need change on as_json. This is not controller's business.
If data is from API it's still a model. If you are not using model to represent the API result but deal with it in controller, you are wrong.
|
0

I wasn't clear if you are sending just the dates to JQuery. If so, you can do this in your controller:

respond_to do |format|
   format.html { render :json => @invoices.collect {|invoice| invoice.date.strftime("%d/%m/%Y")} }
end

Note the absence of @ before invoice within the block since invoice is the alias for the individual element in the array currently being processed.

If you want the whole invoice, it is only slightly more complicated, and there is a bunch of Ruby cleverness that can minimize the number of lines.

1 Comment

I'm sending the invoices array to jQuery where I will then iterate through the results - I just thought it would be best to sort the date into the desired format before sending.
0

You should not change your data, if you only want to to display it in a specific format.

Rails allows you to change the format how a Date is rendered in views (specific per locale):

# config/locales/en.yml
en:
  time:
    formats:
      my_format: "%d/%m/%Y"

# in the view
<%= l invoice.date, format: :my_format %>

(see: http://guides.rubyonrails.org/i18n.html#adding-date-time-formats)

Or (if you do not need locale support) you add our own format to the to_formatted_s method:

# in config/initializers/date_formats.rb
Date::DATE_FORMATS[:my_format] = "%d/%m/%Y"
Time::DATE_FORMATS[:my_format] = "%d/%m/%Y"

# in the view
<%= invoice.date.to_s(:my_format) %>

(see: http://api.rubyonrails.org/classes/Time.html#method-i-to_formatted_s)

2 Comments

but it's jQuery that's rendering the data
It is not clear how you send your data. Even if you send your data directly via render :json => @invoices It would be better to use a date format that is defined globally: Than use my second approach with @invoices.map { |invoice| invoice.date.to_s(:my_format) } If you give it a better name that my_format it is reusable everywhere in the app and you do not need to remember this pattern "%d/%m/%Y". And it is easier to change to another pattern later.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.