首页 > 解决方案 > 从服务设置模型属性

问题描述

这是我第一次使用 Rails 服务。在更改之前,我的代码存在问题。

问题是,在我的一种方法中,我必须设置一个模型属性,我不确定我应该如何从服务中做到这一点。

在我的控制器中:

    def new
      @order = Order.new(default_order_create_params)
      @pricing = PricingComputed.new(order: @order, user: current_user)
    end

从我的服务中(我删除了不必要的代码):

# frozen_string_literal: true

class PricingComputed
  def initialize(params)
    @order = params[:order]
    @user = params[:user]
  end

  def perform
    set_discounted_price_pretax_cents
  end

private

  def set_discounted_price_pretax_cents
    return unless @order.pending?

    @order.discounted_price_pretax_cents = @order.price_pretax_cents - discount_cents
  end
end

如果可能的话,我希望能够设置discounted_price_pretax_cents和使用它@pricing

你能指点我吗?

编辑:

在我看来(新):

= render('steps/price_card', order: @order, pricing: @pricing)

_price_card:

#order-price-card.neo-card
  .neo-card-heading
    h2.neo-card-title
      | Your order
  - if order.cash?
    .neo-card-price-reduction
      .neo-card-list-item
        .neo-card-list-item-label
          | Your reduction
        .neo-card-list-item-value
          - if pricing.discount_cents.positive?
            strong
              => number_to_currency(pricing.discount)
            small
              = "(#{number_to_percentage(pricing.discount_percent, precision: 2)})"
          - else
            strong> 0.00$
            small
              | (0.00%)
      p.small Order more words for a better discount
    .neo-card-price-total
      .neo-card-price-total-label Total
      .neo-card-price-total-value
        - if order.credits?
          .neo-card-price-total-value-pretax
            - if order.credits.positive?
              => order.credits
              small credits
            - else
              ' 0
              small credit
        - else
          .neo-card-price-total-value-pretax
            => number_to_currency(pricing.discounted_price_pretax_cents)
            small HT
          .neo-card-price-total-value-tax
            => number_to_currency(order.price)
            small TTC
    - if user_signed_in? && order.new_record?
      .neo-card-credits-link
        = link_to(\
          "Buy credits",
          new_credit_pack_path)

日志:

09:50:47 server.1 | Started GET "/steps/orders/new" for ::1 at 2019-01-17 09:50:47 +0100
09:50:48 server.1 | Processing by Steps::OrdersController#new as HTML
09:50:48 server.1 |   User Load (1.7ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 7], ["LIMIT", 1]]
09:50:48 server.1 |   ↳ app/controllers/application_controller.rb:93
09:50:49 server.1 |   Category Load (0.6ms)  SELECT  "categories".* FROM "categories" ORDER BY "categories"."id" ASC LIMIT $1  [["LIMIT", 1]]
09:50:49 server.1 |   ↳ app/controllers/steps/orders_controller.rb:18
09:50:49 server.1 |   Rendering steps/orders/new.html.slim within layouts/new_order
09:50:49 server.1 |   User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 7], ["LIMIT", 1]]
09:50:49 server.1 |   ↳ app/views/steps/orders/new.html.slim:31
09:50:49 server.1 |   Category Load (0.4ms)  SELECT "categories"."id", "categories"."source_language", "categories"."target_language" FROM "categories"
09:50:49 server.1 |   ↳ app/helpers/orders_helper.rb:33
09:50:49 server.1 |    (0.4ms)  SELECT "categories"."source_language" FROM "categories"
09:50:49 server.1 |   ↳ app/helpers/orders_helper.rb:29
09:50:49 server.1 |   Category Load (0.6ms)  SELECT "categories".* FROM "categories" WHERE "categories"."source_language" = $1  [["source_language", "fr"]]
09:50:49 server.1 |   ↳ app/views/steps/orders/new.html.slim:60
09:50:49 server.1 |   Rendered steps/_price_card.slim (15.2ms)
09:50:49 server.1 |   Rendered steps/orders/new.html.slim within layouts/new_order (45.7ms)
09:50:49 server.1 | Completed 500 Internal Server Error in 1203ms (ActiveRecord: 21.5ms)
09:50:49 server.1 |
09:50:49 server.1 |
09:50:49 server.1 | undefined method `discounted_price_pretax_cents' for #<PricingComputed:0x00007fd8cb7c5f28> excluded from capture: Not configured to send/capture in environment 'development'
09:50:49 server.1 |
09:50:49 server.1 | ActionView::Template::Error (undefined method `discounted_price_pretax_cents' for #<PricingComputed:0x00007fd8cb7c5f28>):
09:50:49 server.1 |     31:               small credit
09:50:49 server.1 |     32:         - else
09:50:49 server.1 |     33:           .neo-card-price-total-value-pretax
09:50:49 server.1 |     34:             => number_to_currency(pricing.discounted_price_pretax_cents)
09:50:49 server.1 |     35:             small HT
09:50:49 server.1 |     36:           .neo-card-price-total-value-tax
09:50:49 server.1 |     37:             => number_to_currency(order.price)
09:50:49 server.1 |
09:50:49 server.1 | app/views/steps/_price_card.slim:34:in `_app_views_steps__price_card_slim__802419931166157136_70284550345380'
09:50:49 server.1 | app/views/steps/orders/new.html.slim:73:in `_app_views_steps_orders_new_html_slim__4387080387746709579_70284551781060'

此外,当值发生变化时,价格也会更新:

  function updatePriceCard() {
    const $form = $('#order-form');
    $.ajax('/orders/estimate_prices', {
      data: $form.find('textarea, select, input:not([name="_method"])').serialize(),
      type: 'POST',
    }).done((data) => {
      $('#order-price-card').replaceWith(data);
    });
  }
  def estimate_prices
    @order =
      if params[:id].present? then Order.find(params[:id])
      else Order.new
      end

    @order.assign_attributes(
      order_params.merge(user: current_user)
    )

    @pricing = PricingComputed.new(@order).perform
    render(partial: 'steps/price_card', layout: false, locals: {
      order: @order, pricing: @pricing
    })
  end

标签: ruby-on-railsruby

解决方案


您尝试访问discounted_price_pretax_cents没有该字段的服务对象上的模型字段。

如果PricingComputed是作为服务对象(运行业务逻辑的对象),您可能不应该将其传递给视图。相反,使用视图中需要的数据构建一个数据对象(例如 a Struct),或者传递一个模型(在这种情况下可能是@order)。

您还可以包装@order一个可以转换值并调整它以在视图中显示它们的装饰器,但我认为这里不是这种情况。


推荐阅读