Rails 4: comment partial not rendering - ruby

Trying to display comments for photo, photo belongs to profile. html does not render.
The pertinent code:
routes.rb
resources :profiles do
resources :photos do
resources :comments do
resources :comments
end
end
end
comments/_comment.html.haml
= comments.each do |comment|
%li
= comment.body
\-
%small Submitted
= #{time_ago_in_words(comment.created_at)}
= semantic_form_for [#profile, #photo, comment, Comment.new] do |f|
= f.inputs do
= f.input :body, placeholder: "Add a Reply"
%br/
= f.actions do
= f.action :submit, :as => :input, label: "Reply"
%ul
- render partial: 'comments/comment', locals: {comments: comment.comments}
models/photo.rb
class Photo < ActiveRecord::Base
belongs_to :profile
has_many :comments, as: :commentable, :dependent => :destroy
end
models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :profile
belongs_to :commentable, polymorphic: true
has_many :comments, as: :commentable, :dependent => :destroy
end
models/profile.rb
class Profile < ActiveRecord::Base
belongs_to :user
has_many :photos, :dependent => :destroy
has_many :comments, :dependent => :destroy
end
app/controllers/phtos_controller.rb
class PhotosController < ApplicationController
before_action :set_photo, only: [:show, :edit, :update, :destroy]
before_action :set_profile
load_and_authorize_resource
def index
#photos = Photo.where(:profile => #profile)
end
def show
end
def new
#photo = Photo.new(:profile => #profile)
end
def edit
end
def create
#photo = Photo.new(photo_params.merge(:profile_id => #profile.id))
respond_to do |format|
if #photo.save
format.html { redirect_to [#profile, #photo], notice: 'Photo was successfully created.' }
format.json { render :show, status: :created, location: #photo }
else
format.html { render :new }
format.json { render json: #photo.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #photo.update(photo_params)
format.html { redirect_to [#profile, #photo], notice: 'Photo was successfully updated.' }
format.json { render :show, status: :ok, location: #photo }
else
format.html { render :edit }
format.json { render json: #photo.errors, status: :unprocessable_entity }
end
end
end
def destroy
#photo.destroy
respond_to do |format|
format.html { redirect_to profile_photos_url, notice: 'Photo was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_photo
#photo = Photo.find(params[:id])
end
def set_profile
#profile = Profile.find(params[:profile_id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def photo_params
params.require(:photo).permit(:description, :attachment)
end
end
/app/views/photos/show.html.haml
= render partial: "layouts/sub_header", locals: {heading: #photo.profile.name + "'s", sub_heading: "photo", current_bread_crumb: #photo.profile.name + "'s photo", include_crumbs: true}
/ Intro Content
.row
.col-md-6
= image_tag #photo.attachment.url(:large), :class => "img-responsive"
.col-md-6
%p
%h2 About this photo...
= simple_format(#photo.description)
,
/ /.row
%h3 Comments
= semantic_form_for [#profile, #photo, Comment.new] do |f|
= f.inputs do
= f.input :body, :as => :text
= f.actions do
= f.action :submit, :as => :input
%ul
- render partial: 'comments/comment', locals: {comments: #photo.comments}
- if current_user == #profile.user
= link_to 'Edit', edit_profile_photo_path(#profile, #photo)
|
= link_to 'Back', :back
Data is being inserted into the database (except the profile_id, but I will save that for another post). I manually updated the profile_id in the db to make see if it was just a data integrity issue, still nothing.
I have tried moving the resources around in the routes.rb, I have tried refactoring the views to load the collection directly without the partial, nothing seems to work.
Additionally, if I comment out the partial and use this code I do see comment bodies on the page, so it is definitely something I am doing wrong in the call to the partial or inside the partial itself.
%ul
- #photo.comments.each do |comment|
= comment.body
I cannot seem to crack this one and I know it isn't magic, but I clearly not seeing something.
Thanks for any help!

Change show.html.haml to:
%ul
- render 'comments/comment', locals: {comments: #photo.comments}
Reason being, is that you can't render a view within a view, so the above will assume you are looking for a partial named _comment.html.haml within the comments folder.

Thanks Marc and Jarvis for all your help, I still don't know why that wasn't working, but looking at the ActionView::PartialRender at api.rubyonrails.org I found that this does work...
- #photo.comments.each do |comment|
= render partial: 'comments/comment', locals: { comment: comment }
I basically have to do the iterating myself even though clearly in the guide Marc referenced it said I should be able to do what I had written.
Oh well, on to the next problem.
Thanks again!

Related

rails 5 strong params updating record sets other columns to nil

For some reason, when I submit my form and update my user profile record, my user profile records have all the other columns updated to nil for some reason.
Lets say User.last.user_profile has an attribute "linkedin_url" and it is set to "www.yahoo.com". Once I submit the form, the User :phone number, and UserProfile :work_address, :work_zipcode gets updated, but the "linkedin_url" gets set to nil. IDK why!
class UserProfilesController < ApplicationController
def update
#user = User.last
if #user.update(user_profile_params)
respond_to do |format|
format.html {
redirect_to user_profile_path(#user)
}
format.json {
render :show, status: :ok, location: #preference
}
end
end
end
def user_profile_params
params.require(:user).permit( :phone_number, user_profile_attributes: [:work_address, :work_zipcode])
end
form
= form_for #user, url: user_profile_path(#user), method: :put do |f|
= f.fields_for :user_profile do |ff|
= ff.label :work_address
%br
= ff.text_field :work_address
%br
= ff.label :work_zipcode
%br
= ff.text_field :work_zipcode
%br
= f.label :phone_number
%br
= f.text_field :phone_number
%br
= f.submit "Submit", class: "btn"
def user_profile_params
params.require(:user).permit(
:phone_number,
user_profile_attributes: [:work_address, :work_zipcode] # ⇐ HERE
)
end
In the method above you should explicitly list :linkedin_url:
def user_profile_params
params.require(:user).permit(
:phone_number,
user_profile_attributes: [:work_address, :work_zipcode, :linkedin_url]
)
end
Just solved my own problem, it was because i didn't whitelist :id in the strong parameters.

Uploading image in paperclip lags my server for 3 minutes and then gives me error

This is my controller
class PinsController < ApplicationController
before_action :authenticate_user!, except: [:index]
before_action :set_pin, only: [:show, :edit, :update, :destroy]
# GET /pins
# GET /pins.json
def index
#pins = Pin.all
end
# GET /pins/1
# GET /pins/1.json
def show
end
# GET /pins/new
def new
#pin = current_user.pins.new
end
# GET /pins/1/edit
def edit
#pin = current_user.pins.find(params[:id])
end
# POST /pins
# POST /pins.json
def create
#pin = current_user.pins.new(pin_params)
respond_to do |format|
if #pin.save
format.html { redirect_to #pin, notice: 'Pin was successfully created.' }
format.json { render :show, status: :created, location: #pin }
else
format.html { render :new }
format.json { render json: #pin.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /pins/1
# PATCH/PUT /pins/1.json
def update
#pin = current_user.pins.find(params[:id])
respond_to do |format|
if #pin.update(pin_params)
format.html { redirect_to #pin, notice: 'Pin was successfully updated.' }
format.json { render :show, status: :ok, location: #pin }
else
format.html { render :edit }
format.json { render json: #pin.errors, status: :unprocessable_entity }
end
end
end
# DELETE /pins/1
# DELETE /pins/1.json
def destroy
#pin = current_user.pins.find(params[:id])
#pin.destroy
respond_to do |format|
format.html { redirect_to pins_url, notice: 'Pin was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_pin
#pin = Pin.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def pin_params
params.require(:pin).permit(:description, :image)
end
end
This is my model
class Pin < ActiveRecord::Base
attr_accessible :description, :image
has_attached_file :image, styles: { medium: "320x240>"}
validates :description, presence: true
validates :user_id, presence: true
validates_attachment :image, presence: true,
content_type: { content_type: ["image/jpeg", "image/jpg", "image/gif", "image/png"] },
size: { in: 0..5.megabytes }
belongs_to :user
end
When I try to upload an image, my server lags for 3 minutes, console goes crazy and after those 3 minutes I get this error message - "has contents that are not what they are reported to be".
I just changed the model to this
class Pin < ActiveRecord::Base
attr_accessible :description, :image
has_attached_file :image, styles: { medium: "320x240>"}
validates :description, presence: true
validates :user_id, presence: true
validates_attachment :image, presence: true,
# content_type: { content_type: ["image/jpeg", "image/jpg", "image/gif", "image/png"] },
size: { in: 0..5.megabytes }
validates_attachment_content_type :image, :content_type => /\Aimage/
belongs_to :user
end

Dynamic Dropdown SelectBox in Rails Issue

I'm working on a project in rails 4 where I am creating some dynamic drop downs. Below is all the code i have done for this dropdown. The drop downs are appearing, however not saving to the table and wont show up in the Show (and yes I have the proper ruby ie. <%= #reports.site_id %>.
I am not sure what to do from here and I am a bit of a rails noob, but have worked through tutorials and classes on the language.
My Form Select Box Looks Like this:
`<%= collection_select( :site, :site_id, Site.all, :id, :site_call_sign, {}, { :multiple => false %>`
The above select box dose get data from the site table but wont save that data to the reports table??`
My Controller looks like this:
class ReportsController < ApplicationController
before_action :set_report, only: [:show, :edit, :update, :destroy]
# GET /reports
# GET /reports.json
def index
#search = ReportDateSearch.new(params[:search])
#reports = #search.scope
#reports = Report.all
# Adds CSV Downloader to Residents
respond_to do |format|
format.html
format.csv { render text: #reports.to_csv }
end
end
# GET /reports/1
# GET /reports/1.json
def show
end
# GET /reports/new
def new
#report = Report.new
end
# GET /reports/1/edit
def edit
end
# POST /reports
# POST /reports.json
def create
#report = Report.new(report_params)
respond_to do |format|
if #report.save
format.html { redirect_to #report, notice: 'Report was successfully created.' }
format.json { render :show, status: :created, location: #report }
else
format.html { render :new }
format.json { render json: #report.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /reports/1
# PATCH/PUT /reports/1.json
def update
respond_to do |format|
if #report.update(report_params)
format.html { redirect_to #report, notice: 'Report was successfully updated.' }
format.json { render :show, status: :ok, location: #report }
else
format.html { render :edit }
format.json { render json: #report.errors, status: :unprocessable_entity }
end
end
end
# DELETE /reports/1
# DELETE /reports/1.json
def destroy
#report.destroy
respond_to do |format|
format.html { redirect_to reports_url, notice: 'Report was successfully destroyed.' }
format.json { head :no_content }
end
end
# Adds CSV Uploader Method to Application
def import
Report.import(params[:file])
redirect_to reports_path, notice: "Report(s) Added Successfully"
end
private
# Use callbacks to share common setup or constraints between actions.
def set_report
#report = Report.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def report_params
params.require(:report).permit(:date, :site_id, :user_id, :type_of_report, :type_of_incident, :report)
end
end
my model looks like this:
class Report < ActiveRecord::Base
belongs_to :user
belongs_to :site
def self.import(file)
CSV.foreach(file.path, headers: true) do |row|
Report.create! row.to_hash
end
end
def self.to_csv
CSV.generate do |csv|
csv << column_names
all.each do |report|
csv << report.attributes.values_at(*column_names)
end
end
end
end
My Show Page Looks Like:
<p id="notice"><%= notice %></p>
<p>
<strong>Date:</strong>
<%= #report.date %>
</p>
<p>
<strong>Site:</strong>
<%= #report.site_id %>
</p>
<p>
<strong>Created By:</strong>
<%= #report.user_id %>
</p>
<p>
<strong>Type of report:</strong>
<%= #report.type_of_report %>
</p>
<p>
<strong>Type of incident:</strong>
<%= #report.type_of_incident %>
</p>
<p>
<strong>Report:</strong>
<%= #report.report %>
</p>
<%= link_to 'Edit', edit_report_path(#report) %> |
<%= link_to 'Back', reports_path %>
not too sure where I'm going wrong here.Any help would be greatly appreciated
Try changing the first parameter if your collection_select call from :site to :report:
<%= collection_select( :report, :site_id, Site.all, :id, :site_call_sign, {}, { :multiple => false } %>
My initial guess is that your form is passing up site_id as params[:site_id] instead of params[:report][:site_id], which is the format you'd need based on your strong parameters method in your controller:
def report_params
params.require(:report).permit(:date, :site_id, :user_id, :type_of_report, :type_of_incident, :report)
end
If it doesn't work, one thing you can do to help debug the issue is look at your rails console and see exactly the format that your form parameters are being sent from your view to the controller. Putting a couple puts statements in your action can help you better compare params versus report_params:
def create
puts "Params: #{params.inspect}"
puts "Report Params: #{report_params.inspect}"
#report = Report.new(report_params)
respond_to do |format|
if #report.save
format.html { redirect_to #report, notice: 'Report was successfully created.' }
format.json { render :show, status: :created, location: #report }
else
format.html { render :new }
format.json { render json: #report.errors, status: :unprocessable_entity }
end
end
end
Look in your server console for the output of those 2 puts statements. If you see site_id in params and not in report_params, you'll know your strong parameters method has filtered it out.

Undefined method on staging environment, works fine locally

Having some issues with my staging environment at the moment. I have my app on Heroku (both staging and production). It works perfectly on local, but when I push it to the staging environment I keep getting an undefined method for category_id.
I have reset the databases, run my migrations and put the seeds in to no avail. The only thing I can think is there is something wrong with my product model but I haven't changed that part of the app since I last pushed it to production (works fine with the current version on there).
Is there any chance that one of my migrations is not going through? That's the only thing I can think of.
Product model:
class Product < ActiveRecord::Base
belongs_to :subcategory
mount_uploader :product_image, ProductImageUploader
validates :title, :description, presence: true
validates :title, uniqueness: true
validates :image_url, allow_blank: true, format: { with: %r{\.(gif|jpg|png)\Z}i, message: 'must be a URL for GIF, JPG or PNG image.'}
validates :subcategory_id, presence: true
end
Products Controller:
class ProductsController < ApplicationController
skip_before_filter :authorize, only: [:show, :index]
before_action :set_product, only: [:show, :edit, :update, :destroy]
# GET /products
# GET /products.json
def index
#products = Product.order("title ASC")
#categories = Category.all
#subcategories = Subcategory.order("title ASC")
end
# GET /products/1
# GET /products/1.json
def show
end
# GET /products/new
def new
#product = Product.new
end
# GET /products/1/edit
def edit
end
# POST /products
# POST /products.json
def create
#product = Product.new(product_params)
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: 'Product was successfully created.' }
format.json { render json: #product, status: :created, location: #product }
else
format.html { render action: 'new' }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /products/1
# PATCH/PUT /products/1.json
def update
respond_to do |format|
if #product.update(product_params)
format.html { redirect_to #product, notice: 'Product was successfully updated.' }
format.json { head :ok }
else
format.html { render action: 'edit' }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.json
def destroy
#product.destroy
respond_to do |format|
format.html { redirect_to products_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
#product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:title, :description, :image_url, :product_image, :subcategory_id, :category_id)
end
end
The view that is causing the error message:
=form_for(#product) do |f|
-if #product.errors.any?
#error_explanation
%h2
=pluralize(#product.errors.count, "error")
prohibited this product from being saved:
%ul
-#product.errors.full_messages.each do |msg|
%li
=msg
%br
.field
=f.label :title
%br
=f.text_field :title, size: 100
%br
.field
=f.label :description
%br
=f.text_area :description, cols: 100, rows: 10
%br
.field
=f.label :product_image
=f.file_field :product_image
.field
=f.label :category_id
%br
=f.collection_select(:category_id, Category.all, :id, :title)
%br
.field
=f.label :subcategory_id
%br
// =f.collection_select(:subcategory_id, Subcategory.all, :id, :title)
%select{:id => "product_subcategory_id", :name => "product[subcategory_id]", :disabled => "disabled"}
%option
Select a category first...
%br
.actions
%br
=f.submit
%br
%br
:javascript
$(document).ready(function(){
$("select#product_category_id").change(function(e) {
var val = $(this).val();
var subCatSelect = $("select#product_subcategory_id");
subCatSelect.empty();
subCatSelect.append("<option>Loading...</option>");
$.get("/subcategories.json?category="+val)
.done(function(response) {
subCatSelect.empty();
if (response.length > 0) {
$.each(response, function(k,v) {
subCatSelect.append("<option id='"+v.id+"'>"+v.title+"</option>");
subCatSelect.removeAttr("disabled");
});
} else {
subCatSelect.attr("disabled", "disabled");
subCatSelect.append("<option>No Subcategories</option>");
}
});
});
});
And the error message:
ActionView::Template::Error (undefined method `category_id' for #<Product:0x007f64ab47c1d0>):
30: .field
31: =f.label :category_id
32: %br
33: =f.collection_select(:category_id, Category.all, :id, :title)
app/views/products/_form.html.haml:33:in `block in _app_views_products__form_html_haml__3508934121535598535_70035173692040'
app/views/products/_form.html.haml:1:in `_app_views_products__form_html_haml__3508934121535598535_70035173692040'
app/views/products/new.html.haml:7:in `_app_views_products_new_html_haml__3953831312052620477_70035173605140'
It may be an issue with the naming conventions in your asset pipeline.
Try precompiling your asset pipeline befor pushing to Heroku:
bundle exec rake assets:precompile RAILS_ENV=production
git commit -a -m "Prempile assets for release"
git push
git push heroku master
Here's some more info from Heroku on this:
https://devcenter.heroku.com/articles/rails-asset-pipeline
Not sure if this will fix it, but it's very easy to try it. I've found that this fixes most of problems moving from development/test to production.
Hope this helps!
I'm not too sure what happened but when I cleared the heroku DB, re-ran my migrations and seeds it decided to work.... I have no idea what happened.

Rails 4 function in controller not running

I have some code for a Rails 4 project I'm working on. It uses active_record (mysql2), and there is a has_many :through relationship that works properly when I interact through rails c (in either production or development). When I try to submit the relationship in a form (I am using simple_form), I can't seem to get it to save.
Here is how my information is currently set up (just showing snippets, I can't really show the whole source):
Model:
has_many :categorizations
has_many :resource_categories, through: :categorizations
accepts_nested_attributes_for :resource_categories
accepts_nested_attributes_for :categorizations
Form:
= simple_form_for #resource do |f|
= f.association :resource_categories
Controller:
# POST /resources
# POST /resources.json
def create
#resource = Resource.new(resource_params)
set_categories(#resource, params[:resource][:resource_category_ids])
respond_to do |format|
if #resource.save
format.html {
redirect_to #resource, notice: 'Resource was successfully created.'
}
format.json {
render action: 'show', status: :created, location: #resource
}
else
format.html {
render action: 'new'
}
format.json {
render json: #resource.errors, status: :unprocessable_entity
}
end
end
end
# PATCH/PUT /resources/1
# PATCH/PUT /resources/1.json
def update
respond_to do |format|
if #resource.update(resource_params)
set_categories(#resource, params[:resource][:resource_category_ids])
format.html {
redirect_to #resource, notice: 'Resource was successfully updated.'
}
format.json {
head :no_content
}
else
format.html {
render action: 'edit'
}
format.json {
render json: #resource.errors, status: :unprocessable_entity
}
end
end
end
# Never trust parameters from the scary internet, only allow the white list
# through.
def resource_params
params.require(:resource).permit(
:title, :slug, :ancestry, :status, :author_id, :published, :parent_id,
:resource_category_ids, :preview, :body
)
end
def set_categories(resource, categories)
# Clean out the existing categories (if there are any)
unless resource.resource_categories.blank?
resource.resource_categories.each do |category|
resource.resource_categories.delete(category)
end
end
unless categories.blank?
categories.each do |category|
unless category.blank?
resource.resource_categories << ResourceCategory.find(category)
end
end
end
end
When I issue the following commands using rails c -e production (or just plain rails c) it works (In this example, I assign all categories to all resources):
Resource.all.each do |resource|
ResourceCategory.all.each do |category|
resource.resource_categories << category
end
end
It seems like my problem is that the controller is not calling the helper function
Use this instead:
def create
#resource = Resource.new(resource_params)
#resource.set_categories(params[:resource][:resource_category_ids])
..
end
Move the method in the Resource model:
def set_categories(categories)
# Clean out the existing categories (if there are any)
unless new_record?
unless resource_categories.blank?
resource_categories.each do |category|
resource_categories.delete(category)
end
end
end
unless categories.blank?
categories.each do |category|
unless category.blank?
resource_categories << ResourceCategory.find(category)
end
end
end
end
#resource is instance variable of your Controller, you don't need to pass it to a method. Perform all your operations directly on the instance variable.
OP still had problem while saving the record, changed :resource_category_ids to :resource_category_ids => [] in resource_params method:
def resource_params
params.require(:resource).permit(
:title, :slug, :ancestry, :status, :author_id, :published, :parent_id,
:preview, :body, :resource_category_ids => []
)
end

Resources