I'm using Rails 4.2.6 with an sqlite3 database. I want to print the data from database into a file which is readable. But when I click the "Show" button it gives me this error even though I haven't set show's route to POST.
Here is the stuff am working with:
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></th>
</tr>
</thead>
<tbody>
<% #resumes.each do|resume| %>
<tr>
<td><%= resume.name%></td>
<td><%= link_to "Download Resume", resume.attachment_url %></td>
<td><%= button_to "Delete", resume, method: :delete, class: "btn btn-danger", confirm: "Are you sure to delete #{resume.name}?" %></td>
<td><%= button_to "Show", resume, method: :show, class: "btn btn-primary"%></td>
</tr>
<% end %>
</tbody>
</table>
routes.rb:
Rails.application.routes.draw do
resources :resumes
root "resumes#index"
get 'resumes/index'
get 'resumes/new'
get 'resumes/create'
get 'resumes/destroy'
get 'resumes/show'
end
rake routes:
Prefix Verb URI Pattern Controller#Action
resumes GET /resumes(.:format) resumes#index
POST /resumes(.:format) resumes#create
new_resume GET /resumes/new(.:format) resumes#new
edit_resume GET /resumes/:id/edit(.:format) resumes#edit
resume GET /resumes/:id(.:format) resumes#show
PATCH /resumes/:id(.:format) resumes#update
PUT /resumes/:id(.:format) resumes#update
DELETE /resumes/:id(.:format) resumes#destroy
root GET / resumes#index
resumes_index GET /resumes/index(.:format) resumes#index
resumes_new GET /resumes/new(.:format) resumes#new
resumes_create GET /resumes/create(.:format) resumes#create
resumes_destroy GET /resumes/destroy(.:format) resumes#destroy
resumes_show GET /resumes/show(.:format) resumes#show
Please tell me if anything else is also needed.
Try updating the show button syntax line:
<td><%= button_to "Show", url_for(controller: 'resumes', action: 'show', id: resume.id), method: :get, class: "btn btn-primary"%></td>
Also, here is a nice little description of the different HTTP method and their related Rails actions.
Related
I'm developing a CRUD and I have three tables clients, audit_cases and ra_cases.
The followings are the relationship of my models
class Client < ActiveRecord::Base
has_many :audit_cases
end
class AuditCase < ActiveRecord::Base
belongs_to :client
has_many :ra_cases
end
class RaCase < ActiveRecord::Base
belongs_to :audit_case
end
Model
def index
#a_cases = AuditCase.all
#b_cases = RaCase.all
end
I'm trying to join these three tables and show in a view
The following script works successfully
<tbody>
<% #b_cases.each do |b_case| %>
<tr>
<td><%= b_case.audit_case.client.Client_name %></td>
</tr>
<% end %>
</tbody>
But the following script have an error of undefined method `Client_name' for nil:NilClass
<tbody>
<% #a_cases.each do |a_case| %>
<tr>
<td><%= a_case.client.Client_name %></td>
</tr>
<% end %>
</tbody>
I can get the client array 'Client:0x007ff7d662adb0' if I use
<%= a_case.client %>
I'd like to know how could I modify my script if I want to extract parent's data from child(audit_cases) instead of from grandchild(ra_cases).
Thank you very much!
Due to some of the column "client.Client_name" are nil,
It works after I add this code "unless a_case.client.nil?"
<%= a_case.client.Client_name unless a_case.client.nil? %>
It doesn't look like each relation is required, so there may be some AuditCase records in your database that don't have Client records associated with them (or the Client record was destroyed). The consequence of that is that your view will raise an error because it tries to call a method on nil.
To get the view working, I would nil-guard it in some way. If you want to enforce a requirement around the client-case relationship, that's a different issue.
Here are some possible nil guard ideas:
# If you're using Ruby 2.3+, you can use the Safe Navigation Operator
<tbody>
<% #a_cases.each do |a_case| %>
<tr>
<td><%= a_case.client&.Client_name %></td>
</tr>
<% end %>
</tbody>
# Rails also provides a #try method
<tbody>
<% #a_cases.each do |a_case| %>
<tr>
<td><%= a_case.client.try(:Client_name) %></td>
</tr>
<% end %>
</tbody>
# or just a rough nil check
<tbody>
<% #a_cases.each do |a_case| %>
<tr>
<td><%= a_case.client.Client_name if a_case.client %></td>
</tr>
<% end %>
</tbody>
Let me know if that works.
From a ruby style perspective, I would avoid capitalizing methods like Client_name. Capitalization defines a constant/class in ruby.
In a view.html.erb, I want to use something like:
<tbody>
<% #books.each do |book| %>
<tr>
<td><%= book.title %></td>
<td><%= book.author %></td>
<td><%= link_to 'Show', book, class: 'btn btn-mini btn-primary' %></td>
<td><%= link_to 'Edit', edit_book_path(book), class: 'btn btn-default' %></td>
<td><%= link_to 'Destroy', book, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-mini btn-danger' %></td>
<td><%= link_to 'Reserve it', books_path(book, :situation_id => 2), class: "btn btn-mini btn-success" %></td>
</tr>
<% end %>
</tbody>
When I click on the button "Reserve it", I would like that the field "situation_id" of this book become equal to 2.
How can I do that?
If a book has a situation association (and your associations are set up correctly), then you could pass it as a parameter with <%= link_to 'Reserve it', books_path(book, :situation_id => book.situation_id), ... %>
However, you shouldn't need to pass it the situation_id param since you can just grab it with the book instance variable that you're going to. In other words you can do
def show
#book = Book.find(params[:id]).include(:situation)
end
and your book will load up the situation as well and it will be available in your book show view.
Not a Rails solution but I hope this will help you thinking in right direction may be.
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
$(document).ready(function(){
$("#link").click(function(){
$("a").attr("href", function(i, href) {
return href + 'books/?situation_id=2';
});
});
});
</script>
</head>
<body>
<a href="" id="link" >hello</a>
</body>
</html>
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 know there are a lot of issues with wkhtmltopdf and page breaks that date back years, but I haven't worked out a solution yet. I'm using the PDFKit gem to generate my html pages into pdfs, but I don't want the pages to break in the middle of a table row.
I'm using wkhtmltopdf-binary (0.9.9.3), which looks to be the most updated version
My CSS:
#media print {
#scores table tr td, #scores table tr th {
page-break-inside: avoid !important;
}
table, tr, td, th, tbody, thead, tfoot {
page-break-inside: avoid !important;
}
}
My table:
<div class="score_table">
<table id="scores" class="print-friendly">
<tbody>
<% #chapters.each do |chapter| %>
<tr>
<th colspan="3" ><%= chapter.name %></th>
</tr>
<% chapter.rules.each do |rule| %>
<tr>
<th colspan="2" >Rule: <%= rule.name %></th>
<th></th>
</tr>
<!-- Triggers -->
<% rule.triggers.each do |trigger| %>
<tr>
<td>T</td>
<td><%= markdown(trigger.body) %></td>
<td><%= markdown(trigger.explanation) %></td>
</tr>
<% if trigger.image? || trigger.image2? %>
<tr>
<td></td>
<% if trigger.image? %>
<td><%= image_tag trigger.image.url(:thumb) %></td>
<% else %>
<td></td>
<% end %>
<% if trigger.image2? %>
<td><%= image_tag trigger.image2.url(:thumb) %></td>
<% else %>
<td></td>
<% end %>
</tr>
<% end %>
<% end %>
<!-- Questions -->
<% rule.questions.each do |question| %>
<tr>
<td>Q</td>
<td><%= markdown(question.body) %></td>
<td><%= markdown(question.answer) %></td>
</tr>
<% if question.image? || question.image2? %>
<tr>
<td></td>
<% if question.image? %>
<td><%= image_tag question.image.url(:thumb) %></td>
<% else %>
<td></td>
<% end %>
<% if question.image2? %>
<td><%= image_tag question.image2.url(:thumb) %></td>
<% else %>
<td></td>
<% end %>
</tr>
<% end %>
<% end %>
<!-- Hints -->
<% rule.hints.each do |hint| %>
<tr>
<td>H</td>
<td><%= markdown(hint.body) %></td>
<td><%= markdown(hint.explanation) %></td>
</tr>
<% if hint.image? || hint.image2? %>
<tr>
<td></td>
<% if hint.image? %>
<td><%= image_tag hint.image.url(:thumb) %></td>
<% else %>
<td></td>
<% end %>
<% if hint.image2? %>
<td><%= image_tag hint.image2.url(:thumb) %></td>
<% else %>
<td></td>
<% end %>
</tr>
<% end %>
<% end %>
<% end %>
<% end %>
</tbody>
</table>
</div>
Is there a work around, or is there something that I'm doing wrong? This is the result:
I could post the PDFKit code as well, but it sounds like a wkhtmltopdf issue
***Update - My CSS #print isn't affecting the page when .pdf is added to the url. I have my stylesheet link with media: "all"
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
Here's my initializer pdfkit.rb:
ActionController::Base.asset_host = Proc.new { |source, request|
if request.env["REQUEST_PATH"].include? ".pdf"
"file://#{Rails.root.join('public')}"
else
"#{request.protocol}#{request.host_with_port}"
end
}
If I can fix the CSS, then I probably will solve the page break issue!
i added this in css it worked for me
#media print {
#scores {
page-break-before: always;
}
}
I am using version wkhtmltopdf 0.12.0
For me, page breaks ONLY work with --print-media-type.
Without it, page break protection for images works, but not page-break-after or before.
I had to make a special css file for print media to get it work.
Setting the paper size to 'A3' or using the 'overflow: visible' didn't make any difference.
I ended up with the following:
in config/initializers:
PDFKit.configure do |config|
config.wkhtmltopdf = '/usr/bin/wkhtmltopdf'
config.default_options = {
:encoding=>"UTF-8",
:page_size => 'A3',
:zoom => 0.9,
:javascript_delay => 2000,
:print_media_type => true,
:footer_right => 'report, page [page] of [toPage]',
:no_background => true,
}
end
I am not 100% sure if the no_background is needed.
Then, in the controller:
def report_as_pdf
require 'nokogiri'
root_url = Rails.env.development? ? 'http://localhost:3000' : 'https://my.example.com'
html = render_to_string(layout: true, template: "reports/report_as_pdf").gsub('/assets', root_url + '/assets') # since wkhtmltopdf can not find the css files, we add the root_url to all assets
html_doc = Nokogiri::HTML(html)
html_doc.css('div.contain-to-grid').remove
html_doc.css('nav#rapportage_bar').remove
# Had to remove certain elements on the page. Not relevant for this particular problem, but it may help.
html = html_doc.to_html
filename = 'report_' + Time.now.to_s(:db)[0..9]
if Rails.env.development?
File.write("/tmp/#{filename}.html", html)
render :text => "wrote /tmp/#{filename}.html"
fork do
system("wkhtmltopdf --footer-right 'report, page [page] of [toPage]' --page-size 'A3' --zoom 0.9 --javascript-delay 2000 --no-background --print-media-type file:////tmp/#{filename}.html /tmp/#{filename}.pdf")
end
# forking was the only way I could get it to work in development mode, using thin as webserver instead of webrick (but it might work with webrick, I didn't try).
else
kit = PDFKit.new(html)
send_data(kit.to_pdf, :filename => filename + '.pdf', :type => 'application/pdf')
# all is simpeler in production mode.
end
end
Note, that in the default layout (normally app/views/layouts/application.html.erb) I added one line to introduce a special css file for print:
stylesheet_link_tag "application_print", media: "print"
This file actually imports some tables from ZURB Foundation, which is cool.
#import "foundation/components/tables";
h1 {
font-variant: small-caps;
font-weight: bolder;
font-size: 320%;
border-bottom: 12px solid black;
margin-bottom: 20px;
margin-top: 80px;
}
h2 { (etc etc etc)
To make page breaks in a view, I just insert this in the right places:
I hope this will be useful to someone someday.
Can you upload the controller code where you've called PDFkit.new ?
Your stylesheet might not be included.
Try adding the stylesheet in your controller code like this:
def export
kit = PDFKit.new(render_to_string(layout: false, handlers: [:haml], formats: :html, template: 'score_tables/export'))
kit.stylesheets << "#{Rails.root}/vendor/assets/stylesheets/bootstrap.css"
kit.stylesheets << "#{Rails.root}/app/assets/stylesheets/score_tables.css"
kit
end
Here is how I fixed my issue.
- Updated PDFKIT to as of ( 01/22/2014 )
- I had to move my table out of the <div> as the nested table messes everything up.
Example:
No div tag wrapping the table.
From
<div class="score_table">
<table id="scores" class="print-friendly">
...rest of the HTML
To
<table id="scores" class="print-friendly">
...rest of the HTML
Hope this helps.
Can someone rails-haml expert translate please , how this haml code is translated to html ?
the page is derived from this url . I m only interested in lines 1 and 12. I ve used the various tools , on line con verters but the dont seem to work :(
%table.table.table-bordered.table-striped#sortable{:data => {update_url:
sort_admin_things_path}}
%thead
%tr
%th= Title
%th= Description
%th
%tbody
- #things.each do |thing|
# make the <tr>'s draggable by adding the expected '.item' class
# pass the item id into params[:id]
%tr{data: {item_id: "#{thing.id}"}, class: 'item'}
%td= thing.title
%td= thing.description.truncate(20)
%td
= link_to 'show', admin_thing_path(thing), :class => 'btn'
= link_to 'edit', edit_admin_thing_path(thing), :class => 'btn btn-primary'
= link_to 'destroy', admin_thing_path(thing), method: :delete, confirm: "Are you sure?", :class => 'btn btn-danger'
That's not correctly indented. The big deal with haml is that things must be correctly indented to work. Otherwise you'll have unexpected errors due to the indentation.
Anyway..Try this:
<table class="table table-bordered table-striped" id="sortable" data-update_url = <%= sort_admin_things_path%> >
<thead>
<tr>
<th>
<%= Title %>
</th>
<th>
<%= Description %>
</th>
<th> </th>
</tr>
</thead>
<tbody>
<% #things.each do |thing| %>
<tr data-item_id= <%= thing.id %> class= "item" >
<td>
<%= thing.title %>
</td>
<td>
<%= thing.description.truncate(20) %>
</td>
<td>
<%= link_to 'show', admin_thing_path(thing), :class => 'btn' %>
<%= link_to 'edit', edit_admin_thing_path(thing), :class => 'btn btn-primary' %>
<%= link_to 'destroy', admin_thing_path(thing), method: :delete, confirm: "Are you sure?", :class => 'btn btn-danger' %>
</td>
</tr>
<% end %>
</tbody>
</table>