【问题标题】:How Do I Pass Additional Parameters in Rails from Controller to Model如何将 Rails 中的其他参数从控制器传递到模型
【发布时间】:2014-09-02 01:44:56
【问题描述】:

我想在这些代码行(控制器和模型)中传递一个额外的字段,比如 item_id:

# transactions_controller.rb (controller)
@transaction = Transaction.new(app_token: params[:token])

# transaction.rb (model)
def app_token=(token)
    write_attribute(:app_token, token)

    # I want to add a few more lines of code here so that I can manipulate item_id
end

这意味着,我希望将我的 item_id 从控制器传递到模型,以便我可以操纵它在模型中进行一些自定义。

这样做的最佳方法是什么(基于上面的代码)?

===更新至 2014 年 9 月 1 日以了解更多详情===

我有购物车和交易的关联,其中购物车有_许多交易和交易属于购物车;下面是控制器;

# transactions_controller.rb (controller)
def new
  @transaction = Transaction.new(app_token: params[:token])
end

虽然下面的方法在模型中:

# transaction.rb (model)
def app_token=(token)
    write_attribute(:app_token, token)

    # I want to add a few more lines of code here so that I can manipulate cart.id
end

我想在这里实现的是将cart.id 传递到位于transaction.rb 中的app_token 方法中。请注意,这个 cart.id 并不是要保存到数据库中,我可以通过 build 的 create 方法轻松地做到这一点,而是这个 cart.id 用于传递到方法中以调用位于的其他方法在位于 transaction.rb 模型中的 app_token 方法中。我这样做的原因是,我正在与之通信的服务返回一个令牌,我想持有该令牌并执行另一个需要 cart.id 的方法。

因此,我只是想了解,根据上面给定的控制器和模型格式,将这个 cart.id 传递到位于 transaction.rb 模型中的 app_token 方法中最推荐的方式是什么我想用于方法中的其他功能?

谢谢!

【问题讨论】:

  • 不清楚你在问什么。您想在初始化模型实例时传递任意数据元素吗?你能详细说明一下吗?
  • @infused,我已经编辑了问题以提供进一步的清晰度。让我知道是否可以?对造成的混乱表示抱歉。

标签: ruby-on-rails ruby ruby-on-rails-4


【解决方案1】:

我有购物车和交易的关联,其中购物车有_许多交易和交易属于购物车

既然是这样,并且您已经有一个购物车对象,那么在您的控制器中只需实例化购物车中的交易:

transaction = cart.transactions.build app_token: params[:token]
transaction.save

cart_id 将可用于模型中的所有实例方法,因此无需使用与 app_token 无关的附加逻辑扩展 app_token=。相反,利用 ActiveRecord 回调。例如,您可以使用before_save 回调来实现您的逻辑:

class Transaction < ActiveRecord::Base
  belongs_to :cart
  before_save :do_something_with_cart

  def do_something_with_cart
    # I want to add a few more lines of code here so that I can manipulate cart_id
  end
end

如果由于某种原因回调不适合您的用例,请直接在控制器中调用自定义方法:

transaction = cart.transactions.build app_token: params[:token]
transaction.do_something_with_cart

【讨论】:

  • 感谢您的建议!我最终按照建议使用了 build 方法,而没有在 ActiveRecord 中使用 save 方法;构建事务对象后,我会调用模型中的方法来执行我希望它执行的必要功能!
【解决方案2】:

您不需要覆盖 app_token=

# transactions_controller.rb (controller)
@transaction = Transaction.new(app_token: params[:token], item_id: params[:item_id])
@transaction.save

【讨论】:

  • 感谢您的关注!我只想按照上面的问题将数据从控制器传递到模型方法,这与保存到数据库无关;再次感谢您的协助!
【解决方案3】:

属性

这主要取决于您是否将item_id 设置为属性,无论是虚拟的还是在数据库中。

如果您已经设置了关联 foreign_key,您将可以忽略我要写的内容,但如果您还没有,您应该考虑以下几点:

#app/models/transaction.rb
class Transaction < ActiveRecord::Base
   belongs_to :item # -> expects item_id by default
end

如果您没有设置关联(因此没有属性),您需要使用attr_accessor 创建虚拟属性:

#app/models/transaction.rb
class Transaction < ActiveRecord::Base
   attr_accessor :item_id
end

参数

在 Rails 4 中传递属性实际上是您最不关心的问题 - 您可以通过路由传递任意​​数量的属性。当您尝试将项目与您的数据库对象匹配时会出现问题(因此我在上面的建议)

如果您想传递item_id 属性,您只需确保它已在您的视图中设置。这可以通过您的routes 完成,或者通过在您的表单中传递:

#config/routes.rb
resources :items
  resources :transactions #-> domain.com/items/:item_id/transactions/new
end

这将允许您传递您希望的item_id(它将在您的控制器中加载为params[:item_id]。您还可以使用以下内容:

#app/views/transactions/new.html.erb
<%= form_for @transaction do |f| %>
   <%= f.text_field :item_id %>
   <%= f.text_field :token %>
   <%= f.submit %>
<% end %>

这将使您能够将两个不同的属性发送到您的控制器,然后可以按如下方式填充:

#app/controllers/transactions_controller.rb
class TransactionsController < ApplicationController
   def new
      @transaction = Transaction.new
   end

   def create
      @transaction = Transaction.new transaction_params
      @transaction.save
   end

   private

   def transaction_params
      params.require(:transaction).permit(:item_id, :token)
   end
end

必须注意form 方法只有在模型中定义了属性时才可行 - 在数据库中或虚拟(使用attr_accessor

【讨论】:

  • 谢谢丰富;我试图实现的更多是基于给定代码将数据从控制器传递到模型方法(如上图所示);我使用的 item_id 只是一个示例,与任何关联无关;再次感谢! :D
猜你喜欢
  • 1970-01-01
  • 2012-04-20
  • 1970-01-01
  • 2012-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多