我知道这是一个非常简单的问题,但我想我的大脑和google-fu今天工作得不好。
假设我有一个活动,有注册人,他们可以使用一次或多次付款来支付活动费用。
我正在尝试创建与注册人相关联的付款(与活动相关联)
因此,我的付款应同时包含registrant_id
和event_id
。
我的网址如下所示:(嵌套路线)
http://mysite.com/events/1/registrants/1/payments/new
我的控制器看起来像:
def create
@event = Event.find(params[:event_id])
@registrant = Registrant.find(:first, conditions: {id: params[:registrant_id], event_id: params[:event_id]} )
@payment = Payment.new params[:payment]
end
我知道有一个很多更好的方法可以做到这一点,但我在使用正确谷歌的措辞时遇到问题:)
我应该使用什么语法让.new
自动了解event_id
和registrant_id
?
答案 0 :(得分:0)
直接设置id
属性并不是一个好习惯,因为id可能不会引用实际的数据库行。这里正常的做法是使用CanCan(https://github.com/ryanb/cancan),这似乎可以解决你所有的问题。
编辑:
如果您没有使用任何类型的身份验证,那么我会将加载方法放在before_filter
中以保持清洁:
before_filter :load_event
def load_event
@event = Event.find params[:event_id]
end
或定义一些时髦的通用加载器(不必要的元和复杂,不推荐):
_load_resource :event
def self._load_resource resource_type
before_filter do
resource = resource_type.constantize.find params[:"#{ resource_type }_id]
instance_variable_set :"@#{ resource_type }", resource
end
end
答案 1 :(得分:0)
根据评论中的讨论,有几种方法可以解决问题:直接方式和Rails方式。
创建相关对象的直接方法是使用问题中建议的new_object = ClassName.new
创建对象。然后获取创建对象的id并在现有对象上设置(直接使用existing_object.id = new_object.id
或通过其他方法(如果需要其他逻辑))。或者通过定义自定义初始值设定项在新对象上设置id,例如:
class Payment
def initializer id_of_registrant
@registrant_id = id_of_registrant
end
...
end
这种方法的优点是它允许您分配可能来自一系列具有不同类的对象的注册者ID,而不必处理不必要的或可能不正确的(对于您的解决方案)继承和多态。
Rails方式,如果您在注册人和“强制性”付款之间始终存在直接关系(1对1),则使用has_many或belongs_to关联,如Rails指南中所述:http://guides.rubyonrails.org/association_basics.html < / p>
对于问题中的示例类:
class Registrant < ActiveRecord::Base
has_one :payment
end
class Payment < ActiveRecord::Base
belongs_to :registrant
end
您将需要使用适当的迁移来创建与此一起使用的数据库表和外键。例如:
class CreateRegistrants < ActiveRecord::Migration
def change
create_table :registrants do |t|
t.string :name
t.timestamps
end
create_table :payments do |t|
t.integer :registrant_id
t.string :account_number
t.timestamps
end
end
end
当然,如果您的注册人只选择付款或进行多笔付款,那么您需要查看使用has_many关联。
使用has和belongs关联,您可以做以下好事:
@payment.registrant = @registrant
如果您已手动实例化对象,或
@payment.new(payment_amount)
@registrant = @payment.build_registrant(:registrant_number => 123,
:registrant_name => "John Doe")
如果您希望自动填充关联。
Rails指南中有很多示例,但根据我的经验,只有在您的实际用例中尝试最合适的示例才会显示是否存在无法预料的限制。 Rails方法将使未来的查询和对象构建变得更加容易,但如果您的对象具有非常松散的关系模型,您可能会发现它变得具有限制性或不自然,并且可以使用您的其他业务规则更好地编写等效关联。