I'm building a rails project, I have two models: User and Attachment. User has many attachments. One of the columns for the Attachment is salutation, and it can be mr or mrs (enum attributes 0 and 1).
In my ActiveAdmin, when I create a user, I have a dropdown where I can select one of the two options. The selected value is empty. I want to make the mr value preselected.
I tried this but it doesn't work:
<%= semantic_form_for [:admin, user], builder: ActiveAdmin::FormBuilder do |f| %>
<% f.has_many :attributes, heading:false do |g| %>
<% g.input :salutation, value: 'mr' %>
<% end%>
<%= f.actions%>
<% end %>
Did you try with:
g.input :salutation, input_html: { value: 'mr' }
Related
Issue: I have a nested fields_for text_field not appearing, I am not sure what I have been done wrong.
Goal: While creating a record, iterate through a model with preset variables, and save a file (testing with text_field) to a join table which saves both the preset variables and the forms record ID
Models:
class PrintLocation < ApplicationRecord
has_many :shop_products, through: :shop_product_print_files
has_many :shop_product_print_files
accepts_nested_attributes_for :shop_product_print_files
end
class ShopProductPrintFile < ApplicationRecord
belongs_to :shop_products
belongs_to :print_locations
end
class ShopProduct < ApplicationRecord
...
has_many :shop_product_print_files
has_many :print_locations, through: :shop_product_print_files
accepts_nested_attributes_for :print_locations
accepts_nested_attributes_for :shop_product_print_files
...
end
Form:
<%= form_for #shop_product do |f| %>
<%= f.collection_select :product_id, #products, :id, :sku %>
<% PrintLocation.all.each do |print_location| %>
<%= print_location.title %>
<%= f.fields_for :shop_product_print_files do |a| %>
<%= a.text_field :print_file %>
<% end %>
<% end %>
<%= f.submit %>
<% end %>
With this, the text_field doesn't appear but the print_location.title's do appear. There are no errors with this.
While saving the #shop_product, I want to be able to iterate through the possible print_location variables, which are defined, and then for each possible print_location, to then be able to upload a file (text_field for testing), and then save that to the ShopProductPrintFile model which has shop_product_id and print_location_id and print_file attributes.
Is there something I am misunderstanding for how to use fields_for?
Shop Product Controller:
Create:
#shop_product = ShopProduct.new(shop_product_params)
shop = Shop.find(params["shop_product"]["shop_id"])
product = Product.find(params["shop_product"]["product_id"]) #shop_product.product_id = product.id
#shop_product.shop_id = shop.id
respond_to do |format|
if #shop_product.save!
...
Update:
#shop_product = ShopProduct.find_by(store_variant_id: params["shop_product"]["store_variant_id"])
#product = Product.find(params["shop_product"]["product_id"])
Strong Params:
def shop_product_params
params.require(:shop_product).permit(:product_id, :store_product_id, :shop_id, :store_variant_id, :sync, :shop_product_print_file_attributes[:id, :print_files, :print_location_ids => [], :shop_product_ids => []], {print_location_ids: []})
end
UPDATE 2:
Update and Create Method:
#shop_product.shop_product_print_files.build
form:
<% PrintLocation.all.each do |print_location| %>
<%= print_location.title %>
<%= f.fields_for :shop_product_print_files_attributes do |a| %>
<%= a.text_field :print_file %>
<%= a.hidden_field :print_location_id, value: print_location.id %>
<%= a.hidden_field :shop_product_id, value: shop_product.id %>
<% end %>
<% end %>
params:
def shop_product_params
params.require(:shop_product).permit(:shop_product_print_files_attributes => [:ids => [], :print_files => [], :print_location_ids => [], :shop_product_ids => []])
end
error:
Shop product print files shop products must exist
Shop product print files print locations must exist
params that pass:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"u/c103465uNCjF/trYrMleqxJ8b9wyLbU/vjPK4llYtCg/ODj92q5MN24==", "shop_product"=>{"sync"=>"1", "product_id"=>"3", "shop_product_print_files_attributes"=>{"print_file"=>"", "print_location_id"=>"6", "shop_product_id"=>"42"}, "store_product_id"=>"191234345", "store_variant_id"=>"15341234273", "id"=>"42"}, "commit"=>"Sync", "id"=>"42"}
The models haven't changed.
Print file in params still blank?
UPDATE 3:
**using this form: thanks to #arieljuod **
<%= f.fields_for :shop_product_print_files do |ff| %>
<%= ff.object.print_location.title # get the print location from the association %>
<%= ff.hidden_field :print_location_id # save the print_location_id as a hidden field %>
<%= ff.file_field :print_file # file input %>
<% end %>
with this in the new and method housing the view:
#shop_product = ShopProduct.new
PrintLocation.all.each{|p| #shop_product.shop_product_print_files.build(print_location: p)}
works on create.
Issue still arises due to not knowing the ID of the ShopProduct until the page loads due to API and there is a possibility of being multiple IDs on one page.
I use:
<% if #shop_products.find_by(store_variant_id: variant.id) %>
<% shop_product = #shop_products.find_by(store_variant_id: variant.id) %>
<%= form_for shop_product do |f| %>
...
Which, variant comes from a loop defined by an API:
<% #in_store_variants.each do |variant| %>
Now when using shop_products (from when shop_product already exists from finding by the variant.id), the fields_for won't appear. Assuming this is because no records exist in relation. Only if a shop_product.shop_product_print_files exist, will they appear.
The only work around, at this time to my knowledge, is to save all print_locations but use a boolean for which are actually active, or search for which print_locations have an ID attached. But i would rather not do it that way and just save which print_locations are chosen on create (chosen by uploading a print_file).
To "fix" this issue, I:
added accepts_nested_attributes_for reject_if: proc { |attributes| attributes['print_file'].blank? } which doesn't save ShopProductPrintFile's unless the print_file field is submitted with something...
use this form (2 forms depending on if exists or not)
<% if #shop_products.find_by(store_variant_id: variant.id) %>
<%= form_for shop_product do |f| %>
<% PrintLocation.all.each{|p| shop_product.shop_product_print_files.build(print_location: p)} %>
<%= f.fields_for :shop_product_print_files do |ff| %>
<%= ff.object.print_location.title %>
<%= ff.hidden_field :print_location_id %>
<%= ff.text_field :print_file %>
<% end %>
<%= f.submit "Sync" %>
<% end %>
<% else %>
<%= form_for #shop_product do |f| %>
<% PrintLocation.all.each{|p| #shop_product.shop_product_print_files.build(print_location: p)} %>
<%= f.fields_for :shop_product_print_files do |ff| %>
<%= ff.object.print_location.title %>
<%= ff.hidden_field :print_location_id %>
<%= ff.text_field :print_file %>
<% end %>
...
The issue with 2 is i have have PrintLocation 1,2,3 associated, it will show 9 fields, the 1,2,3 ready for update, and the 6 ready for create.
is it possible to call the PrintLocation.all.each{|p| #shop_product.shop_product_print_files.build(print_location: p)} on already created ShopProducts's for where a shop_product_print_file doesn't exist in relation to the possible print location.
So for example...
Created ShopProduct with print location, 1,2,3 (out of 6 possible)
Now, shop_product_print_location where print_location exists will show for updating in the form, so thats 1,2, and 3. How can I have it so the other 3 that weren't created now show to update the ShopProduct and create new ShopProductPrintFile's? so it is possible to update the ShopProduct to have more print_locations to the shop_product_print_file model.
I have a nested fields_for text_field not appearing, I am not sure
what I have been done wrong.
You should add this line in your create action
#shop_product = ShopProduct.new(shop_product_params)
#shop_product.shop_product_print_files.build #this one
Also change shop_product_print_file_attributes to shop_product_print_files_attributes to avoid any further errors.
You have to tell rails which PrintLocation to use on each iteration since your object does not have any
<%= f.fields_for :shop_product_print_files, print_location do |a| %>
I'm not really sure if that's what you want, but the field will appear.
EDIT: so, I think you need something like this:
On the controller
#shop_product = something_to_get_the_product
PrintLocation.all.each{|p| #shop_product.shop_product_print_files.build(print_location: p)}
I prefer to do this here, I don't like that logic on the view
Now you have all the possible print location prebuilt on the shop product object
On the form
# note here the multipart option to allow files
<%= form_for #shop_product, multipart: true do |f| %>
<%= f.collection_select :product_id, #products, :id, :sku %>
<%= f.fields_for :shop_product_print_files do |ff| %>
<%= ff.object.print_location.title # get the print location from the association %>
<%= ff.hidden_field :print_location_id # save the print_location_id as a hidden field %>
<%= ff.file_field :print_file # file input %>
<% end %>
<%= f.submit %>
<% end %>
I got simple_form for testrun model with multiple checkboxes, that save an array of testcases in a model field
app/views/testruns/_form.html.erb
<%= simple_form_for #testrun do |f| %>
<%= f.input :testcase, as: :check_boxes,
collection: [["testcase1", :testcase1], ["testcase2", :testcase2], ... ]%>
<%= f.submit %>
<% end %>
It works fine, but from now I need to create another model called testcase. After submitting form, besides creating a new testrun instance, I need to create testcase instances which depends on every flag checked.
Any idea how can I do it?
You need to use accepts_nested_attributes_for and simple_fields_for. Assuming you have has_many :testcases in Testrun and the field name of Testcase is name, the below steps should put you in the right direction.
#app/models/testrun.rb
accepts_nested_attributes_for :testcases
#app/controllers/testrun_controller.rb
def new
#testrun = Testrun.new
#testrun.testcases.build
end
private
def testrun_params
params.require(:testrun).permit(:field1, :field2.., testcases_attrubtes: [name: []])
end
#app/views/testruns/_form.html.erb
<%= simple_form_for #testrun do |f| %>
<%= f.simple_fields_for :testcases do |testcase| %>
<%= testcase.input :name, as: :check_boxes,
collection: [["testcase1", :testcase1], ["testcase2", :testcase2], ... ]%>
<% end %>
<%= f.submit %>
<% end %>
This is a field that lets people select an article, that they want to connect with the present article to:
<%= form_for(Relation.create, remote: true) do |f| %>
<%= f.hidden_field :dependent_id, :value => #article.id %>
<%= f.collection_select :dependency_id, Article.all.reject{|x| (x.dependency_hack.map{|x| x.dependent_id}.include? #article.id) &&
(if current_user then x.dependency_hack.map{|x| x.user}.include? current_user end) ||
x.id == #article.id}, :id, :title, {} %>
<%= f.submit "Add suggestion" %>
<% end %>
But this loads all article titles, which is wasteful and slow. Instead, titles should be loaded dynamically, after the user types a few characters.
I would like to rewrite a form which is used to update a record on a database.
I want to update the form so that the form input does not show the record, as
the record is outputted by the line
<%= q.object.content %>.
I want the
form input not to display the record, and I want that the record is updated
when the input field is edited, and is not edited when it is left blank.
I am new at working with forms and don't know the best way to achieve this.
Can anyone provide any help on achieving this ? Below is the current form. Any help would be appreciated.
<%= semantic_form_for #bunchOfThings do |f| %>
<%= f.inputs do %>
<%= f.semantic_fields_for :aThing, #aThing do |q| %>
<%= q.object.content %>
<%= q.input :content, label: "A Thing: #{q.object.content}" %>
<% end %>
<% end %>
<%= f.action :submit , label: t('Some Text'), button_html: { class: 'btn btn-primary' } %>
<% end %>
You can manually set the default value of a field to an empty string by changing this line:
<%= q.input :content, label: "A Thing: #{q.object.content}" %>
To this:
<%= q.input :content, label: "A Thing: #{q.object.content}", input_html: {value:''} %>
You would also need to filter out blank fields on the backend within the update controller method. Something like this:
def update
filtered_params = permitted_record_params
filtered_params.keep_if{|k,v| !v.blank? }
record.update(filtered_params)
...
end
Where of course the permitted_record_params method returns your permitted params hash.
These are my params:
{"utf8"=>"✓", "authenticity_token"=>"0RYiIDDgmOk0gCDRkAgHvv+UIgp/BuU33CLThJXqOTE=",
"order"=>
{"operation_in_orders_attributes"=>
{"0"=>{"service_operation_id"=>"5"},
"1"=>{"service_operation_id"=>""},
"2"=>{"service_operation_id"=>"4"},
"3"=>{"service_operation_id"=>""},
"4"=>{"service_operation_id"=>""}},
"kontakt"=>"comment", "Car_id"=>"50"},
"commit"=>"Dodaj",
"car_id"=>"dw815gn"}
Order has many operation_in_orders
Order has many service_operations through OperationInOrder
OperationInOrder belongs to Order
OperationInOrder belongs to ServiceOperation
ServiceOperation has many operation_in_orders
ServiceOperation has many orders through OperationInOrder
My form:
<%= form_for #order, url: new_car_order_path(#car, #order), html: {class: "add_order"} do |r| %>
<%= r.label "Service", class: :add_order_label %>
<% 5.times do %>
<%= r.fields_for :operation_in_orders do |v| %>
<%= v.collection_select(:service_operation_id, ServiceOperation.all, :id, :nazwa,include_blank: true) %>
<!-- <%= v.text_field :order_id, value: #order.id, :style => "display:none" %> -->
<% end %>
<% end %>
<%= r.label "Kontakt", class: :add_order_label %>
<%= r.text_field :kontakt %>
<%= r.text_field :Car_id, value: #car.id, :style => "display:none" %>
<%= r.label " " %>
<%= r.submit "Add", class: "sub" %>
<%= link_to "Send",ordered_path(car_id: #car.id) , class: 'sub'%>
<% end %>
I have a form where I can choose five ServiceOperations at most to an order and save.
When I save, 5 new OperationInService objects/rows are made.
Is there a possibility to not create those join tables if corresponding field on form is blank?
For example:
I fill only 2 from 5 fields. I save only these two, not 5. Now I save nil values...
I have tried to validate in OperationInService model, but there was an error (rails do not recognize format in controller).
Any ideas?
Update the accepts_nested_form_for method call in Order model as below:
class Order < ActiveRecord::Base
has_many :operation_in_orders
accepts_nested_attributes_for :operation_in_orders, reject_if: proc { |attributes| attributes['service_operation_id'].blank? }
## ..
end
This way record for operation_in_orders would not be created if service_operation_id is blank.