I am creating a two button functionality that allows me to pass parameters to a button by either subtracting the from the current month or moving to the next month. Its simple in theory, you click next and you'll see all records that were created for the month, or you'll click last month and you'll see the records that were created last month. The issue I am having is that the parameters will be one off when I click the next button. How can I navigate through months/years with two buttons? It doesn't seem to be remembering the parameter for the last button click event.
Rails Logs
Started GET "/facility_directory/lnpp?previous_month=5&commit=Next&next_month=7" for 127.0.0.1
facilities_controller.rb
def facility_directory
if params.has_key?(:select) # select month/year form
month = Date.new(params[:select][:year].to_i, params[:select][:month].to_i)
@facility_records = @facility.facility_records.where(created_at: month.all_month).order(created_at: :desc)
@year = params[:select][:year]
@month = params[:select][:month]
elsif params.has_key?(:previous_month) # last month navigation button
previous_month = Date.new(Date.today.year, params[:previous_month].to_i)
@facility_records = @facility.facility_records.where(created_at: previous_month.all_month).order(created_at: :desc)
elsif params.has_key?(:next_month)
next_month = Date.new(Date.today.year, params[:next_month].to_i)
@facility_records = @facility.facility_records.where(created_at: next_month.all_month).order(created_at: :asc)
else
date = Date.today
start_date = date.at_beginning_of_month
end_date = date.at_end_of_month
@facility_records = @facility.chart_records.order(created_at: :desc).where(created_at: start_date..end_date)
end
end
facility_directory.html.erb
<%= form_tag facility_directory_path(@facility), :method => :get, :class => "form" do %>
<div>
<%= select_month(Date.today, {:include_blank => true.....%>
<%= select_year(Date.today, {:include_blank => true...%>
</div>
<%= submit_tag('Search') %>
<% end %>
<%= form_tag facility_directory_path(@facility), method: :get, class: '' do %>
<%= submit_tag 'Previous Month', class: 'button' %>
<%= hidden_field_tag 'previous_month', @month.present? ? (@month.to_i - 1) : (Time.now.month - 1) %>
<%= submit_tag 'Next', class: 'button ui basic blue small' %>
<%= hidden_field_tag 'next_month', @month.present? ? (@month.to_i + 1) : (Time.now.month + 1) %>
<% end %>
Looks like you're also going to run into a problem where your view will render out a form where the hidden value of next_month
will be 13, or the previous will be 0 - both of which are going to be invalid.
You're also setting default year and month logic in the view. You'll generally be better served if the setting of month and year is done in one place - the controller.
Shift all of the logic, including how to work out what next/previous is, into the controller and keep the view simple:
<%= form_tag facility_directory_path(@facility), method: :get, class: '' do %>
<%= hidden_field_tag 'current_month', @month %>
<%= hidden_field_tag 'current_year', @year %>
<%= submit_tag 'Previous Month', class: 'button' %>
<%= submit_tag 'Next', class: 'button ui basic blue small' %>
<% end %>
This form in the view now just holds the current state (month and year) and has a previous and next. There is no month calculation or default setting.
Then, in your controller, you can detect if:
The value of the button pressed is passed to the controller, so if the next or previous button is pressed you'll see params[:commit]
will be equal to either 'Previous Month' or 'Next'. And, you'll also have params[:current_year] and params[:current_month].
Make sure that your controller creates a default @year and @month as the current one.
The below should cover all of these cases.
if params[:commit] == "Previous Month" || params[:commit] == "Next"
# Handle preview/next buttons
now = Date.new(params[:current_year].to_i, params[:current_month].to_i, 1)
if params[:commit] == "Previous Month"
target_date = now - 1.month
else
target_date = now + 1.month
end
elsif params.has_key?(:select)
# Handle the select drop down
target_date = Date.new(params[:select][:year].to_i, params[:select][:month].to_i)
else
# Handle the default case - the first day of the current month
target_date = Date.new(Date.today.year, Date.today.month, 1)
end
@year = target_date.year.to_i
@month = target_date.month.to_i
# You can now consolidate the Active Record query into one query which handles all cases
@facility_records = @facility.chart_records.order(created_at: :desc).where(created_at: target_date..target_date+1.month)
Using this approach, you can have one Active Record query which works in all instances.
The best thing to avoid this in future is to:
Hope this helps currently and in future.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.