I have a polymorphic model and want to have a nested form use this model. I am getting no errors but the form is not displaying the nested field. Here are my models and stripped down form:
Polymorphic Model
class SeoMapping < ActiveRecord::Base
belongs_to :mappingtable, :polymorphic => true
attr_accessible :seo_url
validates :seo_url, :presence => true, :uniqueness => true
end
Page model using the Polymorphic Model
class Page < ActiveRecord::Base
has_one :seo_mappings, :as => :mappingtable, :dependent => :destroy
accepts_nested_attributes_for :seo_mappings
attr_accessible :content, :h1, :meta_description, :title, :seo_mappings_attributes
.........
end
Now stripped down form
<%= form_for(#page) do |f| %>
<% if #page.errors.any? %>
.......
<% end %>
<div class="field">
<%= f.fields_for :seo_mappings do |builder| %>
<%= builder.label :seo_url %><br />
<%= builder.text_field :seo_url %>
<% end %>
</div>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
.........
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I cant see why it does not display the fields_for elements. If I comment out accepts_nested_attributes_for the field then displays. Can you see where I am going wrong ?
TY
Possibly a silly question but is this the create or edit action you're talking about? And if it's create, did you call #page.build_seo_mapping or something in the controller?
Also (may be unrelated) if you use has_one, usually you want to use a singular noun, so has_one :seo_mapping instead of mappings.
Related
I have three models in my rails 5 application... What I want to do is to be able to create a note on the person's "show" view, then the note should automatically link to that person and any other person I choose to attach the note to.
Here's where I got up to
Note
class Note < ApplicationRecord
has_many :person_notes
has_many :people, through: :person_notes
accepts_nested_attributes_for :person_notes
end
Person Note (Join table)
class PersonNote < ApplicationRecord
belongs_to :person
belongs_to :note
end
Person
class Person < ApplicationRecord
has_many :person_notes
has_many :notes, through: :person_notes
accepts_nested_attributes_for :person_notes
accepts_nested_attributes_for :notes
end
In my "show" section of my "people" controller I have the following:
def show
#notep = Note.new()
#person.notes << #notep
end
This is creating a join of a new note to my person record every time I open the page (obviously i only want the join to happen on the note I have created.)
I have rendered this in a modal as a partial in my "show" view (there is an "end" and a submit button but it's in between 3 divs and I know they weren't the cause of the issue so i didn't include them.:
<%= simple_form_for(#notep, remote: true) do |f| %>
<%= f.error_notification %>
<%= f.input :subject %>
<%= f.input :note %>
<%= f.input :date, html5: true %>
<div class="input-field">
<%= f.check_box :isalert, :id => "alert" %>
<%= f.label :isalert, :for => "alert" %>
</div>
<div class="input-field">
<%= f.check_box :archived, :id => "archived" %>
<%= f.label :archived, :for => "archived" %>
</div>
<div class="input-field">
<%= f.check_box :deleted, :id => "deleted" %>
<%= f.label :deleted, :for => "deleted" %>
</div>
<%= f.input :datecreated, html5: true %>
<%= f.input :user_id %>
<%= f.simple_fields_for :person_notes do |builder| %>
<%= builder.association :person, label_method: :lstfstfullname %>
<%= builder.input :deleted %>
<%= builder.input :datecreated, html5: true %>
<%= builder.input :user_id %>
<% end %>
You can probably tell I'm a total newb, but I'd appreciate any help I can get.
Thanks,
Leah
If I'm understanding this correctly, you'll want a separate Notes controller and create action to handle note creation. Then in your People show view, you can add a form and input field that submits to NotesController#create.
I'm using nested forms in my rails app and I have a simple parent-child setup:
Models:
class Experiment < ActiveRecord::Base
has_many :exptypes, :dependent => :destroy
accepts_nested_attributes_for :exptypes, :allow_destroy => true
class Exptype < ActiveRecord::Base
belongs_to :experiment
Views:
Parent:
<%= nested_form_for(#experiment) do |f| %>
<%= f.fields_for :exptypes do |builder| %>
<%= render 'exptype_fields', :f => builder %>
<% end %>
<p><%= f.link_to_add "Add an Experimental Type", :exptypes %></p>
Child:
<h2>Experiment type</h2>
<p>
<div class="field">
<%= f.link_to_remove "Remove this Experiment" %>
</div>
<div class="field">
<%= f.label :type_name %><br>
<%= f.text_field :type_name %>
</div>
</p>
The addition of many children works fine, but when I try to remove any from the list (by clicking the button created by link_to_remove), the nested form disappears, but when I hit update, the show form still shows the "deleted" child.
Found the error, I didn't have :_destroy in my permitted parameters in my controller.
Hope this helps someone else!
Edit:
My controller's strong params method looks as follows:
def experiment_params
params.require(:experiment).permit(:_destroy, :experiment_number, :date, :title, :pi,
:biocontrol_run_num, :goals, :description, :str, :exp_type)
end
I have an error "Can't mass-assign protected attributes: Upload", but I have assigned it to be accessible.
This is a nested form with a polymorphic association.
Models
class Upload < ActiveRecord::Base
attr_accessible :link, :post_id
belongs_to :uploadable, polymorphic: true
end
class Post < ActiveRecord::Base
attr_accessible :description, :title, :uploads_attributes
has_many :uploads, as: :uploadable
accepts_nested_attributes_for :uploads, :reject_if => lambda { |a| a[:content].blank?
}, :allow_destroy => true
end
I tried too put accept_nested ... for :uploadable but tells me dont exist the association
The action new on the controller is this one
def new
#post = Post.new
#post.uploads.new
end
and here is the form for create
<%= form_for [:admin,#post], remote: true, :html => {:multipart => true} do |f| %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title%>
</div>
<div class="field">
<%= f.label :description%><br />
<%= f.text_area :description %>
</div>
<div>
<%= f.fields_for :upload do |builder| %>
<%= render 'upload_fields', f: builder %>
<% end %>
<%= link_to_add_fields "Add Upload", f, :uploads %>
</div>
<div class="actions">
<%= f.submit%>
</div>
<% end %>
The partial ...
<fieldset>
<%= f.label :file %><br />
<%= f.file_field :file %>
<%= f.hidden_field :_destroy %>
<%= link_to "remove", '#', class: "remove_fields" %>
</fieldset>
Dont think the javascript affects, so Im not going to put it here.
How I cna solve "Can't mass-assign protected attributes" on polymorphic asociations ?
Plz need help on this anyone. Cant belive I cant upload files, looks so simple on tutorials, and Its not working, or I get a Can't mass assign orthe upload its not saved ....
Try to use #post.uploads.build instead of #post.uploads.new
The associated model needs to know the identity of her parent to save the relationship.
I recommend you the following railscast: Polymorphic Association.
#uploads_controller.rb
before_filter :load_uploadable
def create
#upload = #uploadable.uploads.new(params[:upload])
....
end
private
def load_uploadable
resource, id = request.path.split('/')[1, 2] # /posts/1
#uploadable = resource.singularize.classify.constantize.find(id)
end
This line inside your view:
<%= f.fields_for :upload do |builder| %>
Should be this:
<%= f.fields_for :uploadable do |builder| %>
Because the association on the Post model is called "uploadable", not "upload".
For nested attributes to work, you will need to specify the model does accept nested attributes for this model, which can be done by putting this line underneath the belongs_to in your model:
accepts_nested_attributes_for :uploadable
And then you will need to make these attributes accessible, which you can do with this:
attr_accessible :uploadable_attributes
I followed Episode 196 from Railcasts but seem that if i follow his it doesn't work quite yet, maybe cause the code is old or i just don't get rails.
Here I have 3 models
Customer Book Book_Manager
id id id
first description customer_id
last book_manager_id visible
email
password
Here are my relationship
Book
belongs_to :book_manager
def customer
book_manager.customer
end
Customer
has_many :book_managers, :dependent => :destroy
accepts_nested_attributes_for :book_managers
BookManager
belongs_to :customer
has_many :books, :dependent => :destroy
accepts_nested_attributes_for :books
The form is has follow
<%= form_for #bookmanager do |f| %>
<%= f.fields_for :books do |builder| %>
<div>
<%= builder.label :description %><br />
<%= builder.text_area :description, :rows => 3 %>
</div>
<% end %>
<div class="field">
<%= f.label :visible %><br />
<%= f.text_field :visible %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
If i comment out the line
accepts_nested_attributes_for :books
It show the description box, if however i place it there the box does disapear. Did i miss something??
I think you have to pass a book object here. Try
<%= f.fields_for :books, Book.new do |builder| %>
i understand that if someone goes to an objects edit path, the form_for fields should populate. most of mines do except this one field, which has a has_many :through relationship with another table. how do you get it to pre populate with whatever the using typed in at creation?
for example...
<div class="lesson_content">
<%= f.label :content %>
<%= f.text_area :content %>
</div>
<div class="tags">
<%= f.label :tag_names, "Tags" %>
<%= f.text_field :tag_names, data: { autocomplete_source: tags_path} %>
</div>
my lesson content will populate correctly, but not my tags field. i have a lessons table, tags table, and an intervening tags_relationship table.
my lessons class is...
class Lesson < ActiveRecord::Base
attr_accessible :title, :desc, :content, :tag_names
belongs_to :user
has_many :tag_relationships, :autosave => true
has_many :tags, :through => :tag_relationships, :autosave => true
how do i get the tags field to populate? thanks
What you need is fields_for nested in your form. Details are here http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for
Even better, check out this great screencast from Ryan Bates that he just released http://railscasts.com/episodes/196-nested-model-form-revised
What you need is call accepts_nested_attributes_for from your Lesson class:
# app/models/lesson.rb
class Lesson < ActiveRecord::Base
attr_accessible :title, :desc, :content, :tag_names
belongs_to :user
has_many :tag_relationships, :autosave => true
has_many :tags, :through => :tag_relationships, :autosave => true
accepts_nested_attributes_for :tags
end
And then, in your controller/view:
# app/controllers/lessons_controller.rb
class LessonsController < ActiveSupport::Controller
def edit
#lesson = Lesson.find(params[:id])
end
end
<%= form_for(#lesson) do |f| %>
<div class="lesson_content">
<%= f.label :content %>
<%= f.text_area :content %>
</div>
<div class="tags">
<%- #lesson.tags.each do |tag| -%>
<%= fields_for(tag) do |t| %>
<%= t.label :name, "Tag" %>
<%= t.text_field :name, data: { autocomplete_source: tags_path} %>
<%- end -%>
<%- end -%>
</div>
<%- end -%>
However, this would show a text field for every tag. If you want to use a single text field for all the tags (separated by commas, for example), and also retrieve lessons filtering by tags, you should check this gem: acts-as-taggable-on.