Replacing translations using ActiveAdmin - ruby

I'm trying to use Mobility in my Rails application with ActiveAdmin as administration panel.
I use Container backend with JSONB column.
I also have activeadmin_json_editor gem installed so it's not possible to produce bad JSON. Inside my admin resource I permit :translations attribute using StrongParams.
When editing translations using ActiveAdmin and submitting the form I get the following parameters:
2.5.3 (#<Admin::QuestionsController:0x00007fd466a9a690>):0 > permitted_params
=> <ActionController::Parameters {"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"DwSuN9M9cD27dR7WmitBSMKKgVjhW1om3xwxOJUhK41no8RWH1Xh6L9QNIhOc1NhPYtm5QnKJWh7KEIUvuehUQ==", "commit"=>"Update Question", "id"=>"37", "question"=><ActionController::Parameters {"translations"=>"{\"en\":{\"body\":\"dupa\"}}", "dimension_id"=>"6"} permitted: true>} permitted: true>
However once the update query gets processed my model has no translations at all:
2.5.3 (#<Admin::QuestionsController:0x00007fd466a9a690>):0 > resource.update(permitted_params["question"])
(0.4ms) BEGIN
↳ (pry):18
Dimension Load (0.4ms) SELECT "dimensions".* FROM "dimensions" WHERE "dimensions"."id" = $1 LIMIT $2 [["id", 6], ["LIMIT", 1]]
↳ (pry):18
(0.3ms) COMMIT
↳ (pry):18
=> true
2.5.3 (#<Admin::QuestionsController:0x00007fd466a9a690>):0 > resource
=> #<Question:0x00007fd45c284d98
id: 37,
body: nil,
translations: {},
created_at: Wed, 16 Jan 2019 12:17:38 UTC +00:00,
updated_at: Fri, 08 Feb 2019 12:07:00 UTC +00:00,
dimension_id: 6>
What am I doing wrong? Should I parse the JSON from the params and use resource.<attribute_name>_backend.write for each locale?

Since I didn't get any answers I dug around and came up with the following solution. In your resource admin model add:
controller do
def update
translations = JSON.parse(permitted_params.dig(resource.class.name.downcase, "translations"))
translations.each do |locale, attributes|
supported_attributes = attributes.select { |attribute_name, _| resource.class.mobility_attributes.include?(attribute_name) }
supported_attributes.each do |attribute_name, translation|
resource.send("#{attribute_name}_backend").send(:write, locale.to_sym, translation.to_s)
end
end
resource.save
redirect_to admin_questions_path
end
end
This is probably not really the proper way to mass update the translations but I couldn't figure out a better way to do this. Please keep in mind that this doesn't really care if the locale key is valid.

Related

How to correctly filter ruby enumerator

I have a array/enumarator of accounts. And all i want to do is filter by invoice_ref. So i basically want to split my array into multuple arrays with the same invoice_ref
Im still learning rails and i cant figure out the correct syntax on the select method. Most of the documentation deals with numbers and strings but i have an array of accounts
accounts.each.select do |invoice_ref|
invoice_ref == invoice_ref
end
I have no idea how to do this
We don't know how an account looks; it could be as simple as
p accounts.group_by( &:invoice_ref)
I hope you are trying to group the array with the same values:
['1', '1', '2', '2'] to [['1', '1'], ['2', '2']]
Try the below:
['1', '1', '2', '2'].group_by(&:itself).values
This is what an Account model looks like, this is just dummy data on dev
id: 21,
product_id: 108,
member_id: 20,
username: "5408",
realm: "infinity.co.za",
password: "9BtyPq3q",
comments: "",
contract_term: 1,
status: nil,
created_at: Mon, 11 May 2020 12:01:40 UTC +00:00,
updated_at: Wed, 20 May 2020 12:43:53 UTC +00:00,
invoiced: false,
invoice_ref: "4827132"
And when i do this
accounts.each.class => Enumarator
An I want to filter the Enumarator and group them by invoice_ref
Does that make sense ?

Ruby time zone handling when merging data

Two sets of data need to be merged to create a new DateTime object
def mergeDateTime(date_to_merge, time_to_merge)
DateTime.new(date_to_merge.year, date_to_merge.month,date_to_merge.day, time_to_merge.hour, time_to_merge.min, time_to_merge.sec)
end
querying #signature = Signature.where('playtime_id = ?', 514).first
returns
Signature id: 834,[...], created_at: "2017-06-27 05:16:52"
and querying #interruption = Interruption.where('playtime_id = ?', 514).first
returns
Interruption id: 190, [...], pause: "2017-06-27 06:46:19"
but running
mergeDateTime(#signature.created_at, #interruption.pause)
returns
Tue, 27 Jun 2017 08:46:19 +0000
which is wrong as it interpreted the data at GMT +2 and should have generated
Tue, 27 Jun 2017 06:46:19 +0000
How can this presumption of timezone adjustment be neutered? and take into account the offset of the timezone according to the date_to_merge date?
Specify the timezone with in_time_zone:
def mergeDateTime(date_to_merge, time_to_merge)
date_to_merge = date_to_merge.in_time_zone('UTC')
time_to_merge = time_to_merge.in_time_zone('UTC')
DateTime.new(
date_to_merge.year,
date_to_merge.month,date_to_merge.day,
time_to_merge.hour,
time_to_merge.min,
time_to_merge.sec
)
end
While the other answer points in the right direction, the moment of the conversion to UTC matters
ts_pause_raw = #interruption.pause.in_time_zone('UTC')
ts_pause = Time.parse(ts_pause_raw.to_s[11,8])
Then def mergeDateTime(date_to_merge, time_to_merge)can be called without further invocation of in_time_zone.
Occurring after, it is too late.

Easy way to generate http date (GMT) string in ruby

I need to generate an HTTP (GMT) date string in Ruby. This is because of a requirement of an API that I'm consuming.
What is an easy (out of the box) way to generate it?
I found that Ruby comes with a method for the Time class out of the box for this:
Time.now.httpdate # => "Thu, 06 Oct 2011 02:26:12 GMT"
The time class also supports the following methods
Time.now.iso8601 # => "2011-10-05T22:26:12-04:00"
Time.now.rfc2822 # => "Wed, 05 Oct 2011 22:26:12 -0400"
Source: http://ruby-doc.org/stdlib-2.0.0/libdoc/time/rdoc/Time.html#class-Time-label-Converting+to+a+String
does Time.now.getgm work for you?
Time.now.gmt? #=> fale
Time.now.getgm.gmt? #=> true

How to save a timezone correctly with Ruby and MongoId?

Please excuse me if this is a bit of a noob issue:
I have an app where users can set their own Timezones in their profile.
When someone adds a Lineup (app specific terminology), I do the following:
time = ActiveSupport::TimeZone.new(user.timezone).parse(
"Wednesday, 26 October, 2011 13:30:00"
)
# This outputs: 2011-10-26 13:30:00 +0200 - valid according to the user selected TZ
I then save the Lineup:
Lineup.create({
:date => time.gmtime,
:uid => user._id,
:pid => product._id
})
This should (in theory) save the date as gmtime, but I get the following when viewing the record:
{
"_id": ObjectId("4e9c6613e673454f93000002"),
"date": "Wed, 26 Oct 2011 13: 30: 00 +0200",
"uid": "4e9b81f6e673454c8a000001",
"pid": "4e9c6613e673454f93000001",
"created_at": "Mon, 17 Oct 2011 19: 29: 55 +0200"
}
As you can see the date field is wrong - it still maintaining the user timezone, it should be GMT, not timezone specific.
If I output time.gmtime, I get the right time (that should be saved):
2011-10-26 11:30:00 UTC (correct)
Any ideas how to save the GMT date so that it actually saves the GMT date?
It looks like you need to specify the field type of your date attribute. I would use a Time field if you want mongoid to handle the zones properly.
class Lineup
include Mongoid::Document
field :date, type: Time
end
You will also probably want to set the following in config/mongoid.yml
defaults: &defaults
use_utc: false
use_activesupport_time_zone: true
This sounds counterintuitive, but this is the current way to make mongoid use UTC as the default timezone.
Finally, have a look at the mongoid-metastamp gem. It will give you much better support for querying across multiple timezones, while still seamlessly working like a native Time field.

ROR + Ruby Date From XML API

By using XML API, I got date-time as "2008-02-05T12:50:00Z". Now I wanna convert this text format into different format like "2008-02-05 12:50:00". But I am getting proper way.
I have tried this one :: #a = "2008-02-05T12:50:00Z"
Steps
1. #a.to_date
=> Tue, 05 Feb 2008
2. #a.to_date.strftime('%Y')
=> "2008"
3. #a.to_date.strftime('%Y-%m-%d %H:%M:%S')
=> "2008-02-05 00:00:00
Suggest some thing ?
The to_date method converts your string to a date but dates don't have hours, minutes, or seconds. You want to use DateTime:
require 'date'
d = DateTime.parse('2008-02-05T12:50:00Z')
d.strftime('%Y-%m-%d %H:%M:%S')
# 2008-02-05 12:50:00
Use Ruby's DateTime:
DateTime.parse("2008-02-05T12:50:00Z") #=> #<DateTime: 2008-02-05T12:50:00+00:00 (353448293/144,0/1,2299161)>
From there you can output the value in any format you want using strftime. See Time#strftime for more info.

Resources