问题
I want to update the status value in the properties table as (1 or 2 or 3 or 4) when I click on each button.
These are my buttons in my view file:
<td><%= link_to("Waiting for Response", rms_property_approve_property_path(property, {:status => 'Waiting for Response'}), method: :patch, class: "btn btn-success", "data-no-turbolink" => true) %><td>
<td><%= link_to("No Response", rms_property_approve_property_path(property, {:status => 'No Response'}), method: :patch, class: "btn btn-danger", "data-no-turbolink" => true) %><td>
<td><%= link_to("Registered", rms_property_approve_property_path(property, {:status => 'Registered'}), method: :patch, class: "btn btn-success", "data-no-turbolink" => true) %><td>
<td><%= link_to("Not Interested", rms_property_approve_property_path(property, {:status => 'Not Interested'}), method: :patch, class: "btn btn-danger", "data-no-turbolink" => true) %><td>
My properties_controller.rb:
def approve
@property = Property.find(params[:property_id])
if params[:status]== 'Registered'
@property.update_attributes(:status => 1)
redirect_to :back, flash: {notice: "Property has been Registered."}
elsif params[:status]== 'Not Interested'
@property.update_attributes(:status => 2)
redirect_to :back, flash: {notice: "Not Interested."}
elsif params[:status]== 'Waiting for Response'
@property.update_attributes(:status => 3)
redirect_to :back, flash: {notice: "Waiting for Response"}
elsif params[:status]== 'No Response'
@property.update_attributes(:status => 4)
redirect_to :back, flash: {notice: "No Response."}
end
end
My migration file for status column in properties table:
class AddColumnStatusInProperties < ActiveRecord::Migration
def change
add_column :properties, :status, :string
end
end
When I click on the No response button, I get an ArgumentError:
'4' is not a valid status
回答1:
Judging by the error message, it seems that you are using an enum on the status column. You can't use raw values (the integer part of the enum value) with enums unless you skip object instantiation (using update_all, or update_columns, for example).
If you instantiate the object, you must use the enum value (value is :registered, while raw value is 1).
In approve, you need to update the object as such:
# `:registered` should be the enum value, not the number
@property.update_attributes(status: :registered)
And not
@property.update_attributes(status: 4)
This assumes you have declared your enum as such:
class Property < ActiveRecord::Base
enum status: {
registered: 1,
not_interested: 2,
waiting_for_response: 3, # consider renaming to `awaiting_response`
registered: 4
}
end
You should change the column type in the migration to integer. Using string can lead to strange bugs.
rails g migration change_status_column_type_in_properties
class ChangeStatusColumnTypeInProperties < ActiveRecord::Migration
def change
change_column :properties, :status, :integer
end
end
You can also automate the link generation in your view:
<% Property.statuses.each_key do |name| %>
<%= link_to name, rms_property_approve_property_path(property, {status: name}), method: :patch, class: "btn btn-danger", "data-no-turbolink" => true) %>
<% end %>
And simplify the controller code:
def approve
@property = Property.find(params[:property_id])
@property.update!(status: params[:status])
redirect_to :back, notice: t(".#{params[:status]}")
end
And add the flash messages to your locale file. For example:
en:
rms:
properties:
approve:
registered: "Property registered"
waiting_for_response: "..."
Finally, consider using a default value to your column.
change_column :properties, :status, :integer, null: false, default: 3
来源:https://stackoverflow.com/questions/35595408/how-to-update-status-value-in-table-on-each-button-click