I'm working on a very simple CRUD Asset Management app and I want to use Ransack. I think I have this setup properly in my view and controller but each time the index view is hit I get the exception:
undefined methodassets_path' for #<#:0x007fa5f353e9e0>`
Here is my view:
index.html.erb
<div class="pull-right">
<%= search_form_for #q do |f| %>
<%= f.search_field :asset_name_cont, placeholder: 'Search...' %>
<% end %>
<table class="table table-striped">
<thead>
<tr>
<th>Asset Number</th>
<th>Asset Name</th>
<th>Serial Number</th>
<th>Model</th>
<th>Manufacturer</th>
<th>Asset Type</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% #assets.each do |a| %>
<tr>
<td><%= a.asset_number %></td>
<td><%= a.asset_name %></td>
<td><%= a.asset_serial %></td>
<td><%= a.asset_model %></td>
<td><%= a.asset_manuf %></td>
<td><%= a.asset_type.try(:name) %></td>
<td><%= link_to 'View', inventory_path(a), :class => 'btn btn-mini btn-info' %> <%= link_to 'Edit', edit_inventory_path(a), :class => 'btn btn-mini btn-warning' %></td>
</tr>
</tbody>
<% end %>
<%= will_paginate #assets %>
Here is my controller excerpt:
inventory_controller.rb
def index
#q = Asset.ransack(params[:q])
#assets = #q.result.order("asset_number ASC").paginate(:page => params[:page], :per_page => 10)
end
And here is my model (with annotation of the fields)
asset.rb
id :integer not null, primary key
asset_number :string
asset_shortname :string
asset_name :string
asset_desc :text
asset_serial :string
asset_model :string
asset_manuf :string
asset_type_id :integer
created_at :datetime not null
updated_at :datetime not null
asset_location :string
class Asset < ActiveRecord::Base
extend FriendlyId
friendly_id :asset_name, use: :slugged
validates :asset_name, :asset_serial, :asset_type_id, :asset_model, :asset_manuf, :presence => true
belongs_to :asset_type
end
I think I have the controller wired up fine, I was having issues before with forms and routes by having a controller called assets which is an issue as a reserved name in Rails 4.x.x so I rebuilt the controller as inventory and call the Asset class from within.
My question is, I the search_form_for field to look at the Asset model's field for asset_name but when I write the view as I've laid out I constantly get that path error.
Is there a way to pass a different path into the Ransack search_field method so that I can get past what seems to be an issue with conventions?
If you need more information or if my question is not clear enough, please do not hesitate to edit or ask for more information. Thanks all!
Ok, I figured this out. Similar to issues I was seeing with breaking Rails naming conventions in my other forms, I had to pass the url and method in the search_form_for helper method. It's working!
Here's my view for the search now:
<%= search_form_for(#q, url: "/inventory", method: :get) do |f| %>
<%= f.search_field :asset_name_cont, placeholder: 'Search...' %>
<% end %>
Related
I am new to rails and wants to do following tasks with my uploader-
1) view the uploaded excel sheets in rails in editable mode
2)save that edited sheet in database(sqlite3).
I am seriously not getting what to do with this "view method"(in controller) to get my solution that's why leaving view method empty.
Also, please explain what is "resume.attachment_url" doing in
<%= link_to "Download Resume", resume.attachment_url %> in index.html.erb .
Thanks,
Aarzoo Goyal
routes.rb
Rails.application.routes.draw do
resources :resumes, only: [:index, :new, :create, :destroy]
root "resumes#index"
get 'resumes/index'
get 'resumes/new'
get 'resumes/create'
get 'resumes/destroy'
Model-Resume.rb
class Resume < ActiveRecord::Base
mount_uploader :attachment, AttachmentUploader # Tells rails to use this uploader for this model.
validates :name, presence: true # Make sure the owner's name is present.
validates :attachment, presence: true
end
resume_controller.rb
class ResumesController < ApplicationController
def index
#resumes = Resume.all
end
def new
#resume = Resume.new
end
def create
#resume = Resume.new(resume_params)
if #resume.save
redirect_to resumes_path, notice: "The resume #{#resume.name} has been uploaded."
else
render "new"
end
end
def view
end
def destroy
#resume = Resume.find(params[:id])
#resume.destroy
redirect_to resumes_path, notice: "The resume #{#resume.name} has been deleted."
end
private
def resume_params
params.require(:resume).permit(:name, :attachment)
end
end
new.html.erb
<% if !#resume.errors.empty? %>
<div class = "alert alert-error">
<ul>
<% #resume.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class = "well">
<%= form_for #resume, html: { multipart: true } do |f| %>
<%= f.label :name %>
<%= f.text_field :name %><br />
<%= f.label :attachment %>
<%= f.file_field :attachment %><br />
<%= f.submit "Save", class: "btn btn-primary" %>
<% end %>
</div>
index.html.erb
<% if !flash[:notice].blank?%>
<div class="alert alert-info">
<%= flash[:notice]%>
</div>
<%end%>
<br />
<%= link_to "New File", new_resume_path, class: "btn btn-primary"%>
<br />
<br />
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Name</th>
<th>Download Link</th>
<th>View</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
<% #resumes.each do|resume| %>
<tr>
<td><%= resume.name%></td>
<td><%= link_to "Download Resume", resume.attachment_url %></td>
<td><%= link_to "View "%></td>
<td><%= button_to "Delete", resume, method: :delete, class: "btn btn-danger", confirm: "Are you sure to delete #{resume.name}?" %></td>
</tr>
<% end %>
</tbody>
</table>
First post here... doing the ROR tutorial and found similar questions regarding this issue... but of course none worked. Anyway following the tutorial everything works except when clicking on this link I get the error The action 'edit1' could not be found for SubjectsController... any help is greatly appreciated!Myself and the tutorial are both using same version too... 4.0.
SubjectsController:
class SubjectsController < ApplicationController
layout false
def index
#subjects = Subject.sorted
end
def show
#subject = Subject.find(params[:id])
end
def new
#subject = Subject.new({:name => "Default"})
end
def create
# Instantiate a new object using form parameters
#subject = Subject.new(subject_params)
# Save the object
if #subject.save
# If save succeeds, redirect to the index action
redirect_to(:action => 'index')
else
# If save fails, redisplay the form so user can fix problems
render('new')
end
end
def edit
#subject = Subject.find(params[:id])
end
def update
# Find an existing object using form parameters
#subject = Subject.find(params[:id])
# Update the object
if #subject.update_attributes(subject_params)
# If update succeeds, redirect to the index action
redirect_to(:action => 'show', :id => #subject.id)
else
# If update fails, redisplay the form so user can fix problems
render('edit')
end
end
def delete
#subject = Subject.find(params[:id])
end
def destroy
subject = Subject.find(params[:id]).destroy
redirect_to(:action => 'index')
end
private
def subject_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(:subject).permit(:name, :position, :visible)
end
end
Edit.html
<%= link_to("<< Back to List", {:action => 'index'}, :class => 'back-link') %>
<div class="subjects edit">
<h2>Update Subject</h2>
<%= form_for(:subject, :url => {:action => 'update', :id => #subject.id}) do |f| %>
<table summary="Subject form fields">
<tr>
<th>Name</th>
<td><%= f.text_field(:name) %></td>
</tr>
<tr>
<th>Position</th>
<td><%= f.text_field(:position) %></td>
</tr>
<tr>
<th>Visible</th>
<td><%= f.text_field(:visible) %></td>
</tr>
</table>
<div class="form-buttons">
<%= submit_tag("Update Subject") %>
</div>
<% end %>
</div>
routes file
SimpleCms::Application.routes.draw do
root "demo#index"
#get "demo/index"
match ':controller(/:action(:id))', :via => [:get, :post]
Other than this I'm on Chrome and windows 7.
Code for Show link:
<%= link_to("<< Back to List", {:action => 'index'}, :class => 'back-link') %>
<div class="subjects show">
<h2>Show Subject</h2>
<table summary="Subject detail view">
<tr>
<th>Name</th>
<td><%= #subject.name %></td>
</tr>
<tr>
<th>Position</th>
<td><%= #subject.position %></td>
</tr>
<tr>
<th>Visible?</th>
<td><%= #subject.visible ? 'true' : 'false' %></td>
</tr>
<tr>
<th>Created</th>
<td><%= #subject.created_at %></td>
</tr>
<tr>
<th>Updated</th>
<td><%= #subject.updated_at %></td>
</tr>
</table>
</div>
Code for delete link:
<%= link_to("<< Back to List", {:action => 'index'}, :class => 'back-link') %>
<div class="subjects delete">
<h2>Delete Subject</h2>
<%= form_for(:subject, :url => {:action => 'destroy', :id => #subject.id}) do |f| %>
<p>Are you sure you want to permanently delete this subject?</p>
<p class="reference-name"><%= #subject.name %></p>
<div class="form-buttons">
<%= submit_tag("Delete Subject") %>
</div>
<% end %>
</div>
Your controller contains edit action, but not edit1. edit1 is a result of action being concatenated with parameter due to invalid route setup.
In your routes config a slash / is missing
It should be like this
match ':controller(/:action(/:id))', :via => [:get, :post]
^
|
Adding a slash to the 'match' route as Mladen suggests will fix your immediate problem. However, having that default route is no longer recommended; it's better to be explicit about your routes.
This will give you the 'standard' REST-ful routes, to replace the 'match' route in your routes file:
resources :subjects
If you're really using a 'GET delete' action in your controller you would need a 'member' entry to add that, but usually there's just a link on the show and/or edit form that goes right to the 'destroy' action to delete a record; not sure why you would need a separate 'delete' view.
I'm trying to add a column to a table that displays all the products in my active record that will allow me to remove a product for a given row. When I try to run the code I get an error that matched the title.
Products Controller
def destroy
#product = Product.find(params[:id])
#product.destroy
redirect_to :back
end
private
def product_params
params.require(:product).permit(:ta_code, :tatr, :oem, :name, :kind, :ta_type, :id)
end
Delete Button section of code
<% Product.all.each do |product| %>
<% if product.kind == "oem" %>
<tr data-toggle="collapse" data-target="#all<%= product.tatr %>" class="accordion-toggle">
<% if can? :destroy, Product %>
<td><%= button_to "delete", delete_path(#product), :method => :delete %></td>
<% end %>
<td><%= product.id %></td>
<td><%= product.tatr %></td>
<td><%= product.name %></td>
<td><%= product.oem %></td>
<td><%= product.created_at.strftime("%b/%d/%y") %></td>
</tr>
<% end %>
Routes.rb
get 'signup' => 'users#new'
root 'static#home'
get 'systems' => 'static#pages'
get 'help' => 'static#help'
get 'ce' => 'static#ce'
get 'oem' => 'static#oem'
get 'update_existing' => 'static#update_existing'
get 'reports' => 'static#reports'
get 'miscellaneous' => 'static#miscellaneous'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
get 'create_new' => 'products#new'
delete 'delete'=> 'products#destroy'
get 'new_status' => 'microposts#new'
get 'list' => 'users#list'
resources :users
resources :products
resources :microposts
This is my first real project so I'm sure the convention is a little off and organization may be lacking, but that comes with time. I appreciate any help.
You're passing an object instead of it's id here:
<% if can? :destroy, Product %>
<td><%= button_to "delete", delete_path(:id => product), :method => :delete %></td>
<% end %>
It should be delete_path(product) or delete_path(id: product.id)
Replace
delete_path(#product)
with
delete_path(product)
I wanted to set up a form where I can edit some nested objects and create new objects at the same time.
Thats what I got until now:
Models:
class Rate < ActiveRecord::Base
belongs_to :org_unit
validates_uniqueness_of :name
validates_presence_of :name, :tablename, :rate_order_no, :ratevalue
end
class OrgUnit < ActiveRecord::Base
has_many :rates
accepts_nested_attributes_for :rates
end
Controller:
class OrgUnitsController < ApplicationController
before_action :set_org_unit, only: [:show, :edit]
def index
#org_units = OrgUnit.all
end
def show
end
def edit
end
def update
if #org_unit.update(org_unit_params)
redirect_to #org_unit, notice: 'Update successfull.'
else
render action: 'edit'
end
end
private
def set_org_unit
#org_unit = OrgUnit.find(params[:id])
#rates = #org_unit.rates
end
def org_unit_params
params.require(:org_unit).permit(
:rates_attributes => [:name, :tablename, :rate_order_no, :ratevalue]
)
end
end
Routes:
#Organisation Units
get '/org_units/', :to => 'org_units#index', :as => 'org_units'
get '/org_units/:id', :to => 'org_units#show', :as => 'org_unit'
get '/org_units/:id/edit', :to => 'org_units#edit', :as => 'edit_org_unit'
put '/org_units/:id', :to => 'org_units#update'
patch '/org_units/:id', :to => 'org_units#update'
View:
<%= simple_nested_form_for #org_unit do |f| %>
<table id="ratetable" class="display">
<thead>
<tr> <th>Rate Name</th> <th>Table</th> <th>Department</th> <th>Value</th> </tr>
</thead>
<tbody>
<%= f.simple_fields_for :rates, :wrapper => false do |ff| %>
<tr class="fields">
<td><%= ff.input :name, label: false, required: true %></td>
<td><%= ff.input :tablename, collection: ["Costs","Savings","CnQ"], label:false, required: true, prompt: "Select the table" %></td>
<td><%= ff.input :rate_order_no, collection: 1..19, label:false, required: true, prompt: "Select the row"%></td>
<td><%= ff.input :ratevalue, label: false, required: true %></td>
</tr>
<% end %>
</tbody>
</table>
<p><%= f.link_to_add "Add a rate", :rates, :data => { :target => "#ratetable" }, :class => "btn btn-default" %></p>
<br>
<br>
<%= f.submit "Save Rates", :class => "btn bnt-default" %>
<% end %>
Now if I click the submit button rails is taking every filled line and create a new rate with the attributes of org_unit_params. So the old rates are not updated and multiple times in my database then.
What I want is that he updates the old ones if they changed and create new records for the others.
It should have something to do with create_or_update but I cant put it together.
Would appreciate every hint.
Thanks in advance and best regards.
Okay I had to add :id to my permitted attributes:
def org_unit_params
params.require(:org_unit).permit(:id, :name,
rates_attributes: [:id, :name, :tablename, :rate_order_no, :ratevalue, :org_unit_id, :_destroy]
)
end
But that wasnt enough :( So I had to add a hidden input field with :id in my fields_for and now it works:
<%= f.simple_fields_for :rates, :wrapper => false do |ff| %>
<tr class="fields">
<td><%= ff.input :name, label: false %></td>
<td><%= ff.input :tablename, collection: ["Costs","Savings","CnQ"], label:false, prompt: "Select the table" %></td>
<td><%= ff.input :rate_order_no, collection: 1..19, label:false, prompt: "Select the row"%></td>
<td><%= ff.input :ratevalue, label: false, required: true %></td>
<td><%= ff.link_to_remove "Remove", :class => "btn btn-default" %></td>
<%= ff.input :id, :as => :hidden %>
</tr>
<% end %>
I want to update a model on my db. if an user checked the checkbox, it must not be appear again on the view.
I have some view like this:
<%= form_tag( riepilogo_path, method: "post", id: "sel") do %>
<%= hidden_field_tag "sala", params[:sala] %>
<%= hidden_field_tag "spectacle_id", params[:spectacle_id] %>
<%= hidden_field_tag "num", params[:num] %>
<table>
<tr>
<th></th>
<th>Numero</th>
</tr>
<% for posti in #postis %>
<tr>
<td><%= check_box_tag "posti_ids[]", posti.id %></td>
<td><%=h posti.numero %></td>
</tr>
<% end %>
</table>
<%= submit_tag "OK", id: "sub"%>
<% end %>
controller of Postis is something like so:
class PostisController < ApplicationController
def index
#postis = Posti.where(:stato => "unchecked" , :spectacle_id => params[:spectacle_id] , :hall_num => params[:sala])
end
def posti_multiple
#postis = Posti.find(params[:posti_ids])
end
end
In the Posti's model i have attributes: spectacle_id, hall_num, seat(integer) and stato (:default => "unchecked").
When he submit, seats be load in posti_ids[]. I want to update stato of seats which are present in posti_ids from "unchecked" to "checked".
As per your comment,you have tried to perform update_column on an Array.So is the error
undefined method `update_column' for # Array:0xb881584
Here #postis returns.You should be giving it like this
Posti.update_column(stato: "checked")