5

I have a Phrase class that has_many Phrase as Translation.

app/models/phrase.rb

class Phrase < ActiveRecord::Base
  has_many :translatabilities
  has_many :translations, through: :translatabilities
  has_many :inverse_translatabilities, class_name: "Translatability", foreign_key: "translation_id"
  has_many :inverse_translations, through: :inverse_translatabilities, source: :phrase
  accepts_nested_attributes_for :translatabilities
end

app/models/phrases_controller.rb

class PhrasesController < ApplicationController
  def index
    @phrases = Phrase.all.page params[:page]
    @translations = @phrases.count.times.map do |i|
      translation = Phrase.new
      translation.translatabilities.build
      translation
    end
  end
end

And I want to add "translatability" forms for each "phrase".

app/views/phrases/index.html.erb

<table>
  <tbody>
  <% @phrases.each do |phrase| %>
      <tr>
        <td><%= phrase.text %></td>
      </tr>
      <tr>
        <td>
          <%= form_for @translations do |f| %>
              <%= f.text_field :text %>
              <%= f.submit 'translate' %>
              <%= f.fields_for :translatabilities do |t_form| %>
                  <%= t_form.hidden_field :id %>
              <% end %>
          <% end %>
        </td>
      </tr>
    <% end %>
  </tbody>
</table>

This code has infinite loop bug.

undefined method `phrase_phrase_phrase_phrase_phrase_phrase_...

How can I create forms for translation of original phrases?

app/models/translatability.rb

class Translatability < ActiveRecord::Base
  belongs_to :phrase
  belongs_to :translation, :class_name => 'Phrase'
end
benjamin
  • 2,185
  • 1
  • 14
  • 19
ironsand
  • 14,329
  • 17
  • 83
  • 176
  • [Check this questionhere](http://stackoverflow.com/questions/33510519/collection-through-other-models-rails-4/33511017#33511017) – x6iae Dec 09 '15 at 08:44
  • I know STI. Should I use STI in this case? – ironsand Dec 09 '15 at 08:55
  • yes. so, you can have both an original phrase, as well as a translated phrase. By so, you can have a single table inheritance to phrase. – x6iae Dec 09 '15 at 08:58
  • No, a phrase instance is treated also a translation of other phrases, like a `Friend` is a `User` same time, but you can't make a `Friend` class with STI. Am I misunderstanding? – ironsand Dec 09 '15 at 09:06
  • If you would want to make a `Friend` using STI all you would need to do is inherit from `User` like `class Friend < User; end`. You could do the same with `Translation` and `Phrase` –  Dec 09 '15 at 09:12
  • wait, you are using `translations`..., and especially, `translatabilities`. Where is your `translatability` model? could you show that? – x6iae Dec 09 '15 at 09:17
  • `translatabilities` is a intermediate table for many to many relationships. (I doubt that I choose a good word, though.) I added the model in my question – ironsand Dec 09 '15 at 13:10

1 Answers1

2

I think you might be complicating things a bit with this method. If I understand correctly, you have Phrases that can be translated into multiple languages. It seems to me that what you really want to have is a Phrase model that defines the language and has a reference to allow other translations to be related.

Phrase would look something like this:

create_table :phrases do |t|
  t.text :body
  t.string :locale
  t.integer :translation_ref_id
end

In the Phrase model you can define translations methods:

def translations
  self.class
    .where(translation_ref_id: translation_ref_id)
    .where.not(id: id)
end

In your form, you would have multiple Phrases instead of a single Phrase with nested attributes. And in the controller, you would set the translation_ref_id for each of the Phrases (you could use any unique identifier, incrementing integer ids are good; you don't need a separate model to keep track of ids).

  • As far as I know if `Phrase` model have a reference id for `Translation` model, that means `Translation` has_many `phrases`, isn't it? – ironsand Dec 11 '15 at 10:12
  • My answer is an example of how to relate phrases without using STI. Asking `Phrase` for its translations, returns other `Phrase` objects. –  Dec 11 '15 at 11:15