Rails:从另一个模型调用或delgate实例方法

时间:2016-03-12 15:56:33

标签: ruby-on-rails activerecord

我不确定我要做的是调用或委托其他模型的实例方法

以下是两个类似的问题:Ruby on Rails: Calling an instance method from another model

In rails how can I delegate to a class method

我有四个相关的模型:

订单has_many:reservations / belongs_to:order_status

OrderStatus has_many:order

预订belongs_to:order / belongs_to:reservation_status

ReservationStatus has_many:预订

我正在尝试做什么:

我想在订单的订单状态更新时更改预订的reservation_status_id。

型号:

order.rb

class Order < ActiveRecord::Base

  belongs_to :order_status
  has_many :reservations
  after_update :update_reservations

private
  def update_reservations
    if self.order_status_id == 2
      Reservation.update_status_completed
    end  
  end
end

reservation.rb

class Reservation < ActiveRecord::Base
    belongs_to :order
    belongs_to :reservation_status

    def update_status_completed
        self.reservation_status_id = 5
    end 
end

reservation_status.rb

class ReservationStatus < ActiveRecord::Base
    has_many :reservations
end

order_status.rb

class OrderStatus < ActiveRecord::Base
    has_many :orders
end

当订单的订单状态设置为2时,我想将预订的reservation_status_id更改为5.但是我收到未定义的方法错误'update_status_completed'。据我所知,rails无法找到预订模型中的update_status_completed。

这是日志:

   (0.0ms)  begin transaction
  Reservation Load (0.0ms)  SELECT "reservations".* FROM "reservations" WHERE "reservations"."order_id" = ?  [["order_id", 85]]
  SQL (1.0ms)  UPDATE "orders" SET "order_status_id" = ?, "updated_at" = ? WHERE "orders"."id" = ?  [["order_status_id", 2], ["updated_at", "2016-03-12 15:24:49.024769"], ["id", 85]]
   (6.0ms)  rollback transaction
NoMethodError: undefined method `update_status_completed' for #<Class:0x2abfbc8>
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.2.4/lib/active_record/dynamic_matchers.rb:26:in `method_missing'
        from C:/Users/Antonio/Desktop/RegiSportV01/regisports/app/models/order.rb:67:in `update_reservations'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:432:in `block in make_lambda'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:228:in `call'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:228:in `block in halting_and_conditional'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:506:in `call'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:506:in `block in call'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:506:in `each'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:506:in `call'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:92:in `__run_callbacks__'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:778:in `_run_update_callbacks'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.2.4/lib/active_record/callbacks.rb:310:in `_update_record'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.2.4/lib/active_record/timestamp.rb:70:in `_update_record'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.2.4/lib/active_record/persistence.rb:504:in `create_or_update'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.2.4/lib/active_record/callbacks.rb:302:in `block in create_or_update'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activesupport-4.2.4/lib/active_support/callbacks.rb:117:in `call'
... 12 levels...
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.2.4/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `block in transaction'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.2.4/lib/active_record/connection_adapters/abstract/transaction.rb:184:in `within_new_transaction'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.2.4/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `transaction'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.2.4/lib/active_record/transactions.rb:220:in `transaction'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.2.4/lib/active_record/transactions.rb:348:in `with_transaction_returning_status'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.2.4/lib/active_record/transactions.rb:286:in `block in save'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.2.4/lib/active_record/transactions.rb:301:in `rollback_active_record_state!'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/activerecord-4.2.4/lib/active_record/transactions.rb:285:in `save'
        from (irb):7
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.2.4/lib/rails/commands/console.rb:110:in `start'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.2.4/lib/rails/commands/console.rb:9:in `start'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.2.4/lib/rails/commands/commands_tasks.rb:68:in `console'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.2.4/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
        from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/railties-4.2.4/lib/rails/commands.rb:17:in `<top (required)>'
        from bin/rails:4:in `require'
        from bin/rails:4:in `<main>'irb(main):008:0>

1 个答案:

答案 0 :(得分:1)

在回调函数中执行...

在你的模型中

<!DOCTYPE html>
<html>
	<head>
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<link type="text/css" rel="stylesheet" href="./ok.css">
		<link type="text/css" rel="stylesheet" href="./Codepen project/animate.css">
		<link rel="stylesheet" href="./Codepen project/bootstrap-3.3.5-dist/css/bootstrap.min.css">
		<link type="text/css" rel="stylesheet" href="./Codepen project/font-awesome-4.5.0/css/font-awesome.min.css">
		<script src="./Codepen project/bootstrap-3.3.5-dist/js/bootstrap.min.js"></script>
		<script src="./Codepen project/jquery-2.2.1.min.js"></script>
		<script src="./ok.js"></script>
	</head>
	<body style="height:1000px;background-color:;" onscroll="scrollFunction">
		<div class="container" style="height:70px;">
			<div class="row">
				<div class="col-md-8">
					<table style="border-collapse:collapse;">
						<tr>
							<td style="padding-right:10px"><h1>Welcome to my Portfolio</h1></td>
							<td style="position:absolute;bottom:0;padding-left:10px;border-left: 1px solid black"><h3>In a bid to actualizing my dream...</h3></td>
						</tr>
					</table>
				</div>
				<div class="col-md-4" style="position:relative;height:70px;">
					<div id="contact" style="position:absolute;right:0px;bottom:0">
						<i class="fa fa-facebook-official fa-2x"></i>
						<i class="fa fa-twitter fa-2x"></i>
					</div>
				</div>
			</div>
		</div>

		<nav class="navbar navbar-default" id="nav">
			<div class="container-fluid">
				<div class="navbar-header">
					<button type='button' class='navbar-toggle' data-toggle='collapse' data-target='#myDrop'>
						<i class="fa fa-bars fa-2x"></i>
					</button>
					<a class="navbar-brand" href="#" style="font-size:1.25em !important;"><i class="fa fa-home fa-2x"></i> 'Tunde Aromire</a>
				</div>
				<div class="collapse navbar-collapse" id='myDrop'>
					<ul class="nav navbar-nav navbar-right">
						<li><a href="#"><i class="fa fa-user fa-lg"> Home</i></a></li>
						<li><a href="#"><i class="fa fa-folder fa-lg"> Portfolio</i></a></li>
						<li class="dropdown">
							<a class="dropdown-toggle" data-toggle="dropdown" href="#"><i class="fa fa-book fa-lg"> Contacts </i> <i class="fa fa-caret-down fa-lg"></i></a>
							<ul class="dropdown-menu">
								<li><a href="http://www.facebook.com/tunde1990">Facebook</a></li>
								<li><a href="http://www.twitter.com/tunde1990">Twitter</a></li>
								<li><a href="http://www.codepen.io/toondaey">Codepen</a></li>
							</ul>
						</li>
						<li><a href="#"><i class="fa fa-info fa-lg"> About</i></a></li>
					</ul>
				</div>
				
			</div>
		</nav>

	</body>
</html>

您正在调用类方法,但将其定义为实例方法。为了打电话:

after_save :update_order_status

def update_order_status
  if # relevant condition
     # do stuff
  end
end

update_status需要定义为:

Reservation.update_status

但是当你打电话给一个班级方法时......你将无法获得自我,所以你将无法说出

def self.update_status

也就是说,你将无法调用它:

self.status_id # or whatever it was

在一个模型中,在另一个模型中执行此操作:

Reservation.update_status_completed # calling as class method

因为你没有实例来获取status_id。要解决此问题,请通过参数将值传递给类方法,这样您就不会依赖于您无权访问的对象。

编辑: 无法确切地确定您要更新的预订,但要更新所有预订:

self.reservation_status_id = 5 # inside that class method trying to use instance 

现在已完成更新状态的self指的是一个实例... bc我们在update_reservations_status中调用最后一个。