(Rails) fields_for a serialized column are not being populated with data












0















i won't to submit an @order via a form_with in Rails 5.2. The @order is an instance of the Order class which has a serialized column for the address fields. The address fields are filled by fields_for within the order form, when submitting the form to the OrdersController all the fields / values are being passed correctly.



The problem is: if @order fails validation, the OrdersController renders the form view again with @order's errors, but here the fields_for address are not being populated by the :address hash.



I saw quite some hacky solutions to convert a serialized column into attr_accessors. Is there a convenient solution to populate form fields from a serialized column in Rails?



Here my code …



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>




After submitting the form the @order object has the following values (address values are present)



(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: … >


Thanks!










share|improve this question























  • Are you building the relationship in the controller. @order.build_address ?

    – Mike Heft
    Nov 21 '18 at 17:02











  • The address is an attribute of Order, not an associated record. It is stored in a json hash column in the Orders table. The object @order is built in the controller with the strong parameters :email, address: [:firstname, :lastname, …] from the submitted form; the address attribute can be read and set with @order.address['firstname'], … . Is fields_for only suited for nested models and not for serialized columns?

    – R4ttlesnake
    Nov 22 '18 at 9:43











  • I found an easy solution: Together with serialize :address we can use store_accessor :address, :firstname, :lastname, … in order to create accessors for attributes within the address hash. Now we can use the attributes directly in a form via f.firstname, f.lastname, … and they are being populated respectively. I found out about store_accessor in Nando Vieira's post about using jsonb in RoR.

    – R4ttlesnake
    Nov 22 '18 at 10:13
















0















i won't to submit an @order via a form_with in Rails 5.2. The @order is an instance of the Order class which has a serialized column for the address fields. The address fields are filled by fields_for within the order form, when submitting the form to the OrdersController all the fields / values are being passed correctly.



The problem is: if @order fails validation, the OrdersController renders the form view again with @order's errors, but here the fields_for address are not being populated by the :address hash.



I saw quite some hacky solutions to convert a serialized column into attr_accessors. Is there a convenient solution to populate form fields from a serialized column in Rails?



Here my code …



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>




After submitting the form the @order object has the following values (address values are present)



(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: … >


Thanks!










share|improve this question























  • Are you building the relationship in the controller. @order.build_address ?

    – Mike Heft
    Nov 21 '18 at 17:02











  • The address is an attribute of Order, not an associated record. It is stored in a json hash column in the Orders table. The object @order is built in the controller with the strong parameters :email, address: [:firstname, :lastname, …] from the submitted form; the address attribute can be read and set with @order.address['firstname'], … . Is fields_for only suited for nested models and not for serialized columns?

    – R4ttlesnake
    Nov 22 '18 at 9:43











  • I found an easy solution: Together with serialize :address we can use store_accessor :address, :firstname, :lastname, … in order to create accessors for attributes within the address hash. Now we can use the attributes directly in a form via f.firstname, f.lastname, … and they are being populated respectively. I found out about store_accessor in Nando Vieira's post about using jsonb in RoR.

    – R4ttlesnake
    Nov 22 '18 at 10:13














0












0








0








i won't to submit an @order via a form_with in Rails 5.2. The @order is an instance of the Order class which has a serialized column for the address fields. The address fields are filled by fields_for within the order form, when submitting the form to the OrdersController all the fields / values are being passed correctly.



The problem is: if @order fails validation, the OrdersController renders the form view again with @order's errors, but here the fields_for address are not being populated by the :address hash.



I saw quite some hacky solutions to convert a serialized column into attr_accessors. Is there a convenient solution to populate form fields from a serialized column in Rails?



Here my code …



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>




After submitting the form the @order object has the following values (address values are present)



(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: … >


Thanks!










share|improve this question














i won't to submit an @order via a form_with in Rails 5.2. The @order is an instance of the Order class which has a serialized column for the address fields. The address fields are filled by fields_for within the order form, when submitting the form to the OrdersController all the fields / values are being passed correctly.



The problem is: if @order fails validation, the OrdersController renders the form view again with @order's errors, but here the fields_for address are not being populated by the :address hash.



I saw quite some hacky solutions to convert a serialized column into attr_accessors. Is there a convenient solution to populate form fields from a serialized column in Rails?



Here my code …



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>




After submitting the form the @order object has the following values (address values are present)



(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: … >


Thanks!







ruby-on-rails forms serialization fields-for






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 21 '18 at 16:42









R4ttlesnakeR4ttlesnake

4641619




4641619













  • Are you building the relationship in the controller. @order.build_address ?

    – Mike Heft
    Nov 21 '18 at 17:02











  • The address is an attribute of Order, not an associated record. It is stored in a json hash column in the Orders table. The object @order is built in the controller with the strong parameters :email, address: [:firstname, :lastname, …] from the submitted form; the address attribute can be read and set with @order.address['firstname'], … . Is fields_for only suited for nested models and not for serialized columns?

    – R4ttlesnake
    Nov 22 '18 at 9:43











  • I found an easy solution: Together with serialize :address we can use store_accessor :address, :firstname, :lastname, … in order to create accessors for attributes within the address hash. Now we can use the attributes directly in a form via f.firstname, f.lastname, … and they are being populated respectively. I found out about store_accessor in Nando Vieira's post about using jsonb in RoR.

    – R4ttlesnake
    Nov 22 '18 at 10:13



















  • Are you building the relationship in the controller. @order.build_address ?

    – Mike Heft
    Nov 21 '18 at 17:02











  • The address is an attribute of Order, not an associated record. It is stored in a json hash column in the Orders table. The object @order is built in the controller with the strong parameters :email, address: [:firstname, :lastname, …] from the submitted form; the address attribute can be read and set with @order.address['firstname'], … . Is fields_for only suited for nested models and not for serialized columns?

    – R4ttlesnake
    Nov 22 '18 at 9:43











  • I found an easy solution: Together with serialize :address we can use store_accessor :address, :firstname, :lastname, … in order to create accessors for attributes within the address hash. Now we can use the attributes directly in a form via f.firstname, f.lastname, … and they are being populated respectively. I found out about store_accessor in Nando Vieira's post about using jsonb in RoR.

    – R4ttlesnake
    Nov 22 '18 at 10:13

















Are you building the relationship in the controller. @order.build_address ?

– Mike Heft
Nov 21 '18 at 17:02





Are you building the relationship in the controller. @order.build_address ?

– Mike Heft
Nov 21 '18 at 17:02













The address is an attribute of Order, not an associated record. It is stored in a json hash column in the Orders table. The object @order is built in the controller with the strong parameters :email, address: [:firstname, :lastname, …] from the submitted form; the address attribute can be read and set with @order.address['firstname'], … . Is fields_for only suited for nested models and not for serialized columns?

– R4ttlesnake
Nov 22 '18 at 9:43





The address is an attribute of Order, not an associated record. It is stored in a json hash column in the Orders table. The object @order is built in the controller with the strong parameters :email, address: [:firstname, :lastname, …] from the submitted form; the address attribute can be read and set with @order.address['firstname'], … . Is fields_for only suited for nested models and not for serialized columns?

– R4ttlesnake
Nov 22 '18 at 9:43













I found an easy solution: Together with serialize :address we can use store_accessor :address, :firstname, :lastname, … in order to create accessors for attributes within the address hash. Now we can use the attributes directly in a form via f.firstname, f.lastname, … and they are being populated respectively. I found out about store_accessor in Nando Vieira's post about using jsonb in RoR.

– R4ttlesnake
Nov 22 '18 at 10:13





I found an easy solution: Together with serialize :address we can use store_accessor :address, :firstname, :lastname, … in order to create accessors for attributes within the address hash. Now we can use the attributes directly in a form via f.firstname, f.lastname, … and they are being populated respectively. I found out about store_accessor in Nando Vieira's post about using jsonb in RoR.

– R4ttlesnake
Nov 22 '18 at 10:13












1 Answer
1






active

oldest

votes


















1














There is a convenient (not well documented) solution for this called store_accessor that can be used together with a serialized attributes hash in order to create accessors for its keys. I found this thanks to Using PostgreSQL and jsonb with Ruby on Rails by Nando Vieira.



Using the exemplary address hash from above, we can define …



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

end


to set and read the address' attributes like …



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


in a form for an @order the keys of address can be set directly and the form will be populated respectively …



<%= 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 %>


using strong parameters in OrdersController like …



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





share|improve this answer


























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53416789%2frails-fields-for-a-serialized-column-are-not-being-populated-with-data%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    There is a convenient (not well documented) solution for this called store_accessor that can be used together with a serialized attributes hash in order to create accessors for its keys. I found this thanks to Using PostgreSQL and jsonb with Ruby on Rails by Nando Vieira.



    Using the exemplary address hash from above, we can define …



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

    end


    to set and read the address' attributes like …



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


    in a form for an @order the keys of address can be set directly and the form will be populated respectively …



    <%= 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 %>


    using strong parameters in OrdersController like …



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





    share|improve this answer






























      1














      There is a convenient (not well documented) solution for this called store_accessor that can be used together with a serialized attributes hash in order to create accessors for its keys. I found this thanks to Using PostgreSQL and jsonb with Ruby on Rails by Nando Vieira.



      Using the exemplary address hash from above, we can define …



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

      end


      to set and read the address' attributes like …



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


      in a form for an @order the keys of address can be set directly and the form will be populated respectively …



      <%= 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 %>


      using strong parameters in OrdersController like …



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





      share|improve this answer




























        1












        1








        1







        There is a convenient (not well documented) solution for this called store_accessor that can be used together with a serialized attributes hash in order to create accessors for its keys. I found this thanks to Using PostgreSQL and jsonb with Ruby on Rails by Nando Vieira.



        Using the exemplary address hash from above, we can define …



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

        end


        to set and read the address' attributes like …



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


        in a form for an @order the keys of address can be set directly and the form will be populated respectively …



        <%= 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 %>


        using strong parameters in OrdersController like …



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





        share|improve this answer















        There is a convenient (not well documented) solution for this called store_accessor that can be used together with a serialized attributes hash in order to create accessors for its keys. I found this thanks to Using PostgreSQL and jsonb with Ruby on Rails by Nando Vieira.



        Using the exemplary address hash from above, we can define …



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

        end


        to set and read the address' attributes like …



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


        in a form for an @order the keys of address can be set directly and the form will be populated respectively …



        <%= 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 %>


        using strong parameters in OrdersController like …



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






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 23 '18 at 14:16

























        answered Nov 22 '18 at 10:32









        R4ttlesnakeR4ttlesnake

        4641619




        4641619
































            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53416789%2frails-fields-for-a-serialized-column-are-not-being-populated-with-data%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Guess what letter conforming each word

            Port of Spain

            Run scheduled task as local user group (not BUILTIN)