从网址获取记录

时间:2013-05-02 15:45:20

标签: ruby-on-rails ruby-on-rails-3

我知道这是一个非常简单的问题,但我想我的大脑和google-fu今天工作得不好。

假设我有一个活动,有注册人,他们可以使用一次或多次付款来支付活动费用。

我正在尝试创建与注册人相关联的付款(与活动相关联) 因此,我的付款应同时包含registrant_idevent_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_idregistrant_id

2 个答案:

答案 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方法将使未来的查询和对象构建变得更加容易,但如果您的对象具有非常松散的关系模型,您可能会发现它变得具有限制性或不自然,并且可以使用您的其他业务规则更好地编写等效关联。