title: Set a model attribute from a service
body: <p>This is the first time I'm using rails services. Before the change, my code was in a concern.</p>
  
  <p>The problem is that, in one of my methods, I have to set a model attribute and I'm not sure how should I do this from the service.</p>
  
  <p><strong>In my controller:</strong></p>
  
  <pre><code>    def new
        @order = Order.new(default_order_create_params)
        @pricing = PricingComputed.new(order: @order, user: current_user)
      end
  </code></pre>
  
  <p><strong>From my service (I removed the unnecessary code):</strong></p>
  
  <pre><code># 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
  </code></pre>
  
  <p>I want to be able to set the <code>discounted_price_pretax_cents</code> and use it from <code>@pricing</code> if it's possible.</p>
  
  <p>Could you point me?</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p><strong>in my view (new):</strong></p>
  
  <p><code>= render('steps/price_card', order: @order, pricing: @pricing)</code></p>
  
  <p><strong>_price_card:</strong></p>
  
  <pre><code>#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
                =&gt; number_to_currency(pricing.discount)
              small
                = "(#{number_to_percentage(pricing.discount_percent, precision: 2)})"
            - else
              strong&gt; 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?
                =&gt; order.credits
                small credits
              - else
                ' 0
                small credit
          - else
            .neo-card-price-total-value-pretax
              =&gt; number_to_currency(pricing.discounted_price_pretax_cents)
              small HT
            .neo-card-price-total-value-tax
              =&gt; number_to_currency(order.price)
              small TTC
      - if user_signed_in? &amp;&amp; order.new_record?
        .neo-card-credits-link
          = link_to(\
            "Buy credits",
            new_credit_pack_path)
  </code></pre>
  
  <p><strong>logs:</strong></p>
  
  <pre><code>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 #&lt;PricingComputed:0x00007fd8cb7c5f28&gt; 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 #&lt;PricingComputed:0x00007fd8cb7c5f28&gt;):
  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:             =&gt; 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:             =&gt; 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'
  </code></pre>
  
  <p>Also, the price is updated when a value change:</p>
  
  <pre><code>  function updatePriceCard() {
      const $form = $('#order-form');
      $.ajax('/orders/estimate_prices', {
        data: $form.find('textarea, select, input:not([name="_method"])').serialize(),
        type: 'POST',
      }).done((data) =&gt; {
        $('#order-price-card').replaceWith(data);
      });
    }
  </code></pre>
  
  <pre><code>  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
  </code></pre>