(Rails) поля_ для столбца сериализации не заполняются данными - PullRequest
0 голосов
/ 21 ноября 2018

я не буду отправлять @order через form_with в Rails 5.2.@order является экземпляром класса Order, который имеет сериализованный столбец для полей адреса.Поля адреса заполняются на fields_for в форме заказа, при отправке формы на OrdersController все поля / значения передаются корректно.

Проблема в том, что если @order не проходит проверку, OrdersController снова отображает представление формы с ошибками @order, но здесь адрес fields_for не заполняется хэшем :address.

Я видел довольно хакерские решения для преобразования сериализованного столбца в attr_accessors. Есть ли удобное решение для заполнения полей формы из сериализованного столбца в Rails?

Вот мой код…

order.rb

class Order < ApplicationRecord
  serialize :address

  …

  validate  :address_validator

  …

  private

    def address_validator
      required_fields = [:firstname, :lastname, :line1, :city, :postal_code, :country]
      required_fields.each do |field|
        self.errors.add(:base, "Address / #{field.to_s.titleize} can't be blank") if self.address[field.to_s].blank?
      end
    end

    …
end

new.html.erb

<%= form_with model: @order, id: 'order-form', class: 'form', local: true do |f| %>
  <%= render 'shared/form_errors', object: f.object %>

  …

  <%= f.fields_for :address do |g| %>
    <%= render 'orders/address_fields', f: g %>
  <% end %>

  …

<% end %>

_address_fields.html.erb

<div class='form__row columns columns--responsive-to-small columns--with-gutter'>
  <div class='form__input form__input--mandatory'>
    <%= f.label :firstname, 'Firstname' %>
    <%= f.text_field :firstname %>
  </div>

  <div class='form__input form__input--mandatory'>
    <%= f.label :lastname, 'Lastname' %>
    <%= f.text_field :lastname %>
  </div>
</div>

<div class='form__row'>
  <div class='form__input form__input--mandatory'>
    <%= f.label :line1, 'Address (line 1)' %>
    <%= f.text_field :line1 %>
  </div>
</div>

…

После отправки формы объект @order имеет следующие значения (значения адреса присутствуют)

(byebug) @order
#<Order id: nil, order_id: "HvMB00KS-73e1fc", …, created_at: nil, updated_at: nil, address: {"firstname"=>"Rocky", "lastname"=>"Marciano", "line1"=>"Saplestreet 123", "line2"=>"", "city"=>"Clashtown", "postal_code"=>"18726", "country"=>"Germany"}, email: "test@mail.com", products: … >

Спасибо!

1 Ответ

0 голосов
/ 22 ноября 2018

Для этого существует удобное (недостаточно документированное) решение, которое называется store_accessor, которое можно использовать вместе с хэшированием сериализованных атрибутов для создания средств доступа для его ключей.Я нашел это благодаря Использование PostgreSQL и jsonb с Ruby on Rails Нандо Виейрой.

Используя приведенный выше примерный хэш адреса, мы можем определить…

class Order < ApplicationRecord
  serialize :address
  store_accessor :address, :firstname, :lastname, :postal_code, …
  …
end

чтобы установить и прочитать атрибуты адреса, такие как…

order = Order.new
order.firstame = 'Billy'
order.firstname
#=> "Billy"
order.address['firstname']
#=> "Billy"

в форме для @ порядка, ключи address могут быть установлены напрямую, и форма будет заполнена соответственно…

<%= form_with model: @order, local: true do |f| %>

  <%= f.label :firstname, 'Firstname' %>
  <%= f.text_field :firstname %>

  <%= f.label :lastname, 'Lastname' %>
  <%= f.text_field :lastname %>

<% end %>

использование сильных параметров в OrdersController, например…

params.require(:order).permit(:firstname, :lastname)
...