I have a bit of an interesting predicament. I have an :ingredients field which I'm using to get user-input for an ingredient. Each ingredient belongs to a recipe, which is the form_for (the :ingredients is the field_for). However, the user should be able to enter multiple ingredients, an unlimited amount. Right now I've implemented functionality for adding 1 ingredient, as shown here:
<%= form_for(:recipe, :url => {:action => 'create'}) do |f| %>
<%= fields_for :ingredient do |i| %>
<%= i.text_field(:quantity, :size => '6', :maxlength => '6') %>
<%= i.text_field(:units, :size => '20', :maxlength => '20') %>
<% end %>
<% end %>
To simplify things, I'm going to scratch the unlimited requirement, which I will do later with AJAX, and assume the user only puts in a max of 20. I'm confused as to how to design my form_for to do that, and to access each of those 20 elements in my controller. Would it be something like params[:recipe][1...20]?
I read this question:
How can I create multiple instances of an assosiated model from a rails 3 form_for when I don't know how many I'm going to add?
but I'm still stuck and I would like to avoid using Gems if possible (silly constraint I know).
Have a look at nested_form gem inorder to add multiple ingredients. Also look at
class Recipe < ActiveRecord::Base
accepts_nested_attributes_for :ingredients
end
inside recipe controller new action..
def new
#recipe = Recipe.new
#recipe = #recipe.ingredients.build
end
inside view
<%= nested_form_for(#recipe, :url => {:action => 'create'}) do |f| %>
Related
im using the cocoon gem to build some dynamic form in which i can add new text fields. Ive read others people same problem but i dont know what im doing wrong, i know it has to be something with the associations but i dont seem to get it.
So these are my models:
class MonitorCategory < ActiveRecord::Base
validates :operation, presence: true
attr_accessor :oid, :oid2, :oids, :snmp_oper, :custom_tab_name, :custom_tab_unit, :redfish, :ipmi
has_many :oids
has_and_belongs_to_many :sensors
accepts_nested_attributes_for :oids
class Oid < ActiveRecord::Base
belongs_to :monitor_category
end
And my form:
<%= simple_form_for(:monitor_category, url: create_monitor_category_path, :html => { :remote => true, :method => :post }) do |f| %>
<div id='oids'>
<%= f.simple_fields_for :oids do |oid| %>
<%= render 'oids_fields', :f => oid %>
<% end %>
<div class='links'>
<%= link_to_add_association 'add oid', f, :oids %>
</div>
</div>
with the partial _oids_fields.html.erb:
<div class='nested-fields'>
<%= f.input :oids %>
</div>
What am i doing wrong? Im getting undefined method `reflect_on_association' for NilClass:Class:. Form is okay since i was looking at the page of cocoon and is the same syntax, so i guess it must be something with the associations but i dont really know, im kind of new to the rails world. Maybe since it says nilClass, i need to create a controller for the Oid model in which i make a new method or something? im lost.
Apparently this doesnt work either, i have the same error:
class OidController < ApplicationController
def new
#oid = Oid.new
end
end
thank you for every answer.
edit: just to be more clear, because im very confused.
Before trying to implement this dynamic form, i already have a form which is working correctly. For example, last two fields are these:
<div class="col-md-12">
<%= f.input :oid, label: 'SNMP OID', as: :search, placeholder: 'Output stored in var1.', required: false, novalidate: true, input_html: {data: { autocomplete_source: get_oids_path }} %>
</div>
<div class="col-md-12">
<%= f.input :oid2, label: 'SNMP OID 2', as: :search, placeholder: 'Output stored in var2.', required: false, novalidate: true, input_html: {data: { autocomplete_source: get_oids_path }} %>
</div>
So basically here im storing the values entered on the attribute :oid and :oid2 from the model .
but instead of having these two fields, i want to have only one, and add more dynamically, so i can enter for example 6 values and saved them all on the :oids attribute. Since i was saving the valued on an attribute, i dont know if i have to create a model for Oid, like a did before, and make it belong_to monitor_category. Or if i can just add an attribute :oids to the controller and store all the values in that variable.
The problem is this line
simple_form_for(:monitor_category, url: create_monitor_category_path, :html => { :remote => true, :method => :post }) do |f|
This creates a form for a MonitorCategory but does not set an object. So when you then call f.simple_fields_for there is no object to iterate over the associations.
Normally in the controller you set a #monitor_category instance variable, which is either set to an existing instance (when editing) or a newly created item.
And then you can write:
simple_form_for(#monitor_category, :html => { :remote => true, :method => :post }) do |f|
Rails is smart enough to deduce the url from the object, it will either create a new one or update an existing one.
Is that clear enough?
I think it's because your form is for a monitor_category and the url is pointing to the create_monitor_category_path. But you're showing us the OidController. You would need something like:
class MonitorCategoryController < ApplicationController
def new
#monitor_category = MonitorCategory.new
#monitor_category.oids.build
end
end
This will initialize the parent object and then build the child association. You need to build at least one child for the fields to show up when using fields for.
In a rails 4 application, I have a book resource, that is a Book model with its controller, views and route. It's what gets created by:
rails g scaffold book title
Now I want to have another set of views (and another controller) that allows to manage the same model, maybe dedicated to a different user.
I want both the creating function and the editing function to be available on this different route and view, .
Let's call it book2.
The views in the /book2 url should operate on the Book2sController.
form_for support
But the form_for guesses the submit route (and puts it in the action attribute) from the model class, that, being it always Book, lets rails guess that the submit url is /books/1 for edit or /books/ for new and not /book2s/1 for edit and /book2s/ for new as it should be.
So i found this solution, but i find it to be a bit cumbersome.
Is there anything better out there?
<%= form_for #book, :url => #book.new_record? ? url_for(book2s_path) : url_for(book2_path(#book)) do |f| %>
<%= f.text_field :title %>
<% end %>
You could set the url in your controller.
def new
# ...
#form_url = book2s_path
# ...
end
def edit
# ...
#form_url = book2_path(#book)
# ...
end
Then your view becomes:
<%= form_for #book, :url => #form_url do |f| %>
<%= f.text_field :title %>
<% end %>
I have also seen:
<%= form_for #book, :url => {:controller => 'book2s', :action => #action} do |f| %>
<%= f.text_field :title %>
<% end %>
and you just set #action in the controller (probably create or update).
Note that you don't need to include the url_for like you have.
I'm putting up the same question I asked here in activeadmin's issues board on github:
https://github.com/gregbell/active_admin/issues/645
Hi,
I have two different issues.
1: i love the way active admin handles has_many relationships with a simple DSL like so:
ActiveAdmin.register Artist do
form do |f|
f.inputs do
f.input :name
f.input :description
end
f.inputs "ArtistLinks" do
f.has_many :artist_links do |j|
j.inputs :title, :url
end
end
f.buttons
end
end
The ability to add more links at the bottom of the form is great.
However,I have been using a wyiswyg which i can't seem to get working in this format. I've been using/adding it with a partial like so:
ActiveAdmin.register NewsItem do
form :partial => "/news_items/form"
end
/app/views/news_item/_form.html.erb
<%= javascript_include_tag "/javascripts/ckeditor/ckeditor.js" %>
<%= semantic_form_for [:admin, #news_item], :multipart => true do |f| %>
<%= f.inputs :title, :photo, :excerpt %>
<%= cktext_area_tag("news_item[content]", #news_item.content) %>
<%= f.submit %>
<% end %>
However,
in my partial, i can't seem to be able to make the has_many relationship nicely like so:
f.inputs "ArtistLinks" do
f.has_many :artist_links do |j|
j.inputs :title, :url
end
end
Could you either explain to me how to get my wysiwyg which uses a form helper cktext_area_tag into my admin resource or explain to me how to get that nice has_many into my view partial?
Thanks a bunch!
The reason why has_many does not work in partials is because Active Admin tells you to use semantic_form_for when writing your partial. Active Admin extends Formtastic which it uses to generate forms. It does so by creating its own form builder that extends the Formtastic builder and adds, among others, the has_many method. So if you want to use that inside partials you have to use the Active Admin form builder. To do that use active_admin_form_for instead of semantic_form_for.
If you have problems using active_admin_form_for, take a look at my branch which should fix most of the issues (it's still beta - but I'm working on getting it into Active Admin core)
Alright, I know my title is a little obscure but it best describes the problem I am having.
Essentially, I have a list of users, and want to be able to edit their information in-line using AJAX.
Since the users are showing up in rows, I am using a partial to render the data and the forms (which will be hidden initially by the ajax), however, when the rows are rendered currently only the last item has it's form's fields populated.
I suspect this has something to do with the fact that all the form fields have the same id's and it is confusing the DOM. But I don't know how to make sure the id's are unique.
Here is a small example:
In my view:
<%= render :partial => 'shared/user', :collection => #users %>
My partial (broke down to just the form) note that I am using the local variable "user"
<% form_for user, :html => {:multipart => true} do |f| -%>
<%= f.label :name, "Name*" %>
<%= f.text_field :title, :class => "input" %>
<%= f.label :Address, "Address" %>
<%= f.text_field :address, :class => "input" %>
<%= f.label :description, "Description*" %>
<%= f.text_area :description, :class => "input" %>
<% end -%>
When the html is rendered each form has a unique id (for the id of the user) but the elements themselves all have the same id, and only the last user form is actually getting populated with values.
Does anyone have any ideas?? :)
Thanks in advance!
Alright, after having some lunch and regaining some brain cells, (and with a little help from Google) I figured this one out.
When passing a collection to a partial like this:
<%= render :partial => 'shared/user', :collection => #users %>
Rails creates a counter variable that you can use to define an index for the form in the form of "variable_counter":
<% form_for user, :index => user_counter, :html => {:multipart => true} do |f| -%>
This adds the index number to the form id as well as all the field id's and solved my little problem. :)
I hope this helps out someone else with this issue. :)
I am still kind of fuzzy on controllers in rails, especially so because a lot of things seem to happen magically behind the scenes, and that's not happening in this case.
So say I have a person model, which has many photos (using paperclip) and has many favorite quotes. The quotes can have the text, the attributed author, etc. In both of those models, they are set as belonging to my person model.
Within a new person form, I used some code elsewhere to create a new photo:
<% form.fields_for :screenshots, :html => { :multipart => true } do |screen_form| %>
<%= render :partial => 'screenshot', :locals => { :form => screen_form } %>
<% end %>
The partial for that is very simple, like this (minus some ajax javascript stuff I put in for nested models):
<%= form.label :photo, "Screenshot:" %>
<%= form.file_field :photo %>
This all works fine and magically the ID of the person is associated with a screenshot upon creation in person_id. I don't even have a controller for screenshots and it still works.
However, it's not working for my quotes.
<% remote_form_for :quote, :html => { :method => :put }, :url => {:controller => "quote", :action => "create", :person_id => #person.id} do |quote_form| %>
<%= render :partial => 'quote', :locals => { :form => quote_form } %>
<% end %>
The partial for this is also very simple.
<%= form.label :quote_text %>
<%= form.text_field :quote_text %>
.........
<%= form.submit 'Create' %>
I am not really sure if I can put person ID in there, but it didn't complain. However it didn't work, either. The quotes controller is very simple.
def create
#quote = Quote.create(params[:quote])
end
Currently it gets put in the DB but person_id is not populated so I can't pull up the quotes associated with a particular person. Sorry if this is a silly question, but I'm kind of learning Rails by tweaking tutorials and mashing them together so bear with me :) It's just kind of mysterious how the photo thing works with NO controllers or special stuff and this doesn't.
The first form is a person form mainly that has snapshots fields associated to it, so looking at your HTML you will find something like person[snapshots][photo], this form will be submitted to person controller.
Passing person id to second form the is key to make it work, however it's a bit weird that it's not working, the form will submit to quote controller. Did you make sure(watch the log) that the params hash has person_id attribute?