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
?
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.