Rails 3 - 扩展 gem 或插件中存在的模型

发布于 2024-12-08 15:17:35 字数 306 浏览 0 评论 0原文

在 RefineryCMS gem 中,有一个页面模型,用于从 CMS 中提取信息。该模型未在您当前的应用程序中定义,因此您无法修改其代码(除非您跳入 gem 代码)。

有没有一种方法可以修改现有模型中的方法,而不必在每次加载页面时应用更改?这是我尝试过的:

  1. Model.class_eval

  2. Model.send :include, MixinThatHasNewMethods

我也尝试过创建一个新类使用更新的方法并希望能够更新现有的类。

有什么想法吗?

In the RefineryCMS gem there is a Page model that is used to pull in information from the CMS. The model is not defined in your current app and therefore you cannot modify its code (unless you hop into the gem code).

Is there a way to modify the methods within an existing model without having to apply the changes each time a page is loaded? Here is what I have tried:

  1. Model.class_eval

  2. Model.send :include, MixinThatHasNewMethods

I've also tried creating a new class with the updated methods and hoping that would update the existing class.

Any ideas?

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

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

发布评论

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

评论(2

扛刀软妹 2024-12-15 15:17:35

Ruby 允许开发人员随时“更新”任何对象。

这意味着在 RefineryCMS 加载 Model 后,您可以重新打开该类并更新它:

class Model
    def new_method(value)
        ...
    end

    def existing_method(*args)
        ...
        super  # refer to the ovewriten method
    end
end

在您的情况下,RafineryCMS 是一个 RoR 应用程序,这意味着在加载服务器时,首先为 Rails 加载 ruby​​ 代码框架,然后是 RafineryCMS gem/插件,最后是您的自定义库(例如:lib 文件夹)。

这里重要的一点是代码的加载顺序,修改应该在真正的类代码之后加载。

那是在你的库或初始化程序中(不是一个真正的好地方,但它有效),你应该为 Model 类放置你的自定义方法。

编辑:我再次阅读你的问题,我不得不提到,你错了,你实际上可以从 gem 或插件更改类。
ruby 加载同一范围内的每个对象,并且所有对象都可以被覆盖。

在开发环境中,RoR 在每次请求时重新加载所有类(除非cache_classes = false)。有可能在第一次请求后,gem 会重新加载,并且您的更改会丢失。请注意在每次请求后重新加载库(仅在开发环境中)

PS:include & class_eval 也可以工作,重要的是覆盖以前加载的类

Ruby allows the developer to "update" any object, at anytime.

That means that after Model is loaded by RefineryCMS you can just reopen the class and update it:

class Model
    def new_method(value)
        ...
    end

    def existing_method(*args)
        ...
        super  # refer to the ovewriten method
    end
end

In your case RafineryCMS is an RoR app, that means while loading the server the ruby code is loaded first for the rails framework, then for the RafineryCMS gem/plugin and after all for your custom libraries (eg: lib folder).

The important point here is the loading order of the code, modification should be loaded after the genuine class code.

That is in your lib or initializers (not really a good place but it works) you should put your custome methods for the Model class.

EDIT: I was reading your question again, and I have to mention, that you are wrong, you actually can change a class from a gem or plugin.
ruby load every object in the same scope and all objects are accessible to be overwritten.

In development environment, RoR, reloads all classes (except if cache_classes = false) on every request. It is possible, that after the first request, the gem is reloaded and your changes are lost. Take care to reload your libraries after for every request (only in developement env)

PS: include & class_eval would work too, the important thing is too overwrite a previously loaded class

最终幸福 2024-12-15 15:17:35

如果我正确理解你的问题,你可以做这样的事情。

您可以按如下方式覆盖模型。假设您有以下类:

class User
 def name user_name
  p "my name is #{user_name}"
 end

 def age my_age
   p "age - #{my_age}"
 end

end

那么您可以通过以下方式调用此类:

user = User.new
user.name "sameera"
user.age 30

并且您将得到输出:

"my name is sameera"
"age - 30"

然后假设您只想更改 'name' 方法的行为,那么您可以重新-创建用户类并仅添加该方法,如下所示:

class User
 def name user_name
   p "my modified name #{user_name}"
 end 
end

您仍然可以按如下方式调用这两个方法:

user = User.new
user.name "sameera"
user.age 30

但这一次,您的输出将是:

"my modified name sameera"
"age - 30"

我认为您明白我的意思,希望这会有所帮助。

**注意:请确保在加载原始 User 类之前调用​​修改后的“User”类。

If I understand your question correctly, you can do something like this.

You may override the model as follows. Say you have the following class:

class User
 def name user_name
  p "my name is #{user_name}"
 end

 def age my_age
   p "age - #{my_age}"
 end

end

then you can call this class by:

user = User.new
user.name "sameera"
user.age 30

and you will get the output:

"my name is sameera"
"age - 30"

then say you want to change only the behavior of the 'name' method, the you can re-create the user class and add only that method as follows:

class User
 def name user_name
   p "my modified name #{user_name}"
 end 
end

and still you can call both the methods as follows:

user = User.new
user.name "sameera"
user.age 30

But this time, your output will be:

"my modified name sameera"
"age - 30"

I think you got my point, hope this helps.

**NOTE: make sure you call the modified 'User' class before you load the original User class.

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