如何在Ruby on Rails中嵌套两个级别的模型和访问记录?

时间:2016-09-03 09:01:04

标签: ruby-on-rails ruby activerecord models

我正在尝试在rails上创建一个todo列表应用程序,它有3个模型作为嵌套资源。

例如:

  • 用户:<asp:HiddenField ID="HiddenField1" runat="server" /> <script type="text/javascript"> function fillHiddenField(rowNumber, rowValue) { document.getElementById("<%= HiddenField1.ClientID %>").value = rowValue; }
  • TodoList:has_many :todo_lists&amp; has_many :todo_items
  • TodoItem:belongs_to :user&amp; belongs_to :todo_list

运行scope :completed, -> { where.not(completed_at: nil) }会返回用户的待办事项列表。

运行@user.todo_lists会返回待办事项列表的待办事项。

运行@todo_lists.todo_items会返回待办事项列表中已完成的待办事项。

但是

正在运行@todo_lists.todo_items.completed会返回错误:@user.todo_lists.todo_items

正在运行NoMethodError: undefined method 'todo_items'也会返回错误:@user.todo_lists.todo_items.completed

我们已尝试NoMethodError: undefined method 'todo_items'返回用户的所有待办事项,但我们无法添加@user.todo_lists.map(&:todo_items).flatten范围。

我是在正确的轨道上吗?

2 个答案:

答案 0 :(得分:3)

尝试使用has_many:通过关联。

在您的用户模型中定义关联:

int main()
{
    using namespace std;
    int* nums;
    int size;
    cout << "Enter size of array";
    cin >> size;
    nums = new int[size];
    string input;
    cout << "Enter numbers, separated by single space:\n";
    getline(cin, input);
    istringstream iss(input);
    string s;

    int i = 0;
    while (getline(iss, s, ' ') && i < size) {
        int num = atoi(s.c_str());
        nums[i] = num;
        printf("%d\n", num);
        ++i;
    }
    return 0;
}

你应该在没有先获得todo_lists的情况下获得todo_items。

has_many :todo_items, through: :todo_lists

使用地图,你就在正确的轨道上。

user.todo_items.completed

答案 1 :(得分:0)

您收到这些错误

1 -

@user.todo_lists.todo_items

NoMethodError: undefined method 'todo_items'. 

尝试

@user.todo_lists

这将返回您的活动记录数组或nil,但是如果您将获得nil,那么您将错误未定义的方法'todo_items'。为零级

现在您将获得数组结果,因此您无法使用此方法,因此您可以使用以下命令

@user.todo_lists.map{|m| {todo_lists: m, todo_items: m.todo_items}}

这将返回数组中的todo_lists,并且在todo_lists的第一条记录中,您将获得该todo_list的todo_items。 如果你想在命令

下面只使用todo项目
@user.todo_lists.map{|m| m.todo_items}

2 -

@user.todo_lists.map(&:todo_items).flatten.completed 

使用命令

@user.todo_lists.map(&:todo_items).flatten.collect(&:completed)