Ruby/Rails:调用实例时是否可以执行默认方法(@instance == @instance.all IF“all”是默认方法)?

发布于 2024-09-28 14:19:46 字数 1292 浏览 3 评论 0原文

我知道我的问题有点模糊,但我不知道如何描述它。我问过很多地方,但似乎没有人理解我为什么要这样做。但请耐心等待,我会解释为什么我想要这样的东西。

我正在使用 Liquid 模板来允许用户在我的网站上制作一些动态页面。对于那些不知道的人来说,Liquid 使用他们的一个名为 LiquidDrop 的类来向用户公开某些项目。 Liquid 模板可以调用 drop 中的任何方法。

class PageDrop < Liquid::Drop
  def initialize(page)
    @page = page
  end

  def name
    @page.name
  end

  def children
    PagesDrop.new(@page.children)
  end
end
class PagesDrop < Liquid::Drop
  def initialize(pages)
    @pages = pages
  end

  def group_by
    GroupByDrop.new(@pages)
  end

  def all
    @pages.all
  end

  def size
    @pages.size
  end
end

例如,我希望能够执行以下操作:

@page_drop = PageDrop.new(@page)
@page_drop.children # to get an array of children

而不是

@page_drop.children.all

“为什么我有页面丢失?”

因为我希望能够干净地划分可以对页面数组执行的方法和可以对单个页面执行的方法。这允许我像这样对页面进行分组:

@page_drop.children.group_by.some_method_here_that_the_group_drop_contains

为了让我的用户更简单,我不希望他们必须考虑添加“全部”或不添加到删除实例来获取它包含的“默认”对象。重申一下:

@pages_drop = PagesDrop.new(Page.all)

@pages_drop == @pages_drop.pages #I want this to be true, as well as
@pages_drop == @pages_drop.all

我从哪里得到这个想法?

在 Rails 中,当您对其执行某些操作时,作用域(关联对象)(@person.friends) 似乎会返回数组:@person.friends.each,对于 @person.friends 中的人

I understand my question is a bit vague but I don't know how else to describe it. I've asked in numerous places and no one seems to understand why I want to do this. But please bear with me, and I'll explain why I want something like this.

I'm using Liquid Templates to allow users to make some dynamic pages on my site. And for those that don't know, Liquid uses a class of theirs called LiquidDrop to expose certain items to the user. Any method in the drop can be called by the Liquid template.

class PageDrop < Liquid::Drop
  def initialize(page)
    @page = page
  end

  def name
    @page.name
  end

  def children
    PagesDrop.new(@page.children)
  end
end
class PagesDrop < Liquid::Drop
  def initialize(pages)
    @pages = pages
  end

  def group_by
    GroupByDrop.new(@pages)
  end

  def all
    @pages.all
  end

  def size
    @pages.size
  end
end

For example, I want to be able to do this:

@page_drop = PageDrop.new(@page)
@page_drop.children # to get an array of children

instead of

@page_drop.children.all

Why do I have a pages drop?

Because I want to be able to cleanly split up the methods I can do to an array of pages, and methods I can do to a single page. This allows me to group pages like so:

@page_drop.children.group_by.some_method_here_that_the_group_drop_contains

To make it simpler for my users, I don't want them to have to think about adding "all" or not to a drop instance to get the "default" object/s that it contains. To reiterate:

@pages_drop = PagesDrop.new(Page.all)

@pages_drop == @pages_drop.pages #I want this to be true, as well as
@pages_drop == @pages_drop.all

Where did I get this idea?

In Rails, a scope (association object) (@person.friends) seems to return the array when you do certain things to it: @person.friends.each, for person in @person.friends

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不如归去 2024-10-05 14:19:46

这实在是不可能的。当您编写@instance时,您实际上并没有像您所描述的那样调用实例,而是获得对@instance对象的引用指。

它似乎与 Rails 关联的集合一起工作的原因是关联对象是 Array 的实例,它们的一些方法已被重写。

如果您想要一种简洁的方式来表达分组,我会考虑删除 PagesDrop 并使用 group_by(&:method) 语法。如果您确实想保留它,那么您可以通过在 PagesDrop 上实现 each[] 并让它们委托来实现您想要的目标至@pages。例如,这将允许您在 for 循环中使用 @page_drop.children

This isn't really possible. When you write @instance you aren't really calling an instance as you describe, you're getting a reference to the object that @instance refers to.

The reason it seems to work with the collections for Rails' associations is that the the association objects are instances of Array that have had some of their methods overridden.

I would consider removing PagesDrop and using the group_by(&:method) syntax if you want a concise way to express groupings. If you do want to keep it then you can get some way towards what you want by implementing each and [] on PagesDrop and having them delegate to @pages. That will let you use @page_drop.children in for loops, for instance.

猫卆 2024-10-05 14:19:46

看起来您想在 Rails 之外实现 has_many 。下面的工作会起作用吗?

class PageDrop < Liquid::Drop
  attr_accessor :children
  def initialize(page)
    @page = page
    @children = []
  end

  def name
    @page.name
  end
end

这允许您执行以下操作:

@page_drop = PageDrop.new(@page)
@page_drop.children.size # => 0
@page_drop.children # => []

这还为您提供了所有标准数组函数(group_by、size、each 等)。如果您想添加自己的方法,请创建一个继承自 Array 的类并在其中添加您的方法。

class PageArray < Array
   def my_method
     self.each{|a| puts a}
   end
end

class PageDrop < Liquid::Drop
  attr_accessor :children
  def initialize(page)
    @page = page
    @children = PageArray.new
  end
  [...]
end

@page_drop = PageDrop.new(@page)
@page_drop.children.size # => 0
@page_drop.children # => []
@page_drop.children.my_method # Prints all the children

然后,您未在 PageArray 中定义的任何函数都会落入 Ruby Array 方法。

It looks like you want to implement has_many outside of rails. Will the following work?

class PageDrop < Liquid::Drop
  attr_accessor :children
  def initialize(page)
    @page = page
    @children = []
  end

  def name
    @page.name
  end
end

This allows you to do the following:

@page_drop = PageDrop.new(@page)
@page_drop.children.size # => 0
@page_drop.children # => []

This also gives you all the standard array functions (group_by, size, each, etc). If you want to add your own methods, create a class that inherits from Array and add your methods there.

class PageArray < Array
   def my_method
     self.each{|a| puts a}
   end
end

class PageDrop < Liquid::Drop
  attr_accessor :children
  def initialize(page)
    @page = page
    @children = PageArray.new
  end
  [...]
end

@page_drop = PageDrop.new(@page)
@page_drop.children.size # => 0
@page_drop.children # => []
@page_drop.children.my_method # Prints all the children

Then any functions you don't define in PageArray fall through to the Ruby Array methods.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文