rails: "unknown action" message when action is clearly specified - ruby-on-rails

I had hard time to figure out why I've been getting "unknown action" error message when I was do some editing:
Unknown action
No action responded to 11. Actions: bin, create, destroy, edit, index, new, observe_new, show, tag, update, and vote
you can see that Rails did mention each action in the above list - update. And in my form, I did specify action = "update".
I wonder if some friends could kindly help me with the missing links...
here is the code:
edit.rhtml
<h1>Editing tip</h1>
<% form_tag :action => 'update', :id => #tip do %>
<%= render :partial => 'form' %>
<p>
<%= submit_tag_or_cancel 'Save Changes' %>
</p>
<% end %>
_form.rhtml
<%= error_messages_for :tip %>
<p><label>Title<br/>
<%= text_field :tip, :title %></label></p>
<p><label>Categories<br/>
<%= select_tag('categories[]', options_for_select(Category.find(:all).collect {|c| [c.name, c.id] }, #tip.category_ids), :multiple => true ) %></label></p>
<p><label>Abstract:<br/>
<%= text_field_with_auto_complete :tip, :abstract %></label></p>
<p><label>Name: <br/>
<%= text_field :tip, :name %></label></p>
<p><label>Link: <br/>
<%= text_field :tip, :link %></label></p>
<p><label>Content<br/>
<%= text_area :tip, :content, :rows => 5 %></label></p>
<p><label>Tags <span>(space separated)</span><br/>
<%= text_field_tag 'tags', #tip.tag_list, :size => 40 %></label></p>
class TipsController < ApplicationController
before_filter :authenticate, :except => %w(index show)
# GET /tips
# GET /tips.xml
def index
#tips = Tip.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #tips }
end
end
# GET /tips/1
# GET /tips/1.xml
def show
#tip = Tip.find_by_permalink(params[:permalink])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #tip }
end
end
# GET /tips/new
# GET /tips/new.xml
def new
#tip = session[:tip_draft] || current_user.tips.build
end
def create
#tip = current_user.tips.build(params[:tip])
#tipMail=params[:email]
#if tipMail
# TipMailer.deliver_email_friend(params[:email], params[:name], tip)
# flash[:notice] = 'Your friend has been notified about this tip'
#end
#tip = current_user.tips.build(params[:tip])
#tip.categories << Category.find(params[:categories]) unless params[:categories].blank?
#tip.tag_with(params[:tags]) if params[:tags]
if #tip.save
flash[:notice] = 'Tip was successfully created.'
session[:tip_draft] = nil
redirect_to :action => 'index'
else
render :action => 'new'
end
end
def edit
#tip = Tip.find(params[:id])
end
def update
#tip = Tip.find(params[:id])
respond_to do |format|
if #tip.update_attributes(params[:tip])
flash[:notice] = 'Tip was successfully updated.'
format.html { redirect_to(#tip) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #tip.errors, :status => :unprocessable_entity }
end
end
end
def destroy
#tip = Tip.find(params[:id])
#tip.destroy
respond_to do |format|
format.html { redirect_to(tips_url) }
format.xml { head :ok }
end
end
def observe_new
session[:tip_draft] = current_user.tips.build(params[:tip])
render :nothing => true
end
end

the quick answer is that form_tag doesn't support :action as an option, you want to be passing a string as a path in. A slightly longer answer is you shouldn't be using form_tag anyways for a model edit form, you should be using form_for.
what rails are you using? .rhtml is pretty old, rails generators should be giving you .html.erb files. if it is something even remotely recent, you should be able to use
<% form_for #tip do |f| %>
<%= f.label :title, 'Title' %><br />
<%= f.text_field %>
... etc
<% end %>

Related

Cannot access model method inside its controller in Rails

In my Rails app, I have a controller tickets_controller.rb and model ticket.rb. For creating a ticket I have the following form,
<%= form_for(#ticket) do |f| %>
<% if #ticket.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#ticket.errors.count, "error") %> prohibited this ticket from being saved:</h2>
<ul>
<% #ticket.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.label :ref_no, "Reference Number"%><br/>
<%= f.text_field :ref_no%><br />
<%= f.label :category, "Type of Request"%><br/>
<%= f.text_field :category_id %><br />
<%= f.label :issue, "Issue"%><br/>
<%= f.text_area :issue%><br />
<%= f.label :ticket_priority, "Priority level"%><br/>
<%= f.text_field :ticket_priority_id %><br />
<%= f.label :ticket_status, "Current Status"%><br/>
<%= f.text_field :ticket_status_id %><br />
<%= f.label :project, "Project"%><br/>
<%= f.text_field :project_id %><br />
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I want to create a unique random reference number on the form_load (ticket/new), and it should be appended to Reference Number text field. While creating a new reference number, it should check the tickets table for duplication. So I have the following model,
ticket.rb
class Ticket < ActiveRecord::Base
attr_accessible :issue, :ticket_status_id, :ticket_priority_id, :ref_no, :category_id, :project_id
has_many :ticket_statuses , :through => :ticket_histories
has_one :ticket_priority
belongs_to :user
before_create :generate_token
protected
def generate_num
self.token = loop do
random_token = random(1000000000)
break random_token unless Ticket.exists?(:ref_no => random_token)
end
end
end
and
tickets_controller.rb
class TicketsController < ApplicationController
before_filter :authenticate_user!
#load_and_authorize_resource
def index
#tickets = Ticket.all
respond_to do |format|
format.html # index.html.erb
format.json { render :json => #tickets }
end
end
def show
#ticket = Ticket.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #ticket }
end
end
def new
#ticket = Ticket.new
#ref_no = Ticket.generate_num
#categories = Category.all
#status = TicketStatus.first
#priorities = TicketPriority.all
respond_to do |format|
format.html # new.html.erb
format.json { render :json => #ticket }
end
end
def edit
#ticket = Ticket.find(params[:id])
end
def create
#ticket = Ticket.new(params[:ticket])
respond_to do |format|
if #ticket.save
format.html { redirect_to #ticket, :notice => 'Ticket was successfully created.' }
format.json { render :json => #ticket, :status => :created, :location => #ticket }
else
format.html { render :action => "new" }
format.json { render :json => #ticket.errors, :status => :unprocessable_entity }
end
end
end
def update
#ticket = Ticket.find(params[:id])
respond_to do |format|
if #ticket.update_attributes(params[:ticket])
format.html { redirect_to #ticket, :notice => 'Ticket was successfully updated.' }
format.json { head :no_content }
else
format.html { render :action => "edit" }
format.json { render :json => #ticket.errors, :status => :unprocessable_entity }
end
end
end
def destroy
#ticket = Ticket.find(params[:id])
#ticket.destroy
respond_to do |format|
format.html { redirect_to tickets_url }
format.json { head :no_content }
end
end
end
When I run my app, I am getting the following error. Can anyone help?
NoMethodError in TicketsController#new
undefined method `generate_num' for #<Class:0x7f5cdc1f21c0>
Rails.root: /home/local/Rajesh/ticket_system
Application Trace | Framework Trace | Full Trace
app/controllers/tickets_controller.rb:27:in `new'
Change your model method generate_num to self.generate_num.
def self.generate_num
token = loop do
random_token = random(1000000000)
break random_token unless Ticket.exists?(:ref_no => random_token)
end
end
You have defined and instance method and you are calling it using Class
Call method using object
#ticket.generate_num

undefined method `model_name' for NilClass:Class. The action 'create' could not be found for

When I go to http://localhost:3000/register_entries/new, I am getting this error: undefined method `model_name' for NilClass:Class
Below is my _checkoutform.html.erb. If I add this line <% #register_entry = RegisterEntry.new %> to the beginning of the controller then the form comes up but when I submit I get the following error The action 'create' could not be found for RegisterEntriesController:
<%= form_for (#register_entry) do |f| %>
<% if #register_entry.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#register_entry.errors.count, "error") %> prohibited this register from being saved:</h2>
<ul>
<% #register_entry.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :publisher %>
<%= f.collection_select :publisher_id, Publisher.order(:name), :id, :name %>
</div>
<div class="field">
<%= f.label :territory %>
<%= f.collection_select :territory_id, Territory.order(:last_worked), :id, :number %>
</div>
<div class="field">
<%= f.label "Checkout Date" %>
<%= f.date_select :checkout %>
</div>
<!-- <div class="field">
<%= f.label :checkin %><br />
<%= f.date_select :checkin %>
</div> -->
<!-- <div class="field">
<%= f.label :notes %><br />
<%= f.text_field :notes %>
</div> -->
<div class="actions">
<%= f.submit "Checkout Territory" %>
</div>
<% end %>
Here is my register_entries_controller.rb:
class RegisterEntriesController < ApplicationController
# GET /RegisterEntries
# GET /RegisterEntries.json
before_filter :authenticate_user!
helper_method :sort_column, :sort_direction
private
def sort_column
#register_entry.column_names.include?(params[:sort]) ? params[:sort] : "checkout"
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "desc"
end
def index
authorize! :index, #user, :message => 'Not authorized'
#register_entries = RegisterEntry.order(sort_column + ' ' + sort_direction) #pluralized #register_entry
respond_to do |format|
format.html # index.html.erb
format.json { render json: #register_entries }
end
end
# GET /RegisterEntries/1
# GET /RegisterEntries/1.json
def show
#register_entry = RegisterEntry.find(params[:id])
#publishers = Publisher.all
respond_to do |format|
format.html # show.html.erb
format.json { render json: #register_entry }
end
end
# GET /RegisterEntries/new
# GET /RegisterEntries/new.json
def new
#register_entry = RegisterEntry.new
authorize! :index, #user, :message => 'Not authorized'
respond_to do |format|
format.html # new.html.erb
format.json { render json: #register_entry }
end
end
# GET /RegisterEntries/1/edit
def edit
authorize! :index, #user, :message => 'Not authorized'
#register_entry = RegisterEntry.find(params[:id])
end
# POST /RegisterEntries
# POST /RegisterEntries.json
def create
authorize! :index, #user, :message => 'Not authorized'
#register_entry = RegisterEntry.new(params[:register_entry])
respond_to do |format|
if #register_entry.save
format.html { redirect_to #register_entry, notice: 'Register Entry was successfully created.' }
format.json { render json: #register_entry, status: :created, location: #register_entry }
else
format.html { render action: "new" }
format.json { render json: #register_entry.errors, status: :unprocessable_entity }
end
end
end
# PUT /RegisterEntries/1
# PUT /RegisterEntries/1.json
def update
authorize! :index, #user, :message => 'Not authorized'
#register_entry = RegisterEntry.find(params[:id])
respond_to do |format|
if #register_entry.update_attributes(params[:register_entry])
format.html { redirect_to #register_entry, notice: 'Register Entry was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #register_entry.errors, status: :unprocessable_entity }
end
end
end
# DELETE /RegisterEntries/1
# DELETE /RegisterEntries/1.json
def destroy
authorize! :index, #user, :message => 'Not authorized'
#register_entry = RegisterEntry.find(params[:id])
#register_entry.destroy
respond_to do |format|
format.html { redirect_to register_entries_url }
format.json { head :no_content }
end
end
end
Been fighting with this for a few hours. Any ideas?
You are making all of your controller action methods private which means they can't be called as actions. See the end of the Methods and Actions section of the ActionController Rails Guide.

Rails: ActiveRecord::RecordNotFound in AlbumsController#create Couldn't find User without an ID

Hi I'm currently receiving an error in my controller on submitting a form for creating an album. This is my first project and I am pretty shaky on controllers and what params to put and what to set the instance variables as... please help!!
on submission of my new.html.erb form, I receive
ActiveRecord::RecordNotFound in AlbumsController#create
Couldn't find User without an ID
here is my albums_controller
class AlbumsController < ApplicationController
def index
#albums = Albums.all
respond_to do |format|
format.html
format.json { render json: #albums }
end
end
def show
#albums = Album.all
#album = Album.find(params[:id])
#photo = Photo.new
end
def update
end
def edit
end
def create
#user = User.find(params[:user_id])
#user.album = Album.new(params[:album])
respond_to do |format|
if #user.album.save
format.html { redirect_to #user, notice: 'Album was successfully created.' }
format.json { render json: #album, status: :created, location: #album}
else
format.html { render action: "new" }
format.json { render json: #album.errors, status: :unprocessable_entity }
end
end
end
def new
#user = User.find(params[:user_id])
#album = Album.new
end
def destroy
end
end
here is the form I'm submitting
<%= form_for (#album), :html => { :id => "uploadform", :multipart => true } do |f| %>
<div>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :description %>
<%= f.text_area :description %>
<br>
<%=f.submit %>
Let me know if you need any more files.
In your createmethod you're trying to fetch a user from the database, based on params[:user_id], and params doesn't contain any user_id.
In this case I believe that it should come from the URL
So one solution if an album belongs to the user would be to set your routes like that :
resources :users do
resources :albums
end
Then you'll have to tell your form that the album is nested under a user byt explicitly giving the url. user_albums_path matches /users/:user_id/albums(.:format)
<%= form_for (#album), url: user_albums_path :html => { :id => "uploadform", :multipart => true } do |f| %>
<div>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.label :description %>
<%= f.text_area :description %>
<br>
<%=f.submit %>
The your create method you receive the user_id it need in the params.
Let me know if'm not clear enough or if you need more explanations
You should use the build method defined here
#user = User.find(params[:user_id])
#user.album = Album.new(params[:album])
to create the album, you should
#user = User.find(params[:user_id])
#user.albums.build params[:album])
this will automatically set the user_id attribute of the album to #user.id, you won't have anything to do
so your create method should be
def create
#user = User.find(params[:user_id])
#album = #user.albums.build params[:album]
respond_to do |format|
if #album.save
format.html { redirect_to user_path(#user), notice: 'Album was successfully created.' }
format.json { render json: #album, status: :created, location: #album} # I don't know what this location is
else
format.html { render action: "new" }
format.json { render json: #album.errors, status: :unprocessable_entity }
end
end
end

undefined method `first_name'

Can anyone shed light on this for me?
undefined method `first_name' for #
Here is the show.html
<p id="notice"><%= notice %></p>
<div id="container">
<p>
<b>First name:</b>
<%= #artist.firstname %>
</p>
<p>
<b>Second name:</b>
<%= #artist.surname %>
</p>
<p>
<b>About:</b>
<%= #artist.about %>
</p>
<div id="comments">
<h2>Comments</h2>
<%= render :partial => "shared/comment", :collection => #artist.comments%>
</div
</div>
<%= render :partial => "image", :collection => #artist.images %>
<%= link_to 'Edit', edit_artist_path(#artist) %> |
<%= link_to 'Back', artists_path %>
<%= link_to 'show', images_path %>
Here is the partial
<div class="comment">
<p>
<span class="commentator"><%= comment.commentator.display_name %>
say's</span>
<%= comment.comment %>
</p>
</div
Here is the friend view
class Friends < ActiveRecord::Base
attr_accessible :firstname, :surname
has_many :comments, :as => :commentator, :class_name =>"Commentable"
def display_name
"#{self.firstname} #{self.surname}"
end
end
This is the friends controller
class FriendsController < ApplicationController
# GET /friends
# GET /friends.xml
def index
#friends = Friend.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #friends }
end
end
# GET /friends/1
# GET /friends/1.xml
def show
#friend = Friend.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #friend }
end
end
# GET /friends/new
# GET /friends/new.xml
def new
#friend = Friend.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #friend }
end
end
# GET /friends/1/edit
def edit
#friend = Friend.find(params[:id])
end
# POST /friends
# POST /friends.xml
def create
#friend = Friend.new(params[:friend])
respond_to do |format|
if #friend.save
format.html { redirect_to(#friend, :notice => 'Friend was successfully created.') }
format.xml { render :xml => #friend, :status => :created, :location => #friend }
else
format.html { render :action => "new" }
format.xml { render :xml => #friend.errors, :status => :unprocessable_entity }
end
end
end
# PUT /friends/1
# PUT /friends/1.xml
def update
#friend = Friend.find(params[:id])
respond_to do |format|
if #friend.update_attributes(params[:friend])
format.html { redirect_to(#friend, :notice => 'Friend was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #friend.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /friends/1
# DELETE /friends/1.xml
def destroy
#friend = Friend.find(params[:id])
#friend.destroy
respond_to do |format|
format.html { redirect_to(friends_url) }
format.xml { head :ok }
end
end
end
I am trying to make it so a friend can leave a comment on an artists page but I keep getting the above error.
I am very new to Ruby so I apologise if I have left anything out.
Basically, rails will look at the database to figure out what fields are on a model. So make sure your migrations have been run, and that first_name exists on the db table.
Also, Friends is plural. In rails, your table is plural (friends), your model is singular (Friend), and your controller is plural (FriendsController). It is best not to go against this convention. Try renaming the model and see what happens
This error related to database that first_name don't exist in your db.Run migration carefully.
You need line 2 of the Friend class to be attr_accessible :firstname, :surname so your views have access to the those variables.

Confused as to which Prototype helper to use (updated)

This is a continuation of Confused as to which Prototype helper to use. My code has been updated to reflect other user's suggestions:
(model) message.rb:
class Message < ActiveRecord::Base
after_create :destroy_old_messages
def old_messages
messages = Message.all(:order => 'updated_at DESC')
if messages.size >= 24
return messages[24..-1]
else
return []
end
end
protected # works without protected
def destroy_old_messages
messages = Message.all(:order => 'updated_at DESC')
messages[24..-1].each {|p| p.destroy } if messages.size >= 24
end
end
(view) index.html.erb:
<div id="messages">
<%= render :partial => #messages %>
</div>
<%= render :partial => "message_form" %>
(view) _message.html.erb:
<% div_for message do %>
<%= h message.created_at.strftime("%X") %> - <%= h message.author %><%= h message.message %>
<% end %>
(view) _message_form.html.erb:
<% remote_form_for :message, :url => { :action => "create" }, :html => { :id => 'message_form'} do |f| %>
<%= f.text_area :message, :size => "44x3" %><br />
<%= submit_to_remote 'submit_btn', 'submit', :url => { :action => 'create' } %><br />
<% end %>
(view) create.rjs:
page.insert_html :top, :messages, :partial => #message
page[#message].visual_effect :grow
page[:message_form].reset
flash[:notice]
flash.discard
# #old_messages.each do |m|
# page.remove(m.id)
# end
(controller) messages_controller.rb:
class MessagesController < ApplicationController
def index
#messages = Message.all(:order => "created_at DESC")
respond_to do |format|
format.html
format.js
end
end
def new
#message = Message.new
respond_to do |format|
format.html
end
end
def create
#message = Message.new(params[:message])
# #old_messages = Message.old_messages
respond_to do |format|
if #message.save
flash[:notice] = 'message created.'
format.html { redirect_to(messages_url) }
format.js
else
format.html { render :action => "new" }
end
end
end
def update
#message = Message.find(params[:id])
respond_to do |format|
if #message.update_attributes(params[:message])
flash[:notice] = 'message updated.'
format.html { redirect_to(messages_url) }
format.js
else
format.html { render :action => "edit" }
end
end
end
def destroy
#message = Message.find(params[:id])
#message.destroy
respond_to do |format|
format.html { redirect_to(messages_url) }
format.js
end
end
end
With the exception of the old_messages method in the model, all of the commented code were recommended changes from the previous post to make this work. But as soon as I uncomment the last three lines from create.rjs and #old_messages = Message.old_messages from the controller, I can't even submit messages with the message_form partial. Can anyone see what's wrong here? I'm just trying to create a basic app to help further my understanding of rails and rjs. I would greatly appreciate any suggestions or corrections you have to share, thank you for reading my post.
it's not what you're asking for, but i have a suggestion...
to get the older messages you can use named_scope.
in your case, (if i understood what you want) i think it would be something like:
# model
named_scope :limit, lambda { |num| { :limit => num } }
named_scope :order, lambda { |ord| { :order => ord } }
and
#controller
Message.order("updated_at DESC").limit(24)
the problem is that old_messages is an instance method, and you're calling from a class.
if you do
def self.old_messages
# ...
end
it's now a class method.
this blog has a good explanation about class and instance methods.

Resources