Rails: Only update attribute when specified in form - ruby-on-rails

I have a form, in which users can add their birthday. Now currently, whenever someone submits this form, he will add a birthday, as the date input always has a value.
Is there a way I can add a checkbox - and only if it is checked, the birthday should be saved to the record? If the checkbox is not checked though, the current value for birthday should be removed.
= simple_form_for resource, as: resource_name, url: registration_url(resource_name) do |f|
= f.input :another_field
= f.input :birthday_set?, as: :boolean # or something else?
= f.input :birthday
= f.input :submit

In the controller, you could do something like:
def create
user = User.new
user.birthday = params[:user][:birthday_set?] ? params[:user][:birthday] : nil
params[:user].delete(:birthday, :birthday_set?)
user.update_attributes(user_params)
...
end
And just remove the :birthday / :birthday_set? keys from the permit element of your params.
I'd look at moving :birthday_set? into a form_tag field so it sits outside of params[:user] and then you won't have to worry about clearing it from the params. If you're not storing it in the db, this makes more sense anyway.
This will avoid unpermitted parameters being thrown, and do exactly what you're after.
You could also look into disabling the :birthday field in the front end using js when the checkbox is toggled, but would still want to handle this regardless.
Personally, I'd go down #atomAltera's route and use an attr_accessor and before_save, but if you want to avoid that, this approach will work.

Related

Rails Simple Form Default Value if Submitted Nil

I need to overwrite any blank field submissions in my simple form with the text value "N/A". I've found how to set a default value beforehand, but I would like the field left blank for users to fill out and submit, and only changed if they leave it blank. Is this possible? Thanks!
<%= f.input :survey_year, :input_html => { :value => 'N/A'} %>
Should do the trick. See the flipflops.org link in my comment above for alternative approaches.
Try to the following
before_save :default_values
def default_values
self.name ||= 'N/A' #=> note self.name = 'N/A' if self.name.nil?
end
When a user submits a form with blank/nil name then it will submit to "N/A" otherwise none

ActiveAdmin passing variable in controller

I have a permit and vehicle model. I am trying to update the AA create controller to work how I have it in my rails app. That is taking the vehicle license_number entered and inputting it into the permit table, then also taking the inputted permit_id and inputting it into the permits attribute of the vehicle it is related to in the vehicle table.
admin/permit.rb
permit_params :permit_id, :vehicle, :date_issued, :issued_by, :date_entered, :entered_by
form do |f|
f.inputs do
f.input :permit_id
f.input :vehicle, :collection => Vehicle.all.map{ |vehicle| [vehicle.license_number]}
f.input :date_issued, as: :date_picker
f.input :issued_by
end
f.actions
end
controller do
def new
#permit = Permit.new
#vehicle = #permit.build_vehicle
#vehicle = Vehicle.all
super
end
def create
vehicle = Vehicle.find_by(license_number: permit_params[:vehicle_attributes][:license_number])
#permit = current_user.permit.build(permit_params.merge(date_entered: Date.today,
entered_by: current_user_admin.email))
super
end
end
My errors that I am getting, is that it is inputting the license_number in for the permit_id and then it is also saying the permit_params is not a defined variable. Any help would be great, thanks!
You have an interesting case here: it is confusing because you have a model called Permit, and usually in Rails you name the params method something like permit_params. Turns out, permit_params is the general method signature for ActiveRecord to implement strong params: https://activeadmin.info/2-resource-customization.html
With that, instead of calling permit_params in your create action, you need to call permitted_params[:vehicle_attributes][:license_number]. That’s why it’s considering permit_params as an undefined variable. Again, those two method signatures will be the same for all your ActiveAdmin forms.
Additionally, I’m not sure if this is a typo but you define #vehicle twice in your new method. I’m not sure you need to build a vehicle for the permit form unless you’re doing nested forms. Either way, I think the last line should read #vehicles = Vehicle.all Then you can use that in your form, which also could use an update in the collection part of your form field:
form do |f|
f.inputs do
f.input :permit_id
f.input :vehicle, collection: #vehicles.map { |vehicle| [vehicle.license_number, vehicle.id] }
f.input :date_issued, as: :date_picker
f.input :issued_by
end
f.actions
end
The collection_select form tag will take the first item in the array as the value that appears in the form, and the second value will be the value passed through in the params (https://apidock.com/rails/ActionView/Helpers/FormOptionsHelper/collection_select).
Then in your create action, you can find the Vehicle with the id:
Vehicle.find(permitted_params[:vehicle_attributes][:vehicle_id])
I would avoid Permit as a model name, try using VehiclePermit.

Using Role Model and simple_forms to assign roles

First off, I am using Devise, Cancan, Role Model, and simple_form. Everything seems to work with permissions and whatnot. What I can't seem to do is create a form so that I can assign roles to Users.
Here is what I have so far:
<%= simple_form_for(#profile.user) do |f| %>
<%= f.input :roles_mask, as: :check_boxes, collection: User.valid_roles, :checked => [ 'member' , true] %>
<%= f.button :submit %>
This shows the check boxes properly, and the last part flags one as true. I'm not sure how to get it to flag the roles that are supposed to be flagged. I chose one at random for testing Also, if I send it to update, nothing seems to happen. I updated like I normally would limiting my params to just the roles_mask variable.
def update
if #user.update(params.require(:user).permit(:roles_mask))
flash[:notice] = "Permissions updated."
redirect_to profile_path(#user.profile_id)
else
render 'edit'
end
I have no clue what I am doing wrong. Even if I could just get them to update. Not showing the current roles isn't a huge deal.
You don't need to directly access roles_mask property, just assign roles property with the array of roles. Example:
= f.input :roles, collection: User.valid_roles, as: :check_boxes, checked: #user.roles, label_method: proc {|l| User.human_attribute_name(l) }
And don't forget to permit that form value for strong parameters:
params.require(:user).permit(roles: [])

Rails Form_For Select With Dual Purpose

I have form for adding a new job. On my form I have a select drop-down list. I need to associate the new job to a customer. The following works great.
<%= f.collection_select :customer_id, Customer.all, :id, :business_name %>
But, what if I want to also be able to send in a customer_id to the new form? Can I have the form's select drop-down show all the possible customers, as above, but have it auto select the customer_id I pass into the form, if a customer_id is passed in?
url = ...jobs/new
OR
url = ...jobs/new?customer_id=5
I apologize if I did not explain this well enough.
Thanks in advance.
--jc
I think you do what you're trying to achieve this by populating the customer_id field on the job you're creating in your controller if customer_id is present in the request params. This should make that particular customer be the initially selected option in the form.
http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-collection_select
e.g. Something like.
if params[:customer_id].present?
job.customer_id = params[:customer_id]
end
If you declaring the instance variable #customer in your controller action then you can use selected option as:
<%= f.collection_select :customer_id, Customer.all, :id, :business_name, {:selected => #customer.id} %>

Accept Rails model attribute only if it was previously blank

I have a Rails model (persisted with Mongoid) that can be collaboratively edited by any registered user. However, I want to allow editing any particular attribute only if it was previously blank or nil.
For example, say someone created an object, and set its title attribute to "Test Product". Then another user comes along and wants to add a value for price, which until now has been nil.
What's the best way to do this, while locking an attribute that has previously been entered?
Look into the ActiveRecord::Dirty module for some nice utility methods you can use to do something like this:
NON_UPDATABLE_ATTRIBUTES = [:name, :title, :price]
before_validation :check_for_previously_set_attributes
private
def check_for_previously_set_attributes
NON_UPDATABLE_ATTRIBUTES.each do |att|
att = att.to_s
# changes[att] will be an array of [prev_value, new_value] if the attribute has been changed
errors.add(att, "cannot be updated because it has previously been set") if changes[att] && changes[att].first.present?
end
end
The easiest way, i think, is by checking for it in the form itself.
Just say add :disabled => true to the input field if the person cannot edit it.
<% if #my_object.name %>
<%= f.text_field :name, :disabled => true %>
<% else %>
<%= f.text_field :name, :disabled => true %>
<% end %>
(i think there is a prettier way to write this code)
But by using this the user has a visual feed back that he can't do something, it is always better to not allor something than to give an error message

Resources