Acessing and add records from other controller - ruby-on-rails

I have a model
class Rcomment < ActiveRecord::Base
attr_accessible :comment, :rating
belongs_to :recipe
belongs_to :user
end
I'm trying to add comment via the show view of recipe. I populated rcomment table with dummy data and it's showing fine via:
#recipe = Recipe.find(params[:id])
#comments = #recipe.rcomments
So I tried
#newcomments = #recipe.rcomments.build(params[:recipe])
But it doesn't work at all with an error:
undefined method `rcomments_path' for #<#:0x25ccd10>
How do I get it to display a usable form_for?
%= form_for(#newcomments) do |f| %>
<%= f.label :Comments %>
<%= f.text_field :comment%>
<%= f.label :ratings %>
<%= f.text_field :rating %>
<%= f.submit "Submit Comment", class: "btn btn-large btn-primary" %>
<% end %>

You've created a form for Rcomment creation, but you don't have an rcomments entry in your routes.rb. However, I think what best fits your problem is creating rcomments through a recipe. You can do this with accepts_nested_attributes_for and fields_for.
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
So, something like this--
In your Recipe model, add:
attr_accessible :rcomments_attributes
accepts_nested_attributes_for :rcomments
And in your recipes#show view:
<%= form_for(#recipe) do |f| %>
<% f.fields_for :rcomments do |cf| %>
<%= cf.label "Comments" %>
<%= cf.text_field :comment%>
<%= cf.label "Ratings" %>
<%= cf.text_field :rating %>
<% end %>
<%= f.submit "Submit Comment", class: "btn btn-large btn-primary" %>
<% end %>

Related

edit associated model by input form?

Order has_many jobs
Job belongs to order
And I want to edit attributes of #job.order:
<% order = #job.order %>
<%= simple_form_for [#job, order],
url: job_path(#job),
method: :put,
remote: true do |f| %>
<%= f.input :order_status, input_html: {class: 'form-control'} %>
(...)
<% end %>
any way to do it by just using input in simple form?
in job.rb
accepts_nested_attributes_for :order
in form.html.erb
simple_form_for #job do |f|
f.simple_fields_for #job.order do |order_form|
order_form.input :status
end
end
in jobs_controller.rb
params.require(:job).permit(:something, :something_else, :order_attributes => [:status])
You can use the excellent Cocoon gem https://github.com/nathanvda/cocoon to manage nested relationships, including the ability to easily add new nested relationships.
class Job < ActiveRecord::Base
has_many :orders
accepts_nested_attributes_for :orders, reject_if: :all_blank, allow_destroy: true
end
class Order < ActiveRecord::Base
belongs_to :job
end
Note the pluralization.
_form.html.erb*
<%= form_for #job do |f| %>
<%= f.label :job_name %>
<%= f.text_field :name %>
<div id='order'>
<%= f.fields_for :orders do |order| %>
<%= render 'order_fields', f: order %>
<% end %>
<div class='links'>
<%= link_to_add_association 'add order', f, :orders %>
</div>
<%= f.submit %>
<% end %>
_order_fields.html.erb partial
<div class='nested-fields'>
<%= f.label :order_name %>
<%= f.text_field :order_name %>
</div>
<%= link_to_remove_association "remove order", f %>

having issues converting slim to erb

I have this slim syntax:
= form_for(#influencer.relationships.build(followed_id: #influencer.id)) do |f|
div = f.hidden_field :followed_id
= f.submit "Follow", class: "btn btn-large btn-primary"
This is the erb i came up but it doesn't work.
<%= form_for(#influencer.relationships.build(followed_id: #influencer.id)) do |f| %>
<% f.hidden_field :followed_id %>
<%= f.submit "Follow" %>
<% end %>
<%= form_for #influencer.relationships.build(followed_id: #influencer.id) do |f| %>
<%= f.hidden_field :followed_id %>
<%= f.submit "Follow" %>
<% end %>
Conversely, it's bad practice to build an object out of the controller scope. #influencer.relationships.build(followed_id: #influencer.id) should be done inside the controller:
#app/models/influencer.rb
class Influencer < ActiveRecord::Base
has_many :relationships, foreign_key: :follower_id
end
#app/controllers/relationships_controller.rb
class RelationshipsController < ApplicationController
def new
#influencer = Influencer.find params[:influencer_id]
#relationship = #influencer.relationships.build #-> "followed_id" SHOULD be a foreign key in the model. If you have it in the model, you won't need to explicitly define it
end
end
Thus, you'll get:
<%= button_to "Follow", #relationship %>

Rails fields_for update not working (deleting the parent object)

I have fields_for form for update like below:
<%= form_for #cuisine, url: {action: "update" } do |f| %>
<%= f.text_area :name %>
<% #cuisine.ingredients.each do |ing| %>
<%= f.fields_for ing do |ingredient_fields|%>
<%= ingredient_fields.text_area :name, :value=> ing.name %>
<%= ingredient_fields.hidden_field :_destroy%>
<%= link_to_remove_fields 'Remove this ingredient', f %>
<% end %>
<% end %>
<% end %>
my cuisines_controller:
def update
#cuisine = Cuisine.find(params[:id])
if #cuisine.update_attributes(cuisine_params)
redirect_to root_path
else
redirect_to edit_cuisine_path
end
end
Though this shows the form correctly (showing forms filled with #cuisine and its ingredients' info), after reloading the page the #cuisine object gets deleted even when I don't push the submit button.
Any idea what's going on or how to update nested attributes using fields_for?
Thanks in advance.
First you should just use fields_for like this:
<%= f.fields_for :ingredients do |ingredient_fields|%>
<%= ingredient_fields.text_area :name %>
<%= ingredient_fields.hidden_field :_destroy %>
<%= link_to_remove_fields 'Remove this ingredient', f %>
<% end %>
Second you should first check to see if the cuisine_params in your controller permit those attributes:
params.require(:cuisine).permit(:name, ingredients_attributes:[:id, :name, :_destroy])
Lastly, make sure your model has this accepts_nested_attributes_for :ingredients, allow_destroy: true

undefined method `values_at' using nested_form gem

I am getting the error
ActionView::Template::Error (undefined method `values_at' for nil:NilClass):
when using nested_form gem
Here is my code
Models
class Poll < ActiveRecord::Base
attr_accessible :question, :poll_answers_attributes
has_many :poll_answers
accepts_nested_attributes_for :poll_answers
end
class PollAnswer < ActiveRecord::Base
belongs_to :poll
attr_accessible :answer
end
View
=nested_form_for [:admin, #poll], mutipart: true, class: "form-horizontal" do |f|
.span6
.control-group
=f.label :question, class: "control-label"
.controls
=f.text_field :question, rows: "5", class: "span5"
= f.link_to_add "Add a Answer", :poll_answers
=f.submit "Create Post", class: "btn btn-primary"
StackTrace
/home/abid/.bundler/ruby/1.9.1/nested_form-6232dd853c27/lib/nested_form/builder_mixin.rb:41:in `block in link_to_add'
/home/abid/.bundler/ruby/1.9.1/nested_form-6232dd853c27/lib/nested_form/view_helper.rb:53:in `call'
/home/abid/.bundler/ruby/1.9.1/nested_form-6232dd853c27/lib/nested_form/view_helper.rb:53:in `after_nested_form_callbacks'
/home/abid/.bundler/ruby/1.9.1/nested_form-6232dd853c27/lib/nested_form/view_helper.rb:8:in `block in nested_form_for'
Any Ideas ?
As mentioned in the documentation for the nested_form gem, you have to mention the field_for of the nested object before link_to_load button. I haven't use this gem previously but after going through the documentation, i am guessing this.
Here the form looks like
<%= nested_form_for [:admin, #poll], mutipart: true, class: "form-horizontal" do |f| %>
<%= f.text_field :question %>
<%= f.fields_for :poll_answers do |poll_ans_form| %>
<%= poll_ans_form.text_field :name %>
<%= poll_ans_form.link_to_remove "Remove this task" %>
<% end %>
<p><%= f.link_to_add "Add a Answer", :poll_answers %></p>
<% end %>
You should check out simple_form for doing this type of nested form. It makes it pretty easy. Based on your models you posted, something like this should work:
# controller
def new
#poll = Poll.new
end
# new.html.erb
<%= simple_form_for #poll do |f| %>
<%= f.simple_fields_for :poll_answer do |l| %>
<%= l.input :answer, autofocus: true %>
<%= l.submit "Add", class: 'small round button' %>
<% end %>
<% end %>
Then that post should get sent to the poll#create controller if you have the route open. From there, you can work your logic on it.
Hope that helps.

How to call a method on an object in a nested form in Ruby on Rails 3?

I have these two models
class Invoice < ActiveRecord::Base
has_many :items
accepts_nested_attributes_for :items
...
end
class Item < ActiveRecord::Base
belongs_to :invoice
def total
price * quantity
end
...
end
and this nested (!) form that posts to both models:
<h1>Add an Invoice</h1>
<%= form_for #invoice do |f| %>
<p>
<%= f.label :recipient %>
<%= f.text_field :recipient %> </p>
<p>
<%= f.label :date %>
<%= f.text_area :date %>
</p>
<h2>Items</h2>
<p>
<%= f.fields_for(:items) do |f| %>
<%= f.label :description %>
<%= f.text_field :description %>
<%= f.label :price %>
<%= f.text_field :price %>
<%= f.label :quantity %>
<%= f.text_field :quantity %>
<%= f.label :total %>
<%= f.total %><!-- this method call is not working! -->
<% end %>
</p>
<%= f.submit %>
<% end %>
How can I do calculations on my items within the form?
In my Items model I have this method:
def total
price * quantity
end
However, in the form I can't get it to work with f.total. I keep getting this error:
undefined method `total' for #<ActionView::Helpers::FormBuilder:0x10ec05558>
What am I missing here?
You are calling a method not on your model object, but on f, which is a form helper (ActionView::Helpers::FormBuilder). Error message gives a hint to this.
To call on the item, you need to replace
<%= f.total %>
with
<%= f.object.total %>

Resources