Postgres Range Fields + Rails Forms

What is the proper way to form Rails data before I store it in my Postgres interval data-type column?

You are correct in using the interval type for saving hours, minutes and seconds. But this will not save the milliseconds.

What you did was converting a time into milliseconds. Your interval field only knows of seconds, and 6_000_000 seconds resulted in 16666:40:0 - exceeding the 1_000_000 seconds it represents, which seems to be the max limit.

You should approach this differently:

Use the interval field as intended: save hours, minutes, and seconds into a column - they are part of your form anyway. Then it will be easy to display it in the view as well.

Then, if you want to retrieve your milliseconds, simply add a method:

class Bar < ActiveRecord::Base
def time_in_milliseconds
# retrieve the interval seconds from the database and multiply by 1000
end
end

Also, for handling the conversion of milliseconds to hh:mm:ss format and back you should check out this great answer.

Rails form helper for type tsrange

I think you'll have to add custom getters and setters for those values:

def period_begin
# using read_attribute because I'm redefining the `period` getter at the end
@period_begin = read_attribute(:period)&.begin
end

def period_end
@period_end = read_attribute(:period)&.end
end

def period_begin=(value)
@period_begin = value
end

def period_end=(value)
@period_end = value
end

def period
period_begin..period_end if period_begin && period_end
end

Not a 100% sure about this (I've never used the tsrange type), but hope the idea (maybe the implementation of each getter/setter is not the correct one) helps you.

Then period_end and period_begin should work when rendering the form and should work when setting the attributes when you submit the form.

Selecting Range by Database Attribute for Rails Form

I've never seen Ruby's range with dynamic numbers. I just tried doing it in irb and it didn't work correctly. Another alternative would be to use something like this (not tested, but idea is):

<%= f.select(:quantity_requested, 1.upto(quantity.times).to_a, {}, { class: 'item-quantity form-control' }) %>

Edit:
I just tried this in an irb console and it started at zero based, so you'll want to use upto instead of times, see output below:

a = 100
a.times.to_a
=> [0, 1, ... 99]

1.upto(a).to_a
=> [1, 2, 3,.. 99, 100]

Postgresql change the year range and input order

I was able to get the desired output as follows (strictly with simple_form):

<%= f.input(:date_of_birth, start_year: 1900, end_year: Time.now.year - 1, order: [:month, :day, :year]) %>

Correct format for one or many range_field in form_for

I think you might be a little confused in your approach. Rather than go through each line and explain the failures, I would suggest perhaps using a different approach involving forms and nested forms. Check out the Rails Cast on the topic:

http://railscasts.com/episodes/196-nested-model-form-part-1

It's an older topic but it should help you get the form structure straightened out a bit. He has an updated Cast on the subject, but you have to be a member to see it:

http://railscasts.com/episodes/196-nested-model-form-revised

I would say restructure your forms in that pattern, and come back with another set of questions. Start with the simplest form of the structure, and get it working and then add complexity.

Hope that helps.

UPDATE: I saw your post on Reddit. The fact that you appear to be a student at Chico State may be preventing people from wanting to "do your homework". I tried to answer in a way that will get you to learn the Rails way, rather than solve the problem for you.

Ruby On Rails PG Database problem using nested form with a table entity that has a table-less model relationship 'has many'

has_many and nested attributes are for associations. This isn't an association, it's just a column that contains a string which Rails will serialize and deserialize. That's about all Rails knows about JSONB.

Instead of nested attributes, you're passing an array parameter.

def admin_params
params.require(:admin).permit(:first_name, :last_name, :age, time_ranges: [])
end

It's up to Admin to validate time_ranges contains the correct objects.

Your form would take inputs with the name admin[time_ranges][][start_date] and admin[time_ranges][][end_date]. See Parameter Naming Conventions.


Since Rails does not know about JSONB associations it's going to be a lot more work. This could be done simpler as a regular association with a real table with a single tztsrange or daterange column (it's unclear if you're storing times or dates).

create_table :admin_availability do
t.belongs_to :admin
t.tztsrange :availability, null: false
end

class AdminAvailability < ApplicationRecord
belongs_to :admin
end

class Admin < ApplicationRecord
has_many :admin_availabilities
accepts_nested_attributes_for :admin_availability
end

Now the nested attribute machinery will work. You'll likely still have to translate from start_time/end_time parameters to a single Range object. It might be simpler to add convenience accessors to your controller.

class AdminAvailability < ApplicationRecord
belongs_to :admin

def start_time
availability.begin
end

def start_time=(start)
self.availability = Range.new(start, end_time)
end

def end_time
availability.end
end

def end_time=(end)
self.availability = Range.new(start_time, end)
end
end


Related Topics



Leave a reply



Submit