Error: Messages printout two time in view - ruby-on-rails-4

I've done a simple project about paper_trail, however I encountered a problem. When I created or updated completely there were two message show in the view:
Product was successfully created. undo
Product was successfully created. <a data-method="post" href="/versions/148/revert" rel="nofollow">undo</a>
here is my controller file:
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
# GET /products
# GET /products.json
def index
#products = Product.order(:name)
respond_to do |format|
format.html
format.csv { send_data #products.to_csv }
end
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. #{undo_link}" }
format.json { render action: 'show', 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_url, notice: 'Product was successfully updated.' "#{undo_link}" }
format.json { head :no_content }
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, notice: "Successfully destroyed product. #{undo_link}" }
format.json { head :no_content }
end
end
def import
Product.import(params[:file])
redirect_to root_url, notice: "Products imported."
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(:name, :price)
end
def undo_link
view_context.link_to("undo", revert_version_path(#product.versions.scoped.last), :method => :post)
end
end
and the layout file here:
<!DOCTYPE html>
<html>
<head>
<title>Store</title>
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
<%= csrf_meta_tags %>
</head>
<body>
<div id="container">
<% flash.each do |name, msg|%>
<%= content_tag :div, raw(msg), :id => "flash_#{name}" %>
<% end %>
<%= yield %>
</div>
</body>
</html>
I expect to show message once, however it show twice, so please tell me where my errors?

You are calling a flash message in both your create action and your view.
Create action:
format.html { redirect_to #product, notice: "Product was successfully created. #{undo_link}" }
View:
<% flash.each do |name, msg|%>
<%= content_tag :div, raw(msg), :id => "flash_#{name}" %>
<% end %>
The first gives:
Product was successfully created. undo
The latter show all raw output because of raw(msg):
Product was successfully created. <a data-method="post" href="/versions/148/revert" rel="nofollow">undo</a>

Related

undefined method '_path' with references

I'm looking for make draw lesson with a differente gallery link with each lessons for the users can uplaod there work in.
I have a controller, model and view named "lesson" and the linked gallery is "illst_repot"
I have linked the illust_repot with references.
lesson:references and user:references
I have no problem on the index page, but I have a problem on new page
undefined method `illust_reports_path'
localhost:3000/lessons/1/illust_reports/new
This is my routes
lesson_illust_reports GET /lessons/:lesson_id/illust_reports(.:format) illust_reports#index
POST /lessons/:lesson_id/illust_reports(.:format) illust_reports#create
new_lesson_illust_report GET /lessons/:lesson_id/illust_reports/new(.:format) illust_reports#new
edit_lesson_illust_report GET /lessons/:lesson_id/illust_reports/:id/edit(.:format) illust_reports#edit
lesson_illust_report GET /lessons/:lesson_id/illust_reports/:id(.:format) illust_reports#show
PATCH /lessons/:lesson_id/illust_reports/:id(.:format) illust_reports#update
PUT /lessons/:lesson_id/illust_reports/:id(.:format) illust_reports#update
DELETE /lessons/:lesson_id/illust_reports/:id(.:format) illust_reports#destroy
lessons GET /lessons(.:format) lessons#index
POST /lessons(.:format) lessons#create
new_lesson GET /lessons/new(.:format) lessons#new
edit_lesson GET /lessons/:id/edit(.:format) lessons#edit
lesson GET /lessons/:id(.:format) lessons#show
PATCH /lessons/:id(.:format) lessons#update
PUT /lessons/:id(.:format) lessons#update
DELETE /lessons/:id(.:format) lessons#destroy
routes.rb
resources :lessons do
resources :illust_reports
end
illust_reports_controller.rb
class IllustReportsController < ApplicationController
before_action :set_illust_report, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
before_action :illust_report_owner, only: [:edit, :update, :destroy]
# GET /illust_reports
# GET /illust_reports.json
def index
#illust_reports = IllustReport.all
end
def illust_report_owner
unless #illust_report.user_id == current_user.id
flash[:notice] = "Accès refusé car tu n'es pas l'auteur de ce billet."
redirect_to illust_reports_path
end
end
# GET /illust_reports/1
# GET /illust_reports/1.json
def show
end
# GET /illust_reports/new
def new
#illust_report = current_user.illust_reports.build
end
# GET /illust_reports/1/edit
def edit
end
# POST /illust_reports
# POST /illust_reports.json
def create
#illust_report = current_user.illust_reports.build(illust_report_params)
respond_to do |format|
if #illust_report.save
format.html { redirect_to #illust_report, notice: 'Illust report was successfully created.' }
format.json { render :show, status: :created, location: #illust_report }
else
format.html { render :new }
format.json { render json: #illust_report.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /illust_reports/1
# PATCH/PUT /illust_reports/1.json
def update
respond_to do |format|
if #illust_report.update(illust_report_params)
format.html { redirect_to #illust_report, notice: 'Illust report was successfully updated.' }
format.json { render :show, status: :ok, location: #illust_report }
else
format.html { render :edit }
format.json { render json: #illust_report.errors, status: :unprocessable_entity }
end
end
end
# DELETE /illust_reports/1
# DELETE /illust_reports/1.json
def destroy
#illust_report.destroy
respond_to do |format|
format.html { redirect_to illust_reports_url, notice: 'Illust report was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_illust_report
#illust_report = IllustReport.find_by(id: params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def illust_report_params
params.require(:illust_report).permit(:title, :image, :commentaire, :lesson_id, :user_id)
end
end
_form.html.erb
<%= form_for(#illust_report) do |f| %>
<% if #illust_report.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#illust_report.errors.count, "error") %> prohibited this illust_report from being saved:</h2>
<ul>
<% #illust_report.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
The model are linked.
I'm beginner with rails, I have searched a long time on google, and stack, and make many test before write this message.
Where is the problem ?
Thank you very much for your time.
undefined method `illust_reports_path'
You have nested resources. So the form_for should look like below
<%= form_for [#lesson, #illust_report] do |f| %>
and change the illust_reports_controller's new method like below
def new
#lesson = Lesson.find(params[:lesson_id])
#illust_report = current_user.illust_reports.build
end
Does lesson_illust_reports_path work?
As your illust_report resource is namespaced inside your lessons resource, you have to prepend lesson.

nested attributes not working in rails 4

So I have two models : Artist and Artwork.
Artist have a :name parrameter
Artist have_many artworks and Artwork has_one Artist.
I don't understand why when I call for #artworks.artiste.name in the artworks Index I have this error :
undefined method `artist'
this is my index :
<div class="col-xs-12 col-md-6 col-xs-offset-0 col-md-offset-4 col-lg-offset-5">
<p id="notice"><%= notice %></p>
<h1><%= #artworks.artist.name %></h1>
<% #artworks.each do |artwork| %>
<div class="artwork-container">
<div class="artwork-info">
<span><%= artwork.title %></span>
<p><%= artwork.description %></p>
<span><%= artwork.price %></span>
<span><%= link_to 'Edit', edit_artist_artwork_path(:artist, artwork) %></span>
<span><%= link_to 'Destroy', artist_artwork_path(:artist, artwork), method: :delete, data: { confirm: 'Are you sure?' } %>
</span>
</div>
<div class="artwork-photo-container">
<div class="artwork-photo" style="background-image: url('<%= artwork.photo.url %>');"></div>
</div>
</div>
<% end %>
<br>
<%= link_to 'New Artwork', new_artist_artwork_path %>
</div>
this is my artwork controller :
class ArtworksController < ApplicationController
before_action :set_artwork, only: [:show, :edit, :update, :destroy]
# GET /artworks
# GET /artworks.json
def index
#artworks = Artwork.all
end
# GET /artworks/1
# GET /artworks/1.json
def show
#artwork = Artwork.find(params[:id])
end
# GET /artworks/new
def new
#artwork = Artwork.new
end
# GET /artworks/1/edit
def edit
end
# POST /artworks
# POST /artworks.json
def create
#artwork = Artwork.new(artwork_params)
respond_to do |format|
if #artwork.save
format.html { redirect_to artist_artwork_url(:artist, #artwork), notice: 'Artwork was successfully created.' }
format.json { render :show, status: :created, location: artist_artwork_url(:artist, #artwork) }
else
format.html { render :new }
format.json { render json: #artwork.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /artworks/1
# PATCH/PUT /artworks/1.json
def update
respond_to do |format|
if #artwork.update(artworks_params)
format.html { redirect_to artist_artworks_url(:artist, #artworks), notice: 'Artwork was successfully updated.' }
format.json { render :show, status: :ok, location: artist_artwork_url(:artist, #artworks) }
else
format.html { render :edit }
format.json { render json: #artwork.errors, status: :unprocessable_entity }
end
end
end
# DELETE /artworks/1
# DELETE /artworks/1.json
def destroy
#artwork.destroy
respond_to do |format|
format.html { redirect_to artist_artworks_url(:artist, #artworks), notice: 'Artwork was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_artwork
#artwork = Artwork.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def artwork_params
params.require(:artwork).permit(:title, :description, :ref, :dateof, :price, :stock, :front, :photo, artist_attributes: [ :name, :surname])
end
end
those are my 2 models:
class Artist < ActiveRecord::Base
has_many :artworks
end
class Artwork < ActiveRecord::Base
has_one :artist
accepts_nested_attributes_for :artist
has_attached_file :photo, default_url: "/images/:style/missing.png"
validates_attachment_content_type :photo, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]
validates_attachment_presence :photo
validates_presence_of :title, :description, :stock, :front, :price
end
Change has_one :artist to belongs_to :artist. The reason is that has_one doesn't store an id, so the two models don't really have any association. belongs_to adds an artist_id field.
Ok so I solved the error by replacing <h1><%= #artworks.artist.name %></h1>
by <%= #artworks.first.artist %>
Thanks you

undefined method `current_user?' error

New to Rails and trying to figure out why I'm getting the above error message when I try to view my index properties page. I'm using Devise and CanCanCan. Code is below. Please let me know if something missing that would help identify problem.
View:
<% #properties.each do |property| %>
<div class = "row for-sale-header">
<div class="col-xs-8">
<% if user_signed_in? && current_user? %>
<%= link_to edit_property_path(property) do %>
<i class="glyphicon glyphicon-edit" aria-hidden="true"></i> Edit
<% end %><br />
<% end %>
<h5>Property ID: <%= property.id %> <br /> </h5>
<%= property.description %>
</div>
</div>
<br />
<% end %>
Controller:
class PropertiesController < ApplicationController
before_action :authenticate_user!, except: [:index]
before_action :set_user, only: [:show, :edit, :update]
def index
#properties = Property.all
end
def new
#property = current_user.properties.new
end
def create
#property = current_user.properties.new(property_params)
respond_to do |format|
if #property.save
format.html { redirect_to #property, notice: "Property was successfully created." }
format.json { render :show, location: #property }
else
format.html { render :new }
format.json
end
end
end
def update
respond_to do |format|
if #property.update(property_params)
format.html { redirect_to #property, notice: "You've successfully updated your property listing!" }
format.json { render :show, status: :ok, location: #property }
else
format.html { render :edit }
format.json { render json: #property.errors, status: :unprocessable_entity }
end
end
end
private
def property_params
params.require(:property).permit(:street, :city, :province, :postal_code, :description, :picture)
end
def set_user
#property = Property.find(params[:id])
end
end
Application Controller:
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if:
:devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << :name
end
end
I thought current_user could be used anywhere in the app based on Devise documentation on using it as a helper.
current_user can be used any where in the app. current_user? is not a method provided by Devise.

Rails 4 nested form not creating the objects which it accepts_nested_attributes_for

I'm trying to get categories and subcategories working. So far, I can create categories and add subcategories to them. When I submit the form, the subcategories_attributes send, but no Subcategory records are created. Please help, I'm pulling my hair out over here, and none of the tutorials seem to be helping.
category.rb
class Category < ActiveRecord::Base
has_many :subcategories, :dependent => :destroy
accepts_nested_attributes_for :subcategories, :reject_if => lambda {|a|
a[:content].blank?}
end
subcategory.rb
class Subcategory < ActiveRecord::Base
belongs_to :category
end
categories_controller.rb
class CategoriesController < ApplicationController
before_action :set_category, only: [:show, :edit, :update, :destroy]
def index
#categories = Category.all
end
def show
end
def new
#category = Category.new
#category.subcategories.build
end
def edit
end
def create
#category = Category.new(category_params)
respond_to do |format|
if #category.save
format.html { redirect_to #category, notice: 'Category was successfully
created.' }
format.json { render action: 'show', status: :created, location: #category }
else
format.html { render action: 'new' }
format.json { render json: #category.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #category.update(category_params)
format.html { redirect_to #category, notice: 'Category was successfully
updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #category.errors, status: :unprocessable_entity }
end
end
end
def destroy
#category.destroy
respond_to do |format|
format.html { redirect_to categories_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_category
#category = Category.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def category_params
params.require(:category).permit(:name, subcategories_attributes: [:id, :name,
:_destroy])
end
end
_form.html.erb
<%= nested_form_for(#category) do |f| %>
<% if #category.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#category.errors.count, "error") %> prohibited this category
from being saved:</h2>
<ul>
<% #category.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<%f.fields_for :subcategories do |builder|%>
<p>
<b>Subcategory</b>
<%=builder.text_field :name%>
<%=builder.link_to_remove "Remove"%>
<p>
<%end%>
<p>
<%=f.link_to_add "Add a Subcategory", :subcategories%>
</p>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Params Hash (on submit):
Parameters: {"utf8"=>"✓",
"authenticity_token"=>"19FxRnWF1F3BD4QZIkkce4arkOPt/BMkWFw6Z+vpV+8=", "category"=>
{"name"=>"Test", "subcategories_attributes"=>{"1398706662184"=>{"name"=>"TS1",
"_destroy"=>"false"}, "1398706664804"=>{"name"=>"TS2", "_destroy"=>"false"}}},
"commit"=>"Create Category"}
Thanks in advance!
subcategories_attributes are sent correctly within your params hash BUT content attribute is missing in them.
"subcategories_attributes"=>{"1398706662184"=>{"name"=>"TS1",
"_destroy"=>"false"}, "1398706664804"=>{"name"=>"TS2", "_destroy"=>"false"}}
Notice there is no content key passed.
So, all the subcategories records passed in subcategories_attributes are REJECTED due to the condition you specified in Category model:
accepts_nested_attributes_for :subcategories, :reject_if => lambda {|a|
a[:content].blank?}
Notice :reject_if => lambda {|a| a[:content].blank?} part above, this will reject all the records for which content is missing.
UPDATE
when I go to my edit action, the fields don't show up, despite being added to the database as intended (and showing up as such in other
forms).
Set a variable in edit and new actions as below:
def new
#category = Category.new
#subcategories = #category.subcategories.build ## Added
end
def edit
#subcategories = #category.subcategories ## Added
end
Update the fields_for in edit form as below:
<%= f.fields_for :subcategories, #subcategories do |builder|%>

undefined method `id' for nil:NilClass (NoMethodError)

I encountered this error today, I search google for solution but I cannot find the correct answer for this. The error:
NoMethodError at /master/hotels/import
undefined method `id' for nil:NilClass
This is the templete file:
row
.col-xs-12
%p.pull-left
%button.btn.btn-white.btn-sm
一括削除
%p.pull-right
= link_to "新規作成", url_for(action: :new), class: "btn btn-white btn-sm"
= link_to "CSV Export", url_for(action: :index, format: 'csv'), class: "btn btn-white btn-sm"
= link_to "CSV Upload", url_for(action: :import), class: "btn btn-white btn-sm"
-#= form_tag url_for(action: :import), class: 'pull-right' do |f|
-#= file_field_tag :csv, as: :file
-#= submit_tag "CSV Upload", input_html: {class: "btn btn-white btn-sm"}
.col-xs-12
= render 'cruds/grid'
and here is my controller file:
class CrudsController < ApplicationController
before_action :load_crud
before_action :set_crud, only: [:show, :edit, :update, :destroy]
def load_crud
end
# GET /cruds
# GET /cruds.json
def index
#items_grid = initialize_grid(#model)
#csv = CSV.generate() do |csv|
csv << #model.column_names
#model.all.each do |item|
csv << item.attributes.values_at(*#model.column_names).map{|i| i.to_s.encode("cp932", "UTF-8")}
end
end
respond_to do |format|
format.html { render template: 'cruds/index'}
format.csv { send_data #csv }
#format.xls # {send_data #product.to_csv (col_sep: "|t")}
end
# render template: 'cruds/index'
end
# GET /cruds/1
# GET /cruds/1.json
def show
render template: 'cruds/show'
end
# GET /cruds/new
def new
#crud = #model.new
render template: 'cruds/new'
end
# GET /cruds/1/edit
def edit
render template: 'cruds/edit'
end
# POST /cruds
# POST /cruds.json
def create
#crud = #model.new(crud_params)
respond_to do |format|
if #crud.save
format.html { redirect_to [:master, #crud], notice: 'Crud was successfully created.' }
format.json { render action: 'show', status: :created, location: #crud }
else
format.html { render action: 'new' }
format.json { render json: #crud.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /cruds/1
# PATCH/PUT /cruds/1.json
def update
respond_to do |format|
if #crud.update(crud_params)
format.html { redirect_to [:master, #crud], notice: 'Crud was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #crud.errors, status: :unprocessable_entity }
end
end
end
# DELETE /cruds/1
# DELETE /cruds/1.json
def destroy
#crud.destroy
respond_to do |format|
format.html { redirect_to action: :index }
format.json { head :no_content }
end
end
def import
#model.import(params[:file])
redirect_to root_url, notice: "Products imported."
end
private
# Use callbacks to share common setup or constraints between actions.
def set_crud
#crud = #model.find_by_id(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def crud_params
params[#hash].permit(#model.attribute_names)
end
end
I'm very confused about this error, can someone tell me any solution?
You're iterating over attribute names of #model, and reading them on #crud. #model has an attribute named id; #crud is nil. Either both should be same (probably), or in the somewhat unusual case that you do mean to read #model's attributes off of #crud, you need to check where #crud is assigned.
Your code is a bit confusing, some small comments:
model.find_by_id(params[:id])
Should be:
model.find(params[:id])
Next I would make sure that your view actually passes params[:id] to the view and not something like crud_id. If the latter is the case you should call this:
model.find_by(crud_id: params[:crud_id])
Lastly, I think you should add :file to your strong parameters.