nesting another field in a json column with a rails form - ruby-on-rails

I'm trying to use the Json type available in the Postgres 9.2 release as a means to store a variety of data in one field. I created a column called data of json type on the corrections table. The form is a regular rails form except that the number of form fields it creates depends on the length of a #content array like this
<%= f.fields_for :data, #correction.data do |d| %>
<% #content.each do |content| %>
<%= d.text_area content, :class => 'content', :value => "", :cols => "40", :rows => "2", :id => 'correction_data_'"#{content.parameterize}"%>
<% end -%>
<%= end %>
If the #content array, had two elements, the database entry for data would look like this
data: {"key from #content"=>"value entered in form field", "key from #content" => "value entered in form field }
I have two questions
1 How would I change the Rails form to nest another key value pair inside (or associate with) each key value pair
"key from #content"=>"value entered in form field"
For example, I'm wondering if there's a way to nest or associate a comment field inside this data column for each key/value pair like this
"key from #content"=>"value entered in form field" comment key => comment value
"key from #content"=>"value entered in form field" comment key => comment value
2 Is this proper JSON format? It seems to me like it's just saving a bunch of key value pairs with the key always changing depending on the content from #content. If it isn't, is that a problem? Am I missing out on something by doing it this way?
data: {"content from #content"=>"value entered in form field", "content from #content" => "value entered in form field }

Related

Why is field "line_type_eq" accessible in my view with f.object.line_type_eq but a field called "deleted_eq" always returns nil?

I am using Ransack to search a database with multiple fields. On the view side, I am pre-populating the default field values in my search form with the previous query, which is available in the view, from the controller as #q, using search_form_for #q.
Throughout the form, this is working successfully, but my field called deleted_eq always returns nil when I try to access it with f.object.deleted_eq to check the value. This is despite other field query values being returned properly in the same place using the same format, e.g. f.object.line_type_eq.
Is "deleted" a special field name in Ransack? All fields in my query are working as expected in the controller to return the correct results.
Changing the name of "deleted" would require a database migration and lots of code changes in the project, so I'd hope to check if it is a reserved name before I make all those changes for testing.
Edit for more info:
Rails 5.2.1, Ransack 2.0.1
deleted_eq is a dropdown done with f.select with descriptive text option names that are mapped to 'true', 'false', and ''. So yes, ultimately I believe Ransack is handling it as a boolean.
<%= f.select :deleted_eq, options_for_select([['Active Records', 'false'],
['Deleted Records Only', 'true'], ['Active and Deleted Records', '']],
f.object.deleted_eq || 'false'), {}, { :class => 'form-control',
:onChange => "searchOnchange();" } %>
Figured this out.
It seems like deleted_eq can be nil if a blank value is supplied. I had the most luck adapting another solution I found online like so:
<%= f.select :deleted_eq, [['Active Records', 0], ['Deleted Records', 1]],
{ include_blank: 'All Records', selected: params[:q] ? params[:q][:deleted_eq] : 0 },
{:class => 'form-control', :onChange => "searchOnchange();" } %>
It's a shame that the include_blank option ("All Records") always has to display as the first item in the dropdown, but since I'm able to choose what starts selected, and I can choose "Active Records", it's not the end of the world.

Passing HTML name value into rails select field

I have a form that has a select field where the user selects their title. I want to pass a name value into the rails code so the field can be modified with a client-side validation framework. The client-side validations validate each field based on the name of the field.
My current solution isn't passing the name value of 'title' into the final HTML rendered in the browser.
The field
<%= f.select :title, options_for_select([["Title", "0"], ["Mr.", "Mr."], ["Mrs.", "Mrs."], ["Ms.", "Ms."], ["Dr.", "Dr."], ["Prof.", "Prof."]], selected: "0", disabled: ["0"]), :name => "title" %>
The current HTML output
name="user[title]"
<% possible_options = [["Title", "0"], ["Mr.", "Mr."],
["Mrs.", "Mrs."], ["Ms.", "Ms."], ["Dr.", "Dr."], ["Prof.", "Prof."]]
%>
<%= f.select :title, options_for_select(possible_options), {}, {:name => "title"} %>
It's better to prepare this possible_optins list in controller action itself & accessing here just like an instance variable.
Just for a quick fix, let it be in this view/form.

How do I display the current value in an edit form using haml custom inputs?

The code I'm working with is dynamically rendering the input fields in this edit form, like so:
%input.custom{:name => "short_form[#{field_name}]", :type => field_type, :id => field_id, :value => short_form.send(field_name)}
Based on the field_type value it renders a certain type of input field. However, I cannot get the value to display at all. The value attribute just ends up showing up as blank. Any suggestions? field_name is the attribute name btw, and short_form is the object (this is in a partial).
Do:
:value => short_form.object.send(field_name)

How to display Rails select field values rather than stored integers in other views

I'm using a select field in a Rails app that is NOT tied to a related model, but stores integer values for a static series of options , i.e.,
<%= select (:this_model, :this_field, [['Option1',1],['Option2',2],['Option3',3],['Option4',4]] ) %>
In a show/ index view, if I want to display the option text (i.e. Option1, Option2, etc) rather than the integer value stored in the database, how do I achieve this?
Thanks for helping a noob learn the ropes!
EDIT
Based on Thorsten's suggestion below, I implemented the following. But it is returning nil, and I can't figure out why.
Invoice model:
##payment_status_data = { 1 => "Pending Invoice" , 2 => "Invoiced" , 3 => "Deposit Received", 4 => "Paid in Full"}
def text_for_payment_status
##payment_status_data[payment_status]
end
Invoice show view:
Payment Status: <%= #invoice.text_for_payment_status %>
In the console:
irb > i=Invoice.find(4)
=> [#<Invoice id: 4, payment_status: 1 >]
irb > i.text_for_payment_status
=> nil
I've tried defining the hash with and without quotes around the keys. What am I missing?
something like this would work:
<%= form_for #my_model_object do |form| %>
<%= form.label :column_name "Some Description" %>
<%= form.select :field_that_stores_id, options_for_select({"text1" => "key1", "text 2" => "key2"}) %>
<% end %>
Update
If you later want to display the text you can get it from a simple hash like this:
{"key1" => "text 1", "key2" => "text2"}[#my_object.field_that_stores_id]
But you better store this hash somewhere in a central place like the model.
class MyModel < ActiveRecord
##my_select_something_data = {"key1" => "text 1", "key2" => "text2"}
def text_for_something_selectable
##my_select_something_data[field_that_stores_id]
end
end
Then you can use it in your views like
#my_object.text_for_something_selectable
There are many possible variations of this. But this should work and you would have all information in a central place.
Update
Ok, I used something similar for our website. We need to store return_headers for rma. Those need to store a return reason as a code. Those codes are defined in an external MS SQL Server Database (with which the website exchanges lots of data, like orders, products, and much more). In the external db table are much more return reasons stored than I actually need, so I just took out a few of them. Still must make sure, the codes are correct.
So here goes he model:
class ReturnHeader < AciveRecord::Base
##return_reason_keys = {"010" => "Wrong Produc",
"DAM" => "Damaged",
"AMT" => "Wrong Amount"}
def self.return_reason_select
##return_reason_keys.invert
end
def return_reason
##return_reason_keys[nav_return_reason_code]
end
end
Model contains more code of course, but that's the part that matters. Relevant here is, that keys in the hash are strings, not symbols.
In the views i use it like this:
In the form for edit:
<%= form_for #return_header do |form| %>
<%= form.label :nav_return_reason_code "Return Reason" %>
<%= form.select :nav_return_reason_code, options_for_select(ReturnHeader.return_reason_select, #return_header.nav_return_reason_code) %>
<% end %>
(Maybe no the most elegant way to do it, but works. Don't know, why options_for_select expects a hash to be "text" => "key", but that's the reason, why above class level method returns the hash inverted.)
In my index action the return reason is listed in one of the columns. There I can get the value simply by
#return_headers.each do |rh|
rh.return_reason
end
If you have trouble to get it run, check that keys a correct type and value. Maybe add some debug info with logger.info in the methods to see what actual data is used there.

rails form - 2 fields with same id in a form - how to disable second field when first field is selected

I have in my rails form the following code:
<label>Fruit: </label> <%= f.select(:IST_FRUIT, [['Apple', 'Apple'],
['Orange', 'Orange'],
['Kiwi', 'Kiwi'],
['Other', 'Other']
],{ :prompt => "Please select"},{:onchange => "if (this.value == 'Other')
{document.getElementById('otherTissue').style.display = 'block';
} "}
) %>
<span id="otherFruit" style="display:none;"> If other, please state: <%= f.text_field :IST_FRUIT, :size => 10 %></span>
User can select a fruit form the listbox but if user selects 'Other', a textfield is diaplayed allowing user to input his value.
The problem is that when user selects a fruit and save the form, the fruit field in blank in the table and the reason is that the form is saving the second field 'IST_FRUIT' found in the span with id 'IST_FRUIT'.
I would be really grateful if someone could show me a way how to disable the second field when 'other' is not selected and enable it when 'Other' is selected from the dropdown list.
Many many thanks for any suggestion provided.
First, be aware that rails posts are based on fields' name, not ids.
In your case, you should use a virtual attribute to store the potential other fruit value.
Your model could look like:
attr_accessor :other_fruit
before_save :check_fruits
def check_fruits
#if other_fruit is not nil, it means that you want to store it's value in you IST_FRUIT column
#BTW, why these capital letters?
IST_FRUIT = other_fruit unless other_fruit.nil?
end
And your form would be:
<span id="otherFruit" style="display:none;"> If other, please state: <%= f.text_field :other_fruit, :size => 10 %></span>
I have another advice. Instead of disabling a HTML input (by the way - an ID must be unique in a HTML document) just make another attribute in your model, name it 'other_fruit' for example, and use this value if the 'fruit' is set to 'other' or is empty. For example you may write something like this:
class TheModel
attr :other_fruit
# Overwritten accessor for the fruit attribute.
# Returns the values of :other_fruit if :fruit is blank.
#
def fruit
if self[:fruit].blank?
other_fruit
else
self[:fruit]
end
end
end
Now the HTML part. In your JavaScript you set 'display' to block, but you do not reset it when user selects another option.
If you want to prevent the field from being sent to the server, you should set the 'disabled' attribute. Setting the 'style' only hides the control from the user's eyes.

Resources