#ruby-on-rails #activerecord
#ruby-on-rails #activerecord
Вопрос:
Мое приложение управляет классификациями, в которых несколько списков значений связаны для создания иерархии. Таблица values_to_values реализует связи между значениями для всех классификаций:
class Value < ApplicationRecord
attr_accessor :classification_id
has_many :values_to_values
has_many :child_values, through: :values_to_values
для которых N-N ссылок хранятся в:
# Table name: values_to_values
#
# id :integer not null, primary key
# classification_id :bigint
# parent_values_list_id :bigint
# child_values_list_id :bigint
# parent_value_id :bigint
# child_value_id :bigint
В результате значение может быть задействовано в нескольких иерархиях.
При отображении иерархии я запрашиваю таблицы value_to_values столько раз, сколько уровней содержит иерархия. Чтобы получить только ссылки, относящиеся к текущей классификации, мне нужно распространить classification_id и включить его в запрос.
Я создал метод get_children в values_controller и добавил атрибут classification_id в модель значений. Чтобы извлечь дочерние значения, я фильтрую values_to_values с помощью распространяемого атрибута classification_id:
# GET children from @classification values, including translations for child index
def get_children
@values = @value.child_values.where("values_to_values.classification_id = ?", @value.classification_id).includes(:name_translations).order(:code)
@values.each do |child|
child.classification_id = @value.classification_id
end
respond_to do |format|
format.html { render :index } # index.html.erb
format.json { render json: @values }
format.js # uses specific template to handle js
end
end
Затем я бы присвоил идентификатор классификации виртуальному атрибуту classification_id для распространения на следующий уровень иерархии. На первом уровне classification_id передается через параметр url, но, работая с js в DOM на следующих уровнях, я больше не могу использовать параметр (или я не знаю, как это сделать).
$(function () {
var itemId = '<%= @values_list.id %>',
ctId = 'ui-nav-values_list-' itemId '-children',
// create children array (code generated server side)
children = [
<% @values.each do |child| %>
{
id: '<%= child.id %>',
code: '<%= child.code %>',
classification_id: '<%= child.classification_id %>',
name: '<%= j(translation_for(child.name_translations)) %>',
url: '<%= url_for(child) %>',
loadUrl: '<%= url_for(get_children_value_path(child)) %>',
hasChildren: <%= (!child.child_values.empty?).to_json %>
},
<% end %>
];
$('#' ctId).sisNavigation({
children: children,
childLevelId: 'value'
});
});
К сожалению, виртуальный атрибут classification_id отсутствует в json, поэтому запрос не возвращает дочерних объектов.
- Это правильный способ достижения этой цели?
- Как получить набор данных @values, включающий виртуальный атрибут?
Ответ №1:
Я нашел ответ parial:
О attr_accessor :classification_id
, я, наконец, создал атрибут physicall в таблице значений, который используется только здесь (плохое решение!).
Что касается распространения параметра classification_id, я обновил код, чтобы определенно использовать его в качестве параметра:
get_children.js.erb
$(function () {
var itemId = '<%= @values_list.id %>',
ctId = 'ui-nav-values_list-' itemId '-children',
// create children array (code generated server side)
children = [
<% @values.each do |child| %>
{
id: '<%= child.id %>',
code: '<%= child.code %>',
classification_id: '<%= child.classification_id %>',
name: '<%= j(translation_for(child.name_translations)) %>',
url: '<%= url_for(child) %>',
loadUrl: '<%= url_for(get_children_value_path(child, classification_id: child.classification_id)) %>',
hasChildren: <%= (!child.child_values.empty?).to_json %>
},
<% end %>
];
$('#' ctId).sisNavigation({
children: children,
childLevelId: 'value'
});
});
values_controller
# GET children from @classification values, including translations for child index
def get_children
#@values = @value.child_values.where("values_to_values.classification_id = ?", @classification.id).includes(:name_translations).order(:code)
@values = @value.child_values.where("values_to_values.classification_id = ?", params[:classification_id]).includes(:name_translations).order(:code)
@values.each do |child|
child.classification_id = params[:classification_id]
end
respond_to do |format|
format.html { render :index } # index.html.erb
format.json { render json: @values }
format.js # uses specific template to handle js
end
end
Замечания и альтернативные решения приветствуются!