Coder Social home page Coder Social logo

sedubois / mobility-actiontext Goto Github PK

View Code? Open in Web Editor NEW
35.0 35.0 9.0 249 KB

Translate Rails Action Text rich text with Mobility.

License: MIT License

Ruby 87.50% JavaScript 0.13% CSS 1.43% HTML 10.94%
action-text i18n localization mobility rails rich-text ruby-gem ruby-on-rails translation

mobility-actiontext's Introduction

๐Ÿ‘‹ Software engineer and full-stack web developer with 15 years of experience. Contact me and let's make your project a success.

Web frameworks of choice: Ruby on Rails, Hotwire Javascript (Stimulus, Turbo), Tailwind CSS. Mobile: Kotlin, Turbo Native, Android Jetpack Compose, Play Billing, Play Integrity. Stripe payments, Intercom, DaVinci Resolve audio-video editing, English-French translation, GitHub Actions, Kamal (Docker), Java.

Past occupations:

  • 7 years CTO of Imagine Clarity, SaaS web and mobile Rails audio and video meditation app
  • Node and React open-source collaboration at @OpenCollective
  • Java cybersecurity REST APIs at F-Secure
  • 7 years Java proton therapy control system on-site deployment and in-house R&D at Ion Beam Applications
  • Master's degree in mechanical engineering with specialization in numerical simulations & fluid dynamics

My interests revolve around meditation and mind training (vipassana), spiritual teachings (Dharma, Stoic philosophy), plant-based nutrition, physics. I lived in 6 countries.

"Training the mind is crucial if we want to cultivate wholesome qualities such as vigilant attention, emotional balance, inner peace, compassion and wisdom." โ€”Matthieu Ricard


mobility-actiontext's People

Contributors

dependabot[bot] avatar doits avatar filippoliverani avatar gando001 avatar olimart avatar sedubois avatar thedarkside avatar timmitry avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

mobility-actiontext's Issues

Syntax for accessing records via query

giving the indices

add_index :action_text_rich_texts,              [:record_type, :record_id, :name, :locale]

and assuming a context of exporting a set of translated record_ids, what is the proper syntax for querying/accessing the table for such an array? struggled a bit with this for basic mobility

I believ it evolves from:
Mobility::Activerecord::StringTranslation
Mobility::Activerecord::TextTranslation
to
Mobility::Backends::ActionText::PlainTextTranslation
Mobility::Backends::ActionText::RichTextTranslation
?

Assuming klass.translatable_content column, how does one call a method, say

truncate(klass.translatable_content column, length: 200)

?

Ruby minimum versions

Looking at this gem it seems like it may fill a very obvious gap in the mobility core gem, but I'm wondering if the Ruby minimum version can be loosened to support all current Rails supported Ruby versions? For example, we have a number of applications using v2.6 for various reasons and we are unable to use this gem without forking or other techniques due to a fairly restrictive Ruby version.

Is this something technically limiting to Ruby 2.7 or just a design choice, or something that can ideally be changed to support a wider audience.

Rendering locale specific fields with Mobility.normalize_locale(locale) is not supported.

I've come across an issue where having a partial like this:

<% [:en, :ja].each do |locale| %>
  <% content = "content_#{Mobility.normalize_locale(locale)}" %>
  <%= form.label content do %>
    <%= "Content" %>
  <% end %>

  <%= form.rich_text_area content %> 
<% end %>

Throws this error:

unknown attribute 'locale' for Mobility::Backends::ActionText::RichTextTranslation.

This line is the cuprit but haven't been able to workout why just yet:

  <%= form.rich_text_area content %> 

What I'm trying to achieve is rendering locale specific fields in a single form. For example in a new article form, it would render the content field for :en and :ja locales. Is there a way to do this with rich text fields (works with other fields) and I'm missing something or could this be an issue?

Thanks for creating this Gem! ๐Ÿ™

error when destroying record

Hello, I have a strange error happening when destroying a record of my model that uses the :action_text backend, inserting and updating records works very well.

here's the relevant code in the model:

  extend Mobility
  translates :question, backend: :action_text
  translates :answer, backend: :action_text

and in the controller, very easy:

  def destroy
    @faq.destroy
    respond_with(:admin, @faq)
  end

that brings to the error:

PG::UndefinedColumn: ERROR:  column mobility_text_translations.record does not exist
LINE 1: ...ations".* FROM "mobility_text_translations" WHERE "mobility_...

the strange thing is that looking at the stack trace I see these line:

mobility (1.1.1) lib/mobility/backends/active_record/key_value.rb:198:in `block (3 levels) in <class:KeyValue>'
mobility (1.1.1) lib/mobility/backends/active_record/key_value.rb:198:in `block (2 levels) in <class:KeyValue>'
activesupport (6.0.3.5) lib/active_support/callbacks.rb:428:in `block in make_lambda'

so it looks like when destroying records is using the key_value backend instead of the action_text one.
Am I missing something in my configuration or is that a bug?

with_rich_text_#{name} eager loading does not work

This test currently does not pass:

test 'post content is eager loaded' do
post = assert_queries(2) { Post.with_rich_text_content.last }
assert_no_queries do
assert_equal 'Hello world!', post.content.to_plain_text
skip('FIXME: this should execute no queries')
end
end

Creating this issue for visibility, in case someone would be willing to investigate and offer a PR.

No plugin configured for these keys: type. (Mobility::Pluggable::InvalidOptionKey)

I got this error just after installing the gem

% rails c

/Users/name/.rvm/gems/ruby-3.1.2/gems/mobility-1.2.9/lib/mobility/pluggable.rb:51:in `validate_options': No plugin configured for these keys: type. (Mobility::Pluggable::InvalidOptionKey)
from /Users/name/.rvm/gems/ruby-3.1.2/gems/mobility-1.2.9/lib/mobility/plugins/backend.rb:100:in `validate_options'

guide.rb

class Guide < ApplicationRecord
  belongs_to :category
  extend Mobility
  translates :title, type: :string, locale_accessors: I18n.available_locales
  translates :content, type: :text, locale_accessors: I18n.available_locales, backend: :action_text
end

Gemfile

gem 'mobility'
gem "mobility-actiontext", "~> 1.1"

config/initializer/mobility.rb

Mobility.configure do
  # PLUGINS
  plugins do
    # Backend
    #
    # Sets the default backend to use in models. This can be overridden in models
    # by passing +backend: ...+ to +translates+.
    #
    # To default to a different backend globally, replace +:key_value+ by another
    # backend name.
    #
    backend :key_value

    # ActiveRecord
    #
    # Defines ActiveRecord as ORM, and enables ActiveRecord-specific plugins.
    active_record

    # Accessors
    #
    # Define reader and writer methods for translated attributes. Remove either
    # to disable globally, or pass +reader: false+ or +writer: false+ to
    # +translates+ in any translated model.
    #
    reader
    writer

    # Backend Reader
    #
    # Defines reader to access the backend for any attribute, of the form
    # +<attribute>_backend+.
    #
    backend_reader
    #
    # Or pass an interpolation string to define a different pattern:
    # backend_reader "%s_translations"

    # Query
    #
    # Defines a scope on the model class which allows querying on
    # translated attributes. The default scope is named +i18n+, pass a different
    # name as default to change the global default, or to +translates+ in any
    # model to change it for that model alone.
    #
    query

    # Cache
    #
    # Comment out to disable caching reads and writes.
    #
    cache

    # Dirty
    #
    # Uncomment this line to include and enable globally:
    # dirty
    #
    # Or uncomment this line to include but disable by default, and only enable
    # per model by passing +dirty: true+ to +translates+.
    # dirty false

    # Fallbacks
    #
    # Uncomment line below to enable fallbacks, using +I18n.fallbacks+.
    # fallbacks
    #
    # Or uncomment this line to enable fallbacks with a global default.
    # fallbacks { :pt => :en }

    # Presence
    #
    # Converts blank strings to nil on reads and writes. Comment out to
    # disable.
    #
    presence

    # Default
    #
    # Set a default translation per attributes. When enabled, passing +default:
    # 'foo'+ sets a default translation string to show in case no translation is
    # present. Can also be passed a proc.
    #
    # default 'foo'

    # Fallthrough Accessors
    #
    # Uses method_missing to define locale-specific accessor methods like
    # +title_en+, +title_en=+, +title_fr+, +title_fr=+ for each translated
    # attribute. If you know what set of locales you want to support, it's
    # generally better to use Locale Accessors (or both together) since
    # +method_missing+ is very slow.  (You can use both fallthrough and locale
    # accessor plugins together without conflict.)
    #
    # fallthrough_accessors

    # Locale Accessors
    #
    # Uses +def+ to define accessor methods for a set of locales. By default uses
    # +I18n.available_locales+, but you can pass the set of locales with
    # +translates+ and/or set a global default here.
    #
    # locale_accessors
    #
    # Or define specific defaults by uncommenting line below
    locale_accessors I18n.available_locales

    # Attribute Methods
    #
    # Adds translated attributes to +attributes+ hash, and defines methods
    # +translated_attributes+ and +untranslated_attributes+ which return hashes
    # with translated and untranslated attributes, respectively. Be aware that
    # this plugin can create conflicts with other gems.
    #
    # attribute_methods
  end
end

Does this gem also need mobility to be installed as well?

I followed your readme, which told me to add mobility-actiontext to my gem file, bundle install'ed, did the migration (although I had to add default: :en to the file in order to give all my existing rich text rows a locale) and then added extend Mobility to a model.

class Page < ApplicationRecord
  extend Mobility

  validates :title, :slug, :body, presence: true
  validates :slug, uniqueness: true

  translates :body, backend: :action_text
  translates :title, backend: :action_text, plain: true

  has_one_attached :featured_image do |attachable|
    attachable.variant :thumb, resize_to_limit: [50, 50]
  end
end

I am now getting uninitialized constant Page::Mobility errors. I am guessing that I need to install the base mobility gem - but I know that comes with its own generator and config file... I also see that according to my Gemfile.lock your gem includes mobility, so I'm not sure what the problem is.

Marks object as dirty even if nothing was changed in RichTextTranslation fields

Hi all, I am not 100% sure but I think I might have found an issue with Mobility's dirty option and using actions_text.

I have a model which includes two text areas with Trix. Content and Description. When submitting the edit form without changing any values the @song.saved_changes after @song.update shows that Mobility::Backends::ActionText::RichTextTranslation were saved even if the contents did not change.

Is this expected behaviour or it shouldn't happen? I assume those fields shouldn't save either since they haven't changed?

The mobility plugin configuration:

Mobility.configure do
  # PLUGINS
  plugins do
    # Backend
    #
    # Sets the default backend to use in models. This can be overridden in models
    # by passing +backend: ...+ to +translates+.
    #
    # To default to a different backend globally, replace +:key_value+ by another
    # backend name.
    #
    backend :key_value

    # Dirty
    #
    # Uncomment this line to include and enable globally:
    dirty
  end

The songs controller action:

  def update
    @song = Song.find_by(id: params[:id])

    # Allows all tags are removed on submission.
    # Otherwise it will the last one.
    if params.dig(:song, :tag_ids).nil?
      params[:song][:tag_ids] = []
    end

    if @song.update(song_params)
      puts @song.saved_changes.inspect # Mobility::Backends::ActionText::RichTextTranslation objects present.
      redirect_to songs_path
    else
      render :edit
    end
  end

The output in the terminal is the following when submitting the form without changing values, it only includes rich text fields for some reason:

{"updated_at"=>
  [Fri, 09 Dec 2022 04:11:06.660466000 UTC +00:00, Fri, 09 Dec 2022 04:12:23.104814000 UTC +00:00],
 "description_pt"=>
  [#<Mobility::Backends::ActionText::RichTextTranslation:0x000000011331df30
    id: nil,
    name: "description",
    body: nil,
    record_type: "Song",
    record_id: 4,
    created_at: nil,
    updated_at: nil,
    locale: "pt">,
   #<Mobility::Backends::ActionText::RichTextTranslation:0x000000011331df30
    id: nil,
    name: "description",
    body: nil,
    record_type: "Song",
    record_id: 4,
    created_at: nil,
    updated_at: nil,
    locale: "pt">],
 "content_pt"=>
  [#<Mobility::Backends::ActionText::RichTextTranslation:0x000000011331e250
    id: 18,
    name: "content",
    body: #<ActionText::Content "<!-- BEGIN app/views/l...">,
    record_type: "Song",
    record_id: 4,
    created_at: Fri, 09 Dec 2022 00:20:25.021014000 UTC +00:00,
    updated_at: Fri, 09 Dec 2022 00:20:25.021014000 UTC +00:00,
    locale: "pt">,
   #<Mobility::Backends::ActionText::RichTextTranslation:0x000000011331e250
    id: 18,
    name: "content",
    body: #<ActionText::Content "<!-- BEGIN app/views/l...">,
    record_type: "Song",
    record_id: 4,
    created_at: Fri, 09 Dec 2022 00:20:25.021014000 UTC +00:00,
    updated_at: Fri, 09 Dec 2022 00:20:25.021014000 UTC +00:00,
    locale: "pt">],
 "description_en"=>
  [#<Mobility::Backends::ActionText::RichTextTranslation:0x00000001133960c0
    id: nil,
    name: "description",
    body: nil,
    record_type: "Song",
    record_id: 4,
    created_at: nil,
    updated_at: nil,
    locale: "en">,
   #<Mobility::Backends::ActionText::RichTextTranslation:0x00000001133960c0
    id: nil,
    name: "description",
    body: nil,
    record_type: "Song",
    record_id: 4,
    updated_at: nil,
    locale: "en">],
 "content_en"=>
  [#<Mobility::Backends::ActionText::RichTextTranslation:0x000000011331e4f8
    id: 19,
    name: "content",
    body: #<ActionText::Content "<!-- BEGIN app/views/l...">,
    record_type: "Song",
    record_id: 4,
    created_at: Fri, 09 Dec 2022 00:20:25.022686000 UTC +00:00,
    updated_at: Fri, 09 Dec 2022 00:20:25.022686000 UTC +00:00,
    locale: "en">,
   #<Mobility::Backends::ActionText::RichTextTranslation:0x000000011331e4f8
    id: 19,
    name: "content",
    body: #<ActionText::Content "<!-- BEGIN app/views/l...">,
    record_type: "Song",
    record_id: 4,
    created_at: Fri, 09 Dec 2022 00:20:25.022686000 UTC +00:00,
    updated_at: Fri, 09 Dec 2022 00:20:25.022686000 UTC +00:00,
    locale: "en">]}

If the form is submitted and the title property is changed, it does include it (this works as it should):

{"updated_at"=>
  [Fri, 09 Dec 2022 04:25:58.481859000 UTC +00:00, Fri, 09 Dec 2022 04:26:29.673314000 UTC +00:00],
 "description_pt"=>
  [#<Mobility::Backends::ActionText::RichTextTranslation:0x0000000116a9dd48
    id: nil,
    name: "description",
    body: nil,
    record_type: "Song",
    record_id: 4,
    created_at: nil,
    updated_at: nil,
    locale: "pt">,
   #<Mobility::Backends::ActionText::RichTextTranslation:0x0000000116a9dd48
    id: nil,
    name: "description",
    body: nil,
    record_type: "Song",
    record_id: 4,
    created_at: nil,
    updated_at: nil,
    locale: "pt">],
 "content_pt"=>
  [#<Mobility::Backends::ActionText::RichTextTranslation:0x0000000116a9e040
    id: 18,
    name: "content",
    body: #<ActionText::Content "<!-- BEGIN app/views/l...">,
    record_type: "Song",
    record_id: 4,
    created_at: Fri, 09 Dec 2022 00:20:25.021014000 UTC +00:00,
    updated_at: Fri, 09 Dec 2022 00:20:25.021014000 UTC +00:00,
    locale: "pt">,
   #<Mobility::Backends::ActionText::RichTextTranslation:0x0000000116a9e040
    id: 18,
    name: "content",
    body: #<ActionText::Content "<!-- BEGIN app/views/l...">,
    record_type: "Song",
    record_id: 4,
    created_at: Fri, 09 Dec 2022 00:20:25.021014000 UTC +00:00,
    updated_at: Fri, 09 Dec 2022 00:20:25.021014000 UTC +00:00,
    locale: "pt">],
 "title_en"=>["Butter got spilt", "Butter got spilt edited"],
 "description_en"=>
  [#<Mobility::Backends::ActionText::RichTextTranslation:0x0000000116ade4b0
    id: nil,
    name: "description",
    body: nil,
    record_type: "Song",
    record_id: 4,
    created_at: nil,
    updated_at: nil,
    locale: "en">,
   #<Mobility::Backends::ActionText::RichTextTranslation:0x0000000116ade4b0
    id: nil,
    name: "description",
    body: nil,
    record_type: "Song",
    record_id: 4,
    created_at: nil,
    updated_at: nil,
    locale: "en">],
 "content_en"=>
  [#<Mobility::Backends::ActionText::RichTextTranslation:0x0000000116a9e2e8
    id: 19,
    name: "content",
    body: #<ActionText::Content "<!-- BEGIN app/views/l...">,
    record_type: "Song",
    record_id: 4,
    created_at: Fri, 09 Dec 2022 00:20:25.022686000 UTC +00:00,
    updated_at: Fri, 09 Dec 2022 00:20:25.022686000 UTC +00:00,
    locale: "en">,
   #<Mobility::Backends::ActionText::RichTextTranslation:0x0000000116a9e2e8
    id: 19,
    name: "content",
    body: #<ActionText::Content "<!-- BEGIN app/views/l...">,
    record_type: "Song",
    record_id: 4,
    created_at: Fri, 09 Dec 2022 00:20:25.022686000 UTC +00:00,
    updated_at: Fri, 09 Dec 2022 00:20:25.022686000 UTC +00:00,
    locale: "en">]}

Expected behaviour

Enabling the dirty plugin and running @song.saved_changes should be empty if none of the values we're changed.

For example, when no changes are made to the form saved_changes would be {} and when a change is made it would be:

{
 "title_en"=>["Butter got spilt", "Butter got spilt edited"]
}

Actual behaviour

RichText fields are added saved_changes even if they're not modified in the form.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.