我想将一个参数传递给使用define_method定义的方法,我该怎么做?
在这个例子中,我创建了一个user没有profile,然后在profile为该用户创建一个.我尝试使用带有has_one关联的构建,但是爆炸了.我看到这个工作的唯一方法是使用has_many.本user应该只有最多只能有一个profile.
我一直在尝试这个.我有:
class User < ActiveRecord::Base
has_one :profile
end
class Profile < ActiveRecord::Base
belongs_to :user
end
Run Code Online (Sandbox Code Playgroud)
但当我这样做时:
user.build_profile
Run Code Online (Sandbox Code Playgroud)
我收到错误:
ActiveRecord::StatementInvalid: Mysql::Error: Unknown column 'profiles.user_id' in 'where clause': SELECT * FROM `profiles` WHERE (`profiles`.user_id = 4) LIMIT 1
Run Code Online (Sandbox Code Playgroud)
在rails中有一种方法可以有0或1个关联吗?
我想定义一个Date#next第二天返回的实例方法.所以我做了一个DateExtension模块,像这样:
module DateExtension
def next(symb=:day)
dt = DateTime.now
{:day => Date.new(dt.year, dt.month, dt.day + 1),
:week => Date.new(dt.year, dt.month, dt.day + 7),
:month => Date.new(dt.year, dt.month + 1, dt.day),
:year => Date.new(dt.year + 1, dt.month, dt.day)}[symb]
end
end
Run Code Online (Sandbox Code Playgroud)
使用它:
class Date
include DateExtension
end
Run Code Online (Sandbox Code Playgroud)
调用该方法d.next(:week)会使Ruby抛出错误ArgumentError: wrong number of arguments (1 for 0).如何使用模块中声明的next方法覆盖Date类中的默认方法DateExtension?
我感觉下面的解决方案
class Fixnum
def +(x)
self + x + 1
end
end
Run Code Online (Sandbox Code Playgroud)
不应该工作,因为+将递归调用.
这两个基本上是一回事吗?他们看起来和我很相似.
lambda表达式是否从Ruby借用了它的想法?
在python中,引用函数非常简单:
>>> def foo():
... print "foo called"
... return 1
...
>>> x = foo
>>> foo()
foo called
1
>>> x()
foo called
1
>>> x
<function foo at 0x1004ba5f0>
>>> foo
<function foo at 0x1004ba5f0>
Run Code Online (Sandbox Code Playgroud)
但是,它似乎在Ruby中有所不同,因为裸体foo实际上调用了foo:
ruby-1.9.2-p0 > def foo
ruby-1.9.2-p0 ?> print "foo called"
ruby-1.9.2-p0 ?> 1
ruby-1.9.2-p0 ?> end
=> nil
ruby-1.9.2-p0 > x = foo
foo called => 1
ruby-1.9.2-p0 > foo
foo called => 1
ruby-1.9.2-p0 > x
=> 1
Run Code Online (Sandbox Code Playgroud)
我如何实际将 …
class String
def hello
"world"
end
end
String.class_eval {
def world
"hello"
end
}
"a".world
=> "hello"
"b".hello
=> "world"
Run Code Online (Sandbox Code Playgroud)
他们似乎做了同样的事情 - 向现有类添加方法.那有什么区别?
Method#unbind返回UnboundMethod对方法的引用,稍后可以使用该方法将其绑定到另一个对象UnboundMethod#bind.
class Foo
attr_reader :baz
def initialize(baz)
@baz = baz
end
end
class Bar
def initialize(baz)
@baz = baz
end
end
f = Foo.new(:test1)
g = Foo.new(:test2)
h = Bar.new(:test3)
f.method(:baz).unbind.bind(g).call # => :test2
f.method(:baz).unbind.bind(h).call # => TypeError: bind argument must be an instance of Foo
Run Code Online (Sandbox Code Playgroud)
最初,我认为这非常棒,因为我预计它的工作方式与JavaScript的Function.prototype.call()/ 相似Function.prototype.apply().但是,要绑定方法的对象必须属于同一个类.
我能想到的唯一应用是,如果解除绑定方法,丢失原始实现(重新定义原始或单例类中的方法),然后重新绑定并调用它.
我想在某些课程中发生某些事情时收到通知.我想以这样的方式设置它,使得我在这些类中的方法的实现不会改变.
我以为我会有以下模块:
module Notifications
extend ActiveSupport::Concern
module ClassMethods
def notify_when(method)
puts "the #{method} method was called!"
# additional suitable notification code
# now, run the method indicated by the `method` argument
end
end
end
Run Code Online (Sandbox Code Playgroud)
然后我可以将它混合到我的类中,如下所示:
class Foo
include Notifications
# notify that we're running :bar, then run bar
notify_when :bar
def bar(...) # bar may have any arbitrary signature
# ...
end
end
Run Code Online (Sandbox Code Playgroud)
我的主要愿望是我不想修改:bar以使通知正常工作.可以这样做吗?如果是这样,我将如何编写notify_when实现?
此外,我正在使用Rails 3,所以如果有ActiveSupport或我可以使用的其他技术,请随时分享.(我查看了ActiveSupport :: Notifications,但这需要我修改bar方法.)
我注意到我可能想要使用"模块+超级技巧".我不确定这是什么 - 也许有人可以启发我?
这引发了我在1.9.2 Ruby中的SystemStackError(但在Rubinius中工作):
class Fixnum
def +(other)
self + other * 2
end
end
Run Code Online (Sandbox Code Playgroud)
但没有super了+(基于其他错误).
我如何访问原始+功能?