This sectional will discuss how to create MarkdownContent models and defines associations on them, as well as how to define associations between MarkdownContent and ActiveRecord models.
To make a MarkdownContent, it only needs to inherit from MarkdownContent::Base
. Once you have done that, you can define attributes and associations on it to other MarkdownContent models.
MarkdownContent::Base
includes ActiveAttr::Model
to provide attribute functionality. Please see how to use the ActiveAttr gem's interface here.
You can define custom associations on your model using the belongs_to_content
, has_one_content
and has_many_content
methods like so:
module MarkdownRecord
module Demo
class Section < ::MarkdownRecord::Base
attribute :name
has_many_content :dsl_commands
end
end
end
module MarkdownRecord
module Demo
class DslCommand < ::MarkdownRecord::Base
attribute :name
attribute :description
belongs_to_content :section
end
end
end
Once the associations are defined, you will want to make sure your JSON objects in your markdown have the required fields. For the example above, the DslCommand model will automatically be given a section_id
field that will need to be populated in your markdown like so:
<!--model { "type": "dsl_command", "id": 6, "name": "directory_fragment", "section_id": 1 } -->
Then you can use the association in your code just like ActiveRecord associations:
Section.find(3).dsl_commands.all
=>
[#<DslCommand section_id: 1, description: "...", ...>, ...]
DslCommand.find(1).section
=> #<Section filename: "content_dsl", id: 3, name: "Content DSL", subdirectory: "content", type: "section">
has_many_content
will define a method that returns an MarkdownRecord::Association
object, which you can then chain queries onto. belongs_to_content
and has_one_content
will define methods that returns a single MarkdownContent model.
If a model is defined within a scope (using the scope
Content DSL command), then all its associations are assumed to be within that scope, and must point to other models that are within that scope.
Furthermore, when querying for models that are defined within a scope without using associations, you will need to provide the scope like so:
DslCommand.find(1, "v_0_1_3")
=> #<DslCommand description: "model is the main command...", scope: "v_0_1_3", scoped_id: "v_0_1_3:s:1", section_id: 3, subdirectory: "content", type: "dsl_command">
Or
DslCommand.where(:section_id => 3, :scope => "v_0_1_3").all
=> [#<DslCommand >,...]
Association methods do not need the scope
provided, since they are assumed to be in the same scope as the model instance you call them on.
You can easily integrate MarkdownRecord and ActiveRecord models together using the MarkdownRecord::ContentAssociations
module. Just include it in your ActiveRecord model like so:
class Product < ActiveRecord::Base
include MarkdownRecord::ContentAssociations
has_one_content :user_manual
has_many_content :research_notes
end
You can define the same associations as described for MarkdownRecord models for ActiveRecord models. An important difference between the two cases, however, is that there are no foreign keys on the MarkdownRecord models that point to ActiveRecord models. Instead, MarkdownRecord expects to find an attribute on the ActiveRecord model that can be used for querying the MarkdownRecord models. For example, the Product
model above should have a user_manual_id
column or attribute. This effectively makes has_one_content
and belongs_to_content
aliases for each other. In the case of has_many_content
, the model should have an attribute that is a JSON array of ids that point to the related MarkdownRecord models. In the example above, it would be called research_note_ids
.
The above content was rendered from source files at: content/v_0_1/custom_models_and_associations