Search code examples
ruby-on-rails-3activerecordnested-attributesjquery-tokeninput

jQuery TokenInput plugin with deep nested_attributes pre-populating tokens on edit


I have the following structure working on my application.

class Foo < ActiveRecord::Base
  has_many :examples, :dependent => :destroy

  accepts_nested_attributes_for :examples
end

class Example < ActiveRecord::Base
  belongs_to :foo
  has_many :codes, :dependent => :destroy

  accepts_nested_attributes_for :codes, :reject_if => lambda { |a| a[:code].blank? }
end
class Code < ActiveRecord::Base
  belongs_to :example
  has_many :code_kinds
  has_many :kinds, :through => :code_kinds
  attr_reader :kind_tokens

  def kind_tokens=(ids)
    self.kind_ids = ids.split(",")
  end
end
class CodeKind < ActiveRecord::Base

  belongs_to :code
  belongs_to :kind

end
class Kind < ActiveRecord::Base
    has_many :code_kinds
    has_many :codes, :through => :code_kinds   
end

And it's working perfectly for the form with fields_for on create and save.

I'm using kind_tokens as described on RailsCast #258 Token Fields

But on the edit form everything displays perfectly now I should be pre-populating the data in a data-pre attribute on the kind_tokens field inside the nested attributes for code in examples.

The RailsCast say:

<%= f.text_field :author_tokens, "data-pre" => @book.authors.map(&:attributes).to_json %>

But I can't do @foo.examples.codes.kinds.map... because the relation with Foo and examples returns a collection, the same situation with codes.

I'm just using:

<%= f.fields_for :codes do |codes_form| %>

That's inside of

<%= f.fields_for :examples do |examples_form| %>

Now how can I pre-populate the kind for code if I don't have any loop, and everything's done by nested_attributes and fields_for ?


Solution

  • Solved

    Everytime you use a

    <%= f.fields_for ...

    Rails automatically makes a loop so you can have some kind of counter there like:

    <%
    @ctrEx = 0
    @ctrCd = 0
    %>
    <%= form_for @foo ...
        <%= f.fields_for :examples do |examples_form| %>
            ...
    
            <%= examples_form.fields_for :codes do |codes_form| %>
                ...
                <%= codes_form.text_field :kind_tokens, :class => "tag_matcher", "data-pre" => @foo.examples[@ctrEx].codes[@ctrCd].kinds.map(&:attributes).to_json %>
                ...
                <%@ctrCd +=1%>
            <%end%>
    
            ...
            <%
            @ctrEx += 1
            @ctrCd = 0
            %>
        <%end%>
    <%end%>
    

    Now you can use your counters in the data-pre like this:

    @foo.examples[@ctrEx].codes[@ctrCd].kinds.map(&:attributes).to_json
    

    That's the way i figured it out, but there must be another way.