Maybe someone could tell me how to create or correctly pass params from partial form_for to custom controller? Here is what i got so far:
Basically there are two classes: Scribbles (polymorphic - connected to local feeds) and local feeds. Trough command line, I can create scribbles, assign them to local feeds and display them in html. But creating them in trough different controller seems to be a rather tricky task. Any help would be appreciated.
Scribble.rb
class Scribble < ActiveRecord::Base
attr_accessible :post, :comments_attributes, :user_id, :posted_by, :localfeed_attributes
belongs_to :scribbled, :polymorphic => true
has_many :comments, :as => :commentable
accepts_nested_attributes_for :comments
end
localfeed.rb
class Localfeed < ActiveRecord::Base
attr_accessible :city, :scribble_id, :location_id, :localfeed_id, :scribble_attributes
belongs_to :location
has_many :scribbles, :as => :scribbled
accepts_nested_attributes_for :scribbles
validates :city, :presence => true, :uniqueness => true
Here is the error
NoMethodError in LocalfeedsController#newlocalscribble
undefined method `scribbles' for nil:NilClass
Rails.root: c:/workspace/uu2
Application Trace | Framework Trace | Full Trace
app/controllers/localfeeds_controller.rb:80:in `newlocalscribble'
localfeeds/show.erb.html
<% #newlocalscribble = #localfeed.scribbles.new %>
<%=render :partial => 'newlocalscribble.html.erb', :locals => {:newlocalscribble => #newlocalscribble, :localfeed => #localfeed}%>
localfeeds/_newlocalscribble.html.erb
<%= form_for #newlocalscribble, :remote => true, :url => url_for(:controller => 'localfeeds', :action => 'newlocalscribble') do |f| %>
<div class="">
<div class="field">
<%= f.text_area :post,:rows=>3,:placeholder=>"What's on your mind,#{current_user.full_name}?", :class=>"sribble-status-text" %>
<%= f.hidden_field :localfeed, :value => #localfeed.id%>
</div>
<div class="sribble-status-actions" id="newlocalscribble">
<%= f.submit "Share",:class=>"btn btn-info" %>
</div>
</div>
<% end %>
localfeeds_controller.rb
def newlocalscribble
#localfeed = Localfeed.find_by_id(params[:localfeed])
#user = current_user
#newlocalscribble = #localfeed.scribbles.create(params[:localscribble])
##localscribble.scribbled = #user
##localscribble.scribbled = #localfeed
end
def new
#localfeed = Localfeed.new
#feed = Localfeed.find_by_id(params[:localfeed])
#newlocalscribble = #feed.scribbles.new
end
routes.rb
resources :localfeeds do
resource :scribbles
collection do
post 'localscribble', :action => :newlocalscribble
end
end
Variables passed.
{"utf8"=>"✓",
"authenticity_token"=>"1+/Qu/o4EeEbpiL/g07XFa3756IQDo6ldmKH196EkSQ=",
"scribble"=>{"post"=>"hfdfs",
"localfeed"=>"1"},
"commit"=>"Share"}
most likely your variable params[:localfeed] is not set right. It is either nil or the value that came in is not in the database.
Solved It by passing the :locals => {:scribble => #scribble, :localfeed => #localfeed} to pass the right feed ID params to partial, and deleted the hidden field which created a duplicate and cause mass assignment error
Thank you Guys
Related
I read hundreds of questions with same issue but couldn't figure it out. here is my form:
<%= form_for(#new_thread, :url => {:action => 'create'}) do |f| %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_field :description %>
</div>
<div>
<%= f.hidden_field :user_id, :value => current_user.id %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
my controller:
def new
#new_thread = NewThread.new
end
def create
#new_thread = NewThread.new(new_thread_params)
# Save the object
if #new_thread.save
# If save succeeds, redirect to the list action
flash[:notice] = "Thread created."
redirect_to(:action => 'index')
else
# If save fails, redisplay the form so user can fix problems
#new_thread = NewThread.order('id ASC')
render('new')
end
end
private
# Use callbacks to share common setup or constraints between actions.
# Never trust parameters from the scary internet, only allow the white list through.
def new_thread_params
params.require(:new_thread).permit(:title, :description, :user_id)
end
my model:
class NewThread < ActiveRecord::Base
has_many :replies, :dependent => :destroy
belongs_to :user
has_many :like_counts, :dependent => :destroy
has_many :dislike_counts, :dependent => :destroy
has_many :new_thread_flags, :dependent => :destroy
validates_presence_of :title
validates_presence_of :description
end
my routes associated with new_thread:
GET /new_threads(.:format) new_threads#index
POST /new_threads(.:format) new_threads#create
new_new_thread GET /new_threads/new(.:format) new_threads#new
edit_new_thread GET /new_threads/:id/edit(.:format) new_threads#edit
new_thread GET /new_threads/:id(.:format) new_threads#show
PATCH /new_threads/:id(.:format) new_threads#update
PUT /new_threads/:id(.:format) new_threads#update
DELETE /new_threads/:id(.:format) new_threads#destroy
DELETE /reply_flags/:id(.:format) reply_flags#destroy
new_threads_search POST /new_threads/search(.:format) new_threads#search
root GET / new_threads#list
everything looks just fine. when i submit my form with empty fields i get this :
undefined method `model_name' for NewThread::ActiveRecord_Relation:Class
otherwise it works just fine. i use the same form partial for update and there validations work too. i am using rails 4.
The problem is here, where you initialize a new #new_thread after the save fails:
#new_thread = NewThread.order('id ASC')
What are you expecting to happen there? Perhaps you meant this?
#new_thread = NewThread.order('id ASC').first
Without choosing one of the NewThreads, the view will try to render the whole collection of them.
You should remove this line:
#new_thread = NewThread.order('id ASC')
Otherwise when save fails you will give user different model to edit. You have already assigned #new_thread so all will work.
i'm building a relations Company :has_many Notes.
i want to be able to add some new notes to a just created company in the Comany#show resource. so in the company scaffold's show.html.erb
i have follwed step by step the cocoon demostration app and from the github mardown, but the examples shows only the method to add nested attribute into _form.html.erb partial. I don't know if there is some particular things to do differently, but when i try to run the Company#show action it retrieves this error:
undefined method `new_record?' for nil:NilClass
this is my code:
show.html.erb:
...
<%= simple_form_for :notes, :html => { :class => 'form-horizontal' } do |note| %>
<%= render 'note_fields', :f => note %>
<% end %>
<%= link_to_add_association 'Aggiungi Nota', f, :notes, :render_options => {:wrapper => 'inline' } %>
...
_note_fields.html.erb:
...
<div class="nested-fields">
<%= f.input :body %>
<%= link_to_remove_association "Elimina Nota", f %>
</div>
...
Company.rb:
...
has_many :notes
accepts_nested_attributes_for :notes, :reject_if => :all_blank, :allow_destroy => true
...
Note.rb
class Note < ActiveRecord::Base
attr_accessible :body, :company_id
belongs_to :company
end
company_controller.rb
def show
#company = Company.includes(:category, :clients, :notes).find(params[:id])
#mapCompany = Company.find(params[:id]).to_gmaps4rails
respond_to do |format|
format.html # show.html.erb
format.json { render json: #company }
end
end
thanks!
Dave
In the following code, the f variable was never defined.
<%= link_to_add_association 'Aggiungi Nota', f, :notes, :render_options => {:wrapper => 'inline' } %>
Try using company instead of f.
So I have seen other articles here on stack about this and a lot of the time people are not doing #post = post.new. I read some where to use the plural...??
any ways I am getting this error on my discussion code:
Model
class Discussion < ActiveRecord::Base
has_many :comment
belongs_to :author
attr_accessible :author_id, :content, :title
validate :comment, :presence => true
validate :title, :presence => true
end
Discussion Controller
class DiscussionsController < ApplicationController
def index
#discussion = Discussion.new
#discussions = Discussion.all
end
def create
#discussion = Discussion.create(params[:discussion])
if #discussion.save
redirect_to tasks_path, :flash => {:success => 'Created a new discussion'}
else
redirect_to tasks_path, :flash => {:error => 'Failed to create a discussion'}
end
end
end
Discussion Form
<%= form_for #discussion do |f| %>
<p><%= f.label :title %>
<%= f.text_field :title %></p>
<p><%= f.label :content %>
<%= f.text_area :content %></p>
<% end %>
Discussion Routes
resources :discussions do
resources :comments
end
Now as far as I know I am doing this right, because I have a task form set up essentially the same way - but I have looked at my code for hours and have googled and tried other examples and now i see this:
undefined method `model_name' for NilClass:Class
Extracted source (around line #1):
1: <%= form_for #discussion do |f| %>
2:
3: <p><%= f.label :title %>
4: <%= f.text_field :title %></p>
Which should mean that I am missing something from my controller.....is it as asilly as a spelling mistake? >.>
Have you tried putting this in your discussion controller?
def new
#discussion = Discussion.new
end
I believe your problem is that you are trying to create a discussion on a task form but have only defined the discussion controller and not the task controller.
u have to add :method => :post to the form for creating the object else the form will get submitted with GET request.
<%= form_for #discussion , :method => :post do |f| %>
Is that the index view that has the form_for?
If not, then you should add a new action to the controller and do #discussion = Discussion.new there and not in your index action.
if ur model relationships are exactly as u have provided, then they are incorrect
class Discussion < ActiveRecord::Base
has_many :comment #has_many :comments
belongs_to :author
attr_accessible :author_id, :content, :title
validate :comment, :presence => true #valide :comments, :presence => true
validate :title, :presence => true
end
In my Rails 3.0 app I have a Client model and a polymorphic Addresses model. As per the code below a client can have many addresses. I would like to my form to update a single client address at a time. I can only seem to get the [addresses_attributes] to appear if I allow all of the client's addresses to be edited at the same time. Is there a way around this?
class Client < ActiveRecord::Base
has_many :addresses, :as => :addressable, :dependent => :destroy
accepts_nested_attributes_for :addresses
class Address < ActiveRecord::Base
belongs_to :addressable, :polymorphic => true
Clients Controller
def edit
#client = Client.find(params[:id])
#addresses = #client.addresses
if params[:address]
#address = #client.addresses.find(params[:address])
else
#addresses ? #address = #addresses.first : #address = []
end
end
def update
#client = Client.find(params[:id])
#client.update_attributes(params[:client])
redirect_to client_path(#client)
end
View
<%= form_for #client do |f| %>
<%= render :partial => 'form', :locals => {:f => f} %>
<%= f.fields_for #address do |addresses_attributes| %>
<%= render :partial => 'addresses/fields', :locals => {:f => addresses_attributes} %>
<% end %>
<%= f.submit %>
<% end %>
EDIT:
Sorry, I reread the post and realized that there were better options. You should add a scope to the Address model or you should create separate associations in the Client using conditions.
http://railscasts.com/episodes/108-named-scope
or see conditions here:
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
DETAIL:
class Address < ActiveRecord::Base
belongs_to :addressable, :polymorphic => true
named_scope :type_one, :conditions => { :address_type => 'one' }
named_scope :type_two, :conditions => { :address_type => 'two' }
<%= f.fields_for #address.type_one do |addresses_attributes| %>
<%= render :partial => 'addresses/fields', :locals => {:f => addresses_attributes} %>
<% end %>
I am trying to run this..
- f.fields_for :referrals do |qf|
But I would like to pass this, #organization.referrals.select{|ref|ref.new_record?} as well. This is so that the forms passed are exclusively new objects, and not older ones.
I've tried to do this..
- f.fields_for :referrals do |qf|
- if qf.object.new_record?
= render :partial => 'referral_fields', :locals => {:qf => qf}
Which makes it display correctly in the view, but the params are still populated with every single previously created nested object.
Which leads me to believe that I need to pass this option within the fields_for statement itself.
I have also tried this :
- f.fields_for #organization.referrals.select{|ref|ref.new_record?} do |qf|
= render :partial => 'referral_fields', :locals => {:qf => qf}
As well as this :
- f.fields_for :referrals, #organization.referrals.select{|ref|ref.new_record?} do |qf|
= render :partial => 'referral_fields', :locals => {:qf => qf}
The first example will show and only allows to pass one object. Where as my form is to allow a dynamic number of duplicate nested forms.
The second will display and pass all nested objects
App Info
#organization.rb
has_many :referrals
accepts_nested_attributes_for :referrals, :reject_if => proc { |attributes| attributes.all? { |k, v| v.blank? } }, :allow_destroy => true
#referral.rb
belongs_to :organization
#referrals_controller.rb
def new
2.times { #organization.referrals.build }
....
def create
#referral = Referral.new(params[:referral])
if #referral.valid? && #organization.referrals << #referral
flash[:notice] = "Referrals saved."
redirect_to new_organization_referrals_path(#organization)
else
render :action => :new, :layout => 'manage'
end
end
Here's what you want:
- f.fields_for :referrals, #organization.referrals.select{|ref|ref.new_record?} do |qf|
= render :partial => 'referral_fields', :locals => {:qf => qf}
The first parameter is the association name, which rails needs in order to know how to structure the params. If your first parameter is a collection, rails can usually infer the association name from that collection.
Your collection however, has been filtered into a regular array, where the association can't be as easily inferred. So you pass the specific collection as the second parameter.
Good luck!
UPDATE
I've built out a small rails app to analyze the problem, and the solution above is working just fine for me - the edit form doesn't display existing referrals, only new ones. I'll post the relevant code, so we can see where you and I might differ. One caveat, this is all in erb since I rarely work with haml and wouldn't want a typo to mess up the solution :)
My models:
# app/models/organization.rb
class Organization < ActiveRecord::Base
has_many :referrals
accepts_nested_attributes_for :referrals
end
# app/models/referral.rb
class Referral < ActiveRecord::Base
belongs_to :organization
end
My controller's edit action:
# app/controllers/organizations_controller.rb
class OrganizationsController < ApplicationController
def edit
#organization = Organization.find(params[:id])
2.times { #organization.referrals.build }
end
end
My views:
# app/views/organizations/edit.html.erb
<h1>Editing <%= #organization.name %></h1>
<% form_for(#organization) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<% f.fields_for :referrals, #organization.referrals.select{|ref| ref.new_record?} do |referral_fields| %>
<%= render :partial => 'referral', :locals => {:f => referral_fields} %>
<% end %>
<p>
<%= f.submit %>
</p>
<% end %>
# app/views/organizations/_referral.html.erb
<p>
<%= f.label :name, 'Referral Name' %><br />
<%= f.text_field :name %>
</p>
Of course, I just read your new comments, and maybe you don't need this anymore. Oh well, more documentation for posterity :)