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.
Related
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.
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
I am trying to create a page within my application that shows all listings from a specific user. I am using Devise gem for my users. i do not need/want authentication, therefore the page should be open the the general public. I have already created a "Seller" page where a seller can manage their own listings. so how can I create a link on each listing on my homepage that connects the
<p><%= "Sold by #{listing.user.name}" %></p>
the new show page for that user? thanks!
my listings_controller:
class ListingsController < ApplicationController
before_action :set_listing, only: [:show, :edit, :update, :destroy]
before_filter :authenticate_user!, only: [:seller, :new, :create, :edit, :update, :destroy]
before_filter :check_user, only: [:edit, :update, :destroy]
def seller
#listings = Listing.where(user: current_user).order("created_at DESC")
end
# GET /listings
# GET /listings.json
def index
if params[:category].blank?
#listings = Listing.all.order("created_at DESC").paginate(:page => params[:page], :per_page => 16)
else
#category_id = Category.find_by(name: params[:category]).id
#listings = Listing.where(category_id: #category_id).order("created_at DESC").paginate(:page => params[:page], :per_page => 16)
end
end
# GET /listings/1
# GET /listings/1.json
def show
end
# GET /listings/new
def new
#listing = Listing.new
end
# GET /listings/1/edit
def edit
end
# POST /listings
# POST /listings.json
def create
#listing = Listing.new(listing_params)
#listing.user_id = current_user.id
if current_user.recipient.blank?
Stripe.api_key = ENV["STRIPE_API_KEY"]
token = params[:stripeToken]
recipient = Stripe::Recipient.create(
:name => current_user.name,
:type => "individual",
:bank_account => token
)
current_user.recipient = recipient.id
current_user.save
end
respond_to do |format|
if #listing.save
format.html { redirect_to #listing, notice: 'Listing was successfully created.' }
format.json { render :show, status: :created, location: #listing }
else
format.html { render :new }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /listings/1
# PATCH/PUT /listings/1.json
def update
respond_to do |format|
if #listing.update(listing_params)
format.html { redirect_to #listing, notice: 'Listing was successfully updated.' }
format.json { render :show, status: :ok, location: #listing }
else
format.html { render :edit }
format.json { render json: #listing.errors, status: :unprocessable_entity }
end
end
end
# DELETE /listings/1
# DELETE /listings/1.json
def destroy
#listing.destroy
respond_to do |format|
format.html { redirect_to listings_url, notice: 'Listing was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_listing
#listing = Listing.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def listing_params
params.require(:listing).permit(:name, :category_id, :description, :price, :image)
end
def check_user
if current_user != #listing.user
redirect_to root_url, alert: "Sorry, this listing belongs to someone else"
end
end
end
my current routes:
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
resources :categories
devise_for :users
resources :listings do
resources :orders, only: [:new, :create]
end
get 'pages/about'
get 'pages/contact'
get 'seller' => "listings#seller"
get 'sales' => "orders#sales"
get 'purchases' => "orders#purchases"
# or
root 'listings#index'
end
and finally, my listing model:
class Listing < ActiveRecord::Base
if Rails.env.development?
has_attached_file :image, :styles => { :medium => "200x", :thumb => "100x100>" }, :default_url => "404.jpg"
else
has_attached_file :image, :styles => { :medium => "200x", :thumb => "100x100>" }, :default_url => "404.jpg",
:storage => :dropbox,
:dropbox_credentials => Rails.root.join("config/dropbox.yml"),
:path => ":style/:id_:filename"
end
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
validates :name, :category_id, :description, :price, presence: true
validates :price, numericality: { greater_than: 0}
validates_attachment_presence :image
belongs_to :user
belongs_to :category
has_many :orders
end
my index page where I want to link to the seller specific page
<div class="center">
<div class="row">
<% #listings.each do |listing| %>
<div class="col-md-3">
<div class="thumbnail">
<%= link_to image_tag(listing.image.url), listing %>
<div class="caption">
<h3><%= listing.name %></h3>
<p><%= number_to_currency(listing.price) %></p>
<p><%= "Sold by #{listing.user.name}" %></p>
</div>
</div>
</div>
<% end %>
</div>
</div>
<br>
<div class="center">
<%= will_paginate #posts, renderer: BootstrapPagination::Rails %>
</div>
<% if user_signed_in? %>
<div class="right">
<%= link_to new_listing_path, class: "btn btn-primary", data: { no_turbolink: true } do %>
<i class="glyphicon glyphicon-plus"></i> New Listing
<% end %>
</div>
<% end %>
<br>
'User' is a model that you have created: devise only manages sessions, registrations, passwords, unlocks, and confirmations (the gem provides a controller for each one of these).
You should create your own UsersController, in which you can define the show action that you need. You should also declare a different path in your routes, or you'd have a conflict as '/users' is already used by devise. Something like
resources :users, only: [:show], path: 'sellers'
Then you can use
<p><%= "Sold by #{link_to listing.user.name, user_path(listing.user)}" %></p>
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|%>
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>