In my application Questionnaires its my controller in that one datatype is t.integer "Ques_id" its not able to acess in my index page.when i run the index page then i will get NoMethodError in Questionnaires#index error. How to solve this error?
table
class CreateQuestionnaires< ActiveRecord::Migration
def up
create_table :questionnaires do |t|
#t.column "id", :string, :limit => 25
t.integer "Ques_id"
t.string "Qname"
t.string "Header"
t.string "Description"
t.string "username"
end
end
def down
drop_table :questionnaires
end
end
controller
class QuestionnairesController < ApplicationController
# layout false
layout "admin"
def index
#questionnaires = Questionnaires.sorted()
end
def view
#questionnaires= Questionnaires.find(params[:id])
end
def new
#questionnaires= Questionnaires.new()
end
def create
# Instantiate a new object using form parameters
#questionnaires = Questionnaires.new(questionnaires_params)
# Save the object
if #questionnaires.save
# If save succeeds, redirect to the index action
flash[:notice] = "questions saved successfully."
redirect_to(:action => 'index')
else
# If save fails, redisplay the form so user can fix problems
render('new')
end
end
def edit
#questionnaires = Questionnaires.find(params[:id])
end
def update
# Find an existing object using form parameters
#questionnaires= Questionnaires.find(params[:id])
# Update the object
if #Questionnaires.update_attributes(questionnaires_params)
# If update succeeds, redirect to the index action
flash[:notice] = "questions updated successfully."
redirect_to(:action => 'view', :id => #questionnaires.id)
else
# If update fails, redisplay the form so user can fix problems
render('edit')
end
end
def delete
#Questionnaires= Questionnaires.find(params[:id])
end
def destroy
questionnaires = Questionnaires.find(params[:id]).destroy
flash[:notice] = "questions '#{Questionnaires.name}' destroyed successfully."
redirect_to(:action => 'index')
end
private
def questionnaires_params
# same as using "params[:subject]", except that it:
# - raises an error if :subject is not present
# - allows listed attributes to be mass-assigned
params.require(:questionnaires).permit(:Ques_id,:Qname, :Header, :Description, :visible)
end
end
index page here i got error
<% #page_title = "Questionnaires" %>
<div class="Questionnaires index"
<h2>Questionnaires </h2>
<%= link_to("Add New questions", {:action => 'new'}, :class => 'action new') %><br>
<div><%= pluralize(#questionnaires.size, 'questionnaires') %> found</div>
<th>Questionnaires</th>
<table class="listing" summary="Questionnaires list">
<tr class="Header">
<th>Ques_id</th>
<th>Qname</th>
<th>Header</th>
<th>Description</th>
<th>Actions</th>
</tr>
<% #questionnaires.each do |objQuestionaire| %>
<tr class="<%= cycle('odd', 'even') %>">
<td><%= objQuestionaire.Ques_id %></td>
<td><%= objQuestionaire.Qname %></td>
<td><%= objQuestionaire.Header %></td>
<td><%= objQuestionaire.Description %></td>
<!--td><%= objQuestionaire.username %></td-->
<td class="actions">
<%= link_to("view", {:action => 'view', :id => objQuestionaire.id}, :class => 'action view') %>
<!-- <%= link_to("view", '#', :class => 'action view') %>-->
<!-- <%= link_to("Edit", '#', :class => 'action edit') %>-->
<%= link_to("edit", {:action => 'view', :id => objQuestionaire.id}, :class => 'action edit') %>
</td>
<%end %>
##its my error page
Showing /home/cabox/workspace/app_1/app/views/questionnaires/index.html.erb where line #20 raised:
undefined method `Ques_id' for #<Questionnaires:0x007fcc490c88f8>
Extracted source (around line #20):
17
18
19
20
21
22
23
<% #questionnaires.each do |objQuestionaire| %>
<tr class="<%= cycle('odd', 'even') %>">
<td><%= objQuestionaire.Ques_id %></td>
<td><%= objQuestionaire.Qname %></td>
<td><%= objQuestionaire.Header %></td>
<td><%= objQuestionaire.Description %></td>
Rails.root: /home/cabox/workspace/app_1
Application Trace | Framework Trace | Full Trace
app/views/questionnaires/index.html.erb:20:in `block in _app_views_questionnaires_index_html_erb__3549852765576469128_70257686505360'
app/views/questionnaires/index.html.erb:17:in `_app_views_questionnaires_index_html_erb__3549852765576469128_70257686505360'
It is looking for a Ques_id column in your table(Questionnaires) which is not been migrated yet. So only it throws
`NoMethodError`
Please update your database by doing
rake db:migrate
which will migrate all the required fields defined in the migration file to your database so that it will not throw error.
Related
I have a view with a form and a table that displays some data from the database. Whenever I try to access the object from my controller in my view I get undefined method domain for "https://www.lookagain.co.uk/":String. But if do <%#savedHTML = ScrapedPage.all%> everything works fine. I know the I should not do that in the view as it defeats to purpose of MVC but I don't seem to fin a fix.
View:
<%= stylesheet_link_tag "masterstyles.css" %>
<% #url = 'default' %>
<%= form_for #url, :url => {:controller => "page_scraper", :action => "scrape"} do |f| %>
<%= f.text_field (:url) %>
<%= f.submit "Scrape" %>
<% end %>
<%#domain ='default'%>
<%#date ='default'%>
<%= form_for #domain, :url => {:controller => "page_scraper", :action => "compare"} do |f| %>
<%=select_tag 'domain', options_for_select(#savedHTML.collect{ |u| [u.domain, u.domain] })%>
<%=select_tag 'date', options_for_select(#savedHTML.collect{ |u| [u.created_at, u.created_at] })%>
<%= f.submit "compare" %>
<% end %>
<div class="subjects index">
<h2>FGH Page Scraper</h2>
<table class="listing" summary="Links list">
<tr class="header">
<th>ID</th>
<th>link</th>
<th>Created at</th>
<th>Updated at</th>
</tr>
<% #savedHTML.each do |page| %>
<tr>
<td><%= page.id %></td>
<td><%= page.domain %></td>
<td class="center"><%= page.created_at %></td>
<td class="center"><%= page.updated_at %></td>
<td class="actions">
<%= link_to("Delete", {:controller => 'page_scraper', :action => 'delete', :id => page.id}, :class => 'action delete') %>
</td>
</tr>
<% end %>
</table>
</div>
Controller:
class PageScraperController < ApplicationController
require 'nokogiri'
require 'open-uri'
require 'diffy'
require 'htmlentities'
def scrape
#url = watched_link_params[:url].to_s
puts "LOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOG#{#url}"
#page = Nokogiri::HTML(open(#url))
coder = HTMLEntities.new
#encodedHTML = coder.encode(#page)
create
end
def index
#savedHTML = ScrapedPage.distinct.pluck(:domain)
end
def show
#savedHTML = ScrapedPage.distinct.pluck(:domain)
end
def new
#savedHTML = ScrapedPage.new
end
def create
#savedHTML = ScrapedPage.create(domain: #url, html: #encodedHTML, css: '', javascript: '')
if #savedHTML.save
puts "ADDED TO THE DATABASE"
redirect_to(root_path)
else
puts "FAILED TO ADD TO THE DATABASE"
end
end
def edit
end
def upadate
end
def delete
#savedHTML = ScrapedPage.find(params[:id])
end
def destroy
#savedHTML = ScrapedPage.find(params[:id])
#savedHTML.destroy
redirect_to(root_path)
end
def compare
#domain = params[:domain].to_s
puts #domain
redirect_to(root_path)
#timestamp
end
def watched_link_params
params.require(:default).permit(:url)
end
def compare_params
params.require(:domain).permit(:domain)
end
end
The problem is that in your controller you are saving only string-values to #savedHTML variable (pluck will give you only an array of attributes from given objects). Therefore you cant ask "some_string".domain because String class doesn't have a domain method.
If you have a domain method on ScrapedPage object then in your controller action (index or show - whatever you are dealing with) you should replace
#savedHTML = ScrapedPage.distinct.pluck(:domain)
with
#savedHTML = ScrapedPage.select(:domain).distinct
The latter will give you unique ScrapedPage objects based on domain value. Look here for further info and examples.
NB! also a tip for refactoring:
Use strong parameters under private section. Also, if you have the same query in your controller twice in different actions then it is better to make it in before_action like this:
class PageScraperController < ApplicationController
before_action :set_saved_html, only: %i[index show]
def index
end
def show
end
private
def watched_link_params
params.require(:default).permit(:url)
end
def compare_params
params.require(:domain).permit(:domain)
end
def set_saved_html
#savedHTML = ScrapedPage.select(:domain).distinct
end
end
This is the error I'm getting:
No route matches [POST] "/specials/1"
I understand that it's not able to produce the post route, or it isn't available.
Here's my view/form code:
<%= form_for(:special, :url => {:action => 'update', :id => #special.id}) do |f| %>
<table class="table table-responsive table-striped table-condensed table-hover" summary="Special form fields">
<tr>
<th>Order</th>
<td><%= f.text_field :order, class: "form-control" %></td>
</tr>
<tr>
<th>Name</th>
<td><%= f.text_field :name, class: "form-control" %></td>
</tr>
<tr>
<th>Description</th>
<td><%= f.text_field :description, class: "form-control" %></td>
</tr>
<tr>
<th>Fine Print</th>
<td><%= f.text_field :fine_print, class: "form-control" %></td>
</tr>
<tr>
<th>Active</th>
<td><%= f.text_field :active, class: "form-control" %></td>
</tr>
</table>
<div class="form-buttons">
<%= submit_tag("Update Special") %>
</div>
<% end %>
Heres's my controller code:
class SpecialsController < ApplicationController
def index
#specials = Special.sorted
end
def show
#special = Special.find(params[:id])
end
def new
#special = Special.new
end
def create
#Instantiation of object using form parameters
#special = Special.new(special_params)
#Save the object
if #special.save
#If success, redirect to index action
redirect_to(:action => 'index')
else
# Redisplay the form so user can fix problems
render('new')
end
end
def edit
#special = Special.find(params[:id])
end
def update
#Find an existing object using form parameters
#special = Special.find(params[:id])
#Update the object
if #special.update_attributes(special_params)
#If succeeds, redirect to index action
redirect_to(:action => 'show', :id => #special.id)
else
# If update fails, redisplay the form so user can fix problems
render('edit')
end
end
def delete
end
private
def special_params
params.require(:special).permit(:name, :description, :fine_print, :active, :order)
end
end
I noticed that there is an update path:
PATCH /specials/:id(.:format) specials#update
I can't figure out why the post route isn't being applied. It's looking for the right #special instance, but it doesn't seem to have the route available. Any advice?
Usually when updating a record, we do a patch request to the route. Your form should look like this:
<%= form_for(#special) do |f| %>
Rails will determine the correct route is PATCH /specials/:id based on the fact that #special has been persisted to the database.
If you decide to use this same form as a partial in your new view, just make sure to add this to your controller:
def new
#special = Special.new
end
That way whether you are on the new route or the edit route, there will always be a #special object for form_for to infer whether to POST to /specials or PATCH /specials/:id
I'm trying to display only records created by the logged in user from the database, and don't know how to go about doing that. I get an error when I try to access the database and identify specific data to pull from it.
Hours Controller
class HoursController < ApplicationController
before_action :require_user
def new
#hour = HourLog.where(:user_id => current_user.id)
#entry = HourLog.all
end
def create
#hour = HourLog.new(hour_params)
#hour.User_id = current_user.id if current_user
#hour.status = 'Pending'
if #hour.save
redirect_to '/dashboard'
end
end
private
def hour_params
params.require(:hour_log).permit(:assignment, :hours, :supervisor, :date,)
end
end
Hours View (new.html.erb)(field to enter data into database)
<% #entry.each do |hour| %>
<tr>
<td><%= hour.assignment %></td>
<td><%= hour.hours %></td>
<td><%= hour.supervisor %></td>
<td><%= hour.date %></td>
<td><%= hour.status %></td>
</tr>
<% end.empty? %>
<%= form_for(#hour, url: hours_path) do |f|%>
<tr>
<td id="dashfield"><%=f.text_field :assignment, :placeholder=> "Assignment"%></td>
<td id="dashfiled"><%=f.text_field :hours, :placeholder => "Hours"%></td>
<td id="dashfield"><%=f.text_field :supervisor, :placeholder=> "Supervisor/Location"%></td>
<td id="dashfield"><%=f.date_field :date, :placeholder=> "Date"%></td>
<%=f.hidden_field :status, :value => "Pending" %>
<%=f.hidden_field :User_id, :value => current_user.id %>
<td id="dashbtn"><%=f.submit 'Create' %></td>
</tr>
<%end%>
Error:
Started GET "/dashboard" for 127.0.0.1 at 2015-08-10 17:29:08 -0500
Processing by HoursController#new as HTML
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 4]]
Completed 404 Not Found in 18ms
ActiveRecord::RecordNotFound (Couldn't find HourLog without an ID):
app/controllers/hours_controller.rb:4:in `new'
Thanks!
I think this function:
def new
#hour = HourLog.where(:user_id => current_user.id)
#entry = HourLog.all
end
should be changed to:
def new
#hour = current_user.hour_logs.new
#entry = current_user.hour_logs.all
end
Assuming the model user is configured with has_many :hour_logs.
as in your models, user have many hour_logs the table hour_logs must have a column user_id minding the capitalization
to change the column name from User_id to user_id you need to create a new migration.
in the command prompt navigate to the rails app folder and execute:
rails g migration fixcolumn1
this will generate a file in your-app-path/db/migrate called some-date_fixcolumn1.rb
edit this file so the following is present:
def change
rename_column :hour_logs, :User_id, :user_id
end
after that go back to the prompt and execute
rake db:migrate
It should work from there
Assuming User has_many hour_logs and HourLog belongs_to users ...
visit "/hours/new?user_id=123" to fill out your new hour_log form. Upon successful save user will be redirect to "/users/:user_id" page where they will see only records created by current logged in user ... which is what you asked for :) Hope this helps!
#config/routes.rb
Rails.application.routes.draw do
get '/hours/new', to: "hours#new"
post '/hours/create', to: "hours#create"
get '/users/:user_id', to: "users#index"
end
#controllers/users_controller.rb
class UsersController < ApplicationController
def index
#user_hours = User.find(params[:user_id]).hour_logs
end
end
#controllers/hours_controller.rb
class HoursController < ApplicationController
before_action :require_user
def new
#user_hours = User.find(params[:user_id]).hour_logs
end
def create
User.find(params[:user_id]).hour_logs.create!(
assignment: params[:assignment],
hours: params[:hours],
supervisor: params[:supervisor],
date: params[:date],
status: params[:status]
)
redirect_to "/users/#{params[:user_id]}"
end
end
#hours view
<% #user_hours.each do |hour| %>
<tr>
<td><%= hour.assignment %></td>
<td><%= hour.hours %></td>
<td><%= hour.supervisor %></td>
<td><%= hour.date %></td>
<td><%= hour.status %></td>
</tr>
<% end %>
<%= form_for "", url: {controller: 'hours', action: 'create'}, method: "post" do |f|%>
<tr>
<td id="dashfield"><%=f.text_field :assignment, :placeholder=> "Assignment"%></td>
<td id="dashfiled"><%=f.text_field :hours, :placeholder => "Hours"%></td>
<td id="dashfield"><%=f.text_field :supervisor, :placeholder=> "Supervisor/Location"%></td>
<td id="dashfield"><%=f.date_field :date, :placeholder=> "Date"%></td>
<%=f.hidden_field :status, :value => "Pending" %>
<%=f.hidden_field :user_id, :value => params[:user_id] %>
<td id="dashbtn"><%=f.submit 'Create' %></td>
</tr>
<%end%>
From show view: I'd like to pass the shown message's id to discard action and trash the message.
From index view: I'd like to pass the checked messages' ids to discard action and trash them all at once.
But I only can trash one record at once even if I check multiple and submit from index view.
How can I archive both 1 and 2 with the same action????
Routes
match 'messages/discard(/:id)' => 'messages#discard', :via => :post , :as => :discard_messages
index view
<%= form_tag(:action => discard, :via => 'post') do %>
<% #messages.each do |m| %>
<tr>
<td><%= check_box_tag "id",m.id %></td>
<td><%= m.last_message.id %></td>
<td><%= 'unread' if m.is_unread?(current_user) %></td>
<td><%= m.last_message.created_at.to_s(:jp) %></td>
<td><%= m.last_sender.username %></td>
<td><%= link_to m.subject, show_messages_path(:id => m, :breadcrumb => #box) %></td>
</tr>
<% end %>
<%= submit_tag "discard", :class => 'btn' %>
<% end %>
show view
<%= link_to 'Discard', discard_messages_path(#messages), :class => 'btn', :method => 'post' %>
controller
def discard
conversation = Conversation.find_all_by_id(params[:id])
if conversation
current_user.trash(conversation)
flash[:notice] = "Message sent to trash."
else
conversations = Conversation.find(params[:conversations])
conversations.each { |c| current_user.trash(c) }
flash[:notice] = "Messages sent to trash."
end
redirect_to :back
end
use the [] naming in your html, which rails will then make available as an array in the params
index.html.erb
<td><%= check_box_tag "message_id[]", m.id %></td>
controller
# ...
else
conversations = Conversation.where("id IN (?)", params[:message_id][])
# ...
to simplify things further I would remove the conditional in your action and create two separate actions
routes
resource :messages do
member do
post 'discard' # /messages/:id/discard
end
collection do
post 'discard_all' # /messages/discard_all?message_id[]=1&message_id[]=22
end
end
I just picked up Agile Web Development with Rails 3rd Ed., and I'm going thru the Depot Application chapters, I'm attempting to create a simple Edit quantity function, and delete function. I've had luck with the delete function but no luck with the edit quantity function.
I'm going to provide a lot of information, so please don't feel overwhelmed. I've found this to be a challenging problem.
To add_to_cart.html.erb
<div class="cart-title">Your cart</div>
<table>
<% for item in #cart.items %>
<tr>
<td><% form_for #cart.items, :url => {:action => "cart_update", :id => "#{item.getinventoryid}"} do |f| %>
<%= f.text_field :quantity, :size => '3' %>
<%= f.hidden_field :id, :value => "#{item.getinventoryid}" %>
<%= f.submit 'cart_update' %>
<% end %></td>
<td><%=h item.quantity %> ×</td>
<td><%=h item.title %></li></td>
<td><%=h item.description %></td>
<td class="item-price"><%= number_to_currency(item.price) %></td>
<td><%= link_to 'remove', {:controller => 'inventories', :action => 'remove_cart_item', :id => "#{item.getinventoryid}"} %></td>
</tr>
<% end %>
<tr class="total-line">
<td colspan="4">Total</td>
<td class="total-cell"><%= number_to_currency(#cart.total_price) %></td>
</tr>
</table>
<%= button_to "Checkout", :action => 'checkout' %>
<%= button_to 'Empty cart', :action => 'empty_cart' %>
inventories_controller:
def cart_update
#inventory = Inventory.find(params[:id])
#cart = find_cart
#cart.increment_inventory_quantity(params[:inventory])
end
def remove_cart_item
inventory = Inventory.find(params[:id])
#cart = find_cart
#cart.remove_inventory(inventory)
redirect_to_index("The item was removed")
end
Cart.rb model
attr_accessor :items
def increment_inventory_quantity(id, quantity)
inventory_to_increment = #items.select{|item| item.inventory == inventory}
# We do this because select will return an array
unless product_to_increment.empty?
inventory_to_increment = inventory_to_increment.first
else
# error handling here
end
inventory_to_increment.quantity = quantity
end
def remove_inventory(inventory)
#items.delete_if {|item| item.inventory == inventory }
end
cart_item.rb model
attr_accessor :inventory, :quantity
def getinventoryid
#inventory.id
end
This produces strange results:
Notice the quantity 16 appears in both items from my loop (#Fail). When I submit the form a ArgumentError in InventoriesController#cart_update wrong number of arguments (1 for 2) error is returned. Parameters being passed:
{"commit"=>"cart_update",
"_method"=>"put",
"authenticity_token"=>"sH1tWXTJPltpSq5XaAkww7259IR5ZiflnqSFB2Zb0IY=",
"id"=>"50",
"cart_item"=>{"quantity"=>"16",
"id"=>"50"}}
You are getting the wrong number of arguments error because you are passing one argument to #cart.increment_inventory_quantity in the controller method. That method requires two arguments.
# In your controller:
def cart_update
#inventory = Inventory.find(params[:id])
#cart = find_cart
#cart.increment_inventory_quantity(params[:inventory]) # you are passing one thing
end
# Then in your model:
def increment_inventory_quantity(id, quantity) # the method wants two things
# ...
Possibly you intended to do something like this:
def cart_update
#inventory = Inventory.find(params[:cart_item][:id])
#cart = find_cart
#cart.increment_inventory_quantity(#inventory.id, params[:cart_item][:quantity])
end
Are you sure it's form_for( #cart.items ) and not form_for( item )?