(Rails) fields_for a serialized column are not being populated with data
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
add a comment |
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
Are you building the relationship in the controller.@order.build_address
?
– Mike Heft
Nov 21 '18 at 17:02
Theaddress
is an attribute of Order, not an associated record. It is stored in ajson hash
column in theOrders
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']
, … . Isfields_for
only suited for nested models and not for serialized columns?
– R4ttlesnake
Nov 22 '18 at 9:43
I found an easy solution: Together withserialize :address
we can usestore_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 viaf.firstname
,f.lastname
, … and they are being populated respectively. I found out aboutstore_accessor
in Nando Vieira's post about using jsonb in RoR.
– R4ttlesnake
Nov 22 '18 at 10:13
add a comment |
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
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
ruby-on-rails forms serialization fields-for
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
Theaddress
is an attribute of Order, not an associated record. It is stored in ajson hash
column in theOrders
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']
, … . Isfields_for
only suited for nested models and not for serialized columns?
– R4ttlesnake
Nov 22 '18 at 9:43
I found an easy solution: Together withserialize :address
we can usestore_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 viaf.firstname
,f.lastname
, … and they are being populated respectively. I found out aboutstore_accessor
in Nando Vieira's post about using jsonb in RoR.
– R4ttlesnake
Nov 22 '18 at 10:13
add a comment |
Are you building the relationship in the controller.@order.build_address
?
– Mike Heft
Nov 21 '18 at 17:02
Theaddress
is an attribute of Order, not an associated record. It is stored in ajson hash
column in theOrders
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']
, … . Isfields_for
only suited for nested models and not for serialized columns?
– R4ttlesnake
Nov 22 '18 at 9:43
I found an easy solution: Together withserialize :address
we can usestore_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 viaf.firstname
,f.lastname
, … and they are being populated respectively. I found out aboutstore_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
add a comment |
1 Answer
1
active
oldest
votes
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)
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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)
add a comment |
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)
add a comment |
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)
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)
edited Nov 23 '18 at 14:16
answered Nov 22 '18 at 10:32
R4ttlesnakeR4ttlesnake
4641619
4641619
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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 ajson hash
column in theOrders
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']
, … . Isfields_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 usestore_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 viaf.firstname
,f.lastname
, … and they are being populated respectively. I found out aboutstore_accessor
in Nando Vieira's post about using jsonb in RoR.– R4ttlesnake
Nov 22 '18 at 10:13