1

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?

  • I don't know ActiveAdmin so I don't think I can answer this question, but why are you updating `translations`? Why don't you just write to each attribute normally? i.e. permit `body` if that is the name of the attribute. You shouldn't need to worry about JSON at all, Mobility and Rails will handle that part. – Chris Salzberg Feb 09 '19 at 12:20
  • @ChrisSalzberg I want to be able to modify translations in bulk, I would have to swap locale to modify each translation this way. Unless I'm wrong about how Mobility would work in this case. – Michał Zając Feb 10 '19 at 16:09
  • @ChrisSalzberg I added my solution as an answer. Do you think there is any cleaner way of doing this? – Michał Zając Feb 12 '19 at 16:08

1 Answers1

0

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.

  • I'm not really following everything, but you shouldn't need to call `send("#{attribute_name}_backend")`, juts call `resource.send("#{attribute_name}=", translation.to_s, locale: locale.to_sym)`. I suspect the rest can be simplified further as well. – Chris Salzberg Feb 19 '19 at 06:18