NoMethodError using Prawn and Rails Casts as reference - ruby-on-rails-3

I`m using Prawn 0.14.0
I'm using the rails casts #153 Pdf With Prawn Revised as reference to generate a pdf with some informations and a table.But I`m getting this error:
NoMethodError in LendingsController#show - undefined method `line_items'
I can generate the pdf and some information appears if I don`t call the method "line_item_rows" inside the "line_items method"But if I try to populate the table calling line_item_rows,I get the error above.
I have this in my TermPdf class:
class TermPdf < Prawn::Document
def initialize(lending)
super()
#lending_term = lending
line_items
end
def line_items
move_down 20
table line_item_rows
end
def line_item_rows
[["Equipament","Brand","Tipping","Description"]] +
#lending_term.line_items.map do |item|
[
item.equipment.title,
item.equipment.brand.title,
item.equipment.tipping,
item.description
]
end
end
end
and this is the show method in LendingsController
def show
#lending = Lending.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.pdf do
pdf = TermPdf.new(#lending)
send_data pdf.render, filename: "Agreement Number #{#lending.id}.pdf",
type: "application/pdf",
disposition: 'inline'
end
format.json { render json: #lending }
end
end
I really tried to fix this error but no success.

The issue seems to come from here:
#lending_term.line_items
Now i don't know if this is a relation or a class method but you need to check it out!! PDF code seems clean to me.
A little advise here is to avoid ambiguous naming in your code. You were looking at the wrong direction because you used the name "Line_items" in different cases which made debugging harder.

Related

rails 3 nested resource `new` path being switched

I don't quite get why this is happening, maybe someone of you does... here it goes.
I've created a nested resource:
resources :order do
resources :ordered_vehicles
end
I've added a link_to the new action and passed the order.id like so new_order_ordered_vehicle_path(order.id) the page is loaded nicely. The problem is after I press the button to submit the choice. He switches the path from http://localhost:3000/order/3/ordered_vehicles/new to http://localhost:3000/order/R076027535/ordered_vehicles and displays error Couldn't find Order with id=R076027535... go figure.
The error is being raised in the controller in this method
private
def find_order
#order = Order.find(params[:order_id])
end
Which is a before_filter.
the new.html.haml file looks like this
= form_for [#order, #ordered_vehicle], html: { multipart: true } do |f|
= #order.number
%br= #order.id
= f.fields_for :vehicles do |car|
.... #some fields here
= car.submit "Save your choice"
That id he can't find is the #order.number but I don't get why the switch.
EDIT:
Just to be thorough, I'll add the controller methods:
def new
#ordered_vehicle = #order.ordered_vehicles.build(params.slice(:order_id, :vehicle_id))
end
def create
binding.pry
#ordered_vehicle = #order.ordered_vehicles.build(params.slice(:order_id, :vehicle_id))
if #ordered_vehicle.save
flash[:notice] = "Save successful."
redirect_to account_path
end
end
POST request (I hope that's the one, still new to all this stuff):
"action_dispatch.request.formats"=>[text/html]},
#request_method="POST", #filtered_parameters={"utf8"=>"✓", "authenticity_token"=>
"Ar4vy8pqCSpA2ch0qG0qiJXAJUbNALYxm/FbuKbdzCc=", "ordered_vehicle"=>
{"vehicles"=> {"maker_id"=>"", "model_id"=>"", "year"=>"", "body"=>"", "capacity"=>"", "id"=>"1"}},
"commit"=>"Save your choice", "action"=>"create",
"controller"=>"spree/ordered_vehicles", "order_id"=>"R076027535"}, #method="POST",
#fullpath="/order/R076027535/ordered_vehicles">
As per request ;)
Well, it turned out to be a problem with Spree which I'm currently tweaking (I know I didn't mention it explicitly, but didn't want to just post too much information).
Bottom line:
In the Order model the method to_param was overwritten to pass the number column in to the params. Didn't overwrote it again, just left it there and adapted. In my find_order method I wrote:
def find_order
#order = Order.find_by_number(params[:order_id])
end
Also I've stored the order number in the table, there was a problem I believe with out that, but can't remember explicitly. Anyways, thanks for the help.
P.S. Sorry for the mess

How to pass size param to carrierwave helper?

Im trying to make 1 global function to display carrier wave images in different sizes. the problem is passing the size var in method call to the carrierwave helper like below:
def get_avatar(id, size)
#profile = User.find(id).profile rescue nil
image_tag #profile.photos.first.file_url(:img_120x145)
rescue
image_tag ("/assets/avatars/img_#{size}.png")
end
I tried all kinds of things but are unable to pass the size var to the #profile.photos.first_url(size here).
How should one approach this?
Heres what worked for me recently.
<% image_tag #profile.photos.first.url(size) %>

rspec rendered view fails to include variable data

I have a failing rspec view test but the code works - I probably have a variable incorrectly setup but can't figure out what it is.
When I display the contents of #incident_report (pp #incident_report) in my spec, it properly displays the record created by FactoryGirl.
When I display the actual rendered content (puts rendered), it shows the values from the the record I created with FactoryGirl...
But the "rendered.should contain(work_order)" spec fails with:
1) incident_reports/show.html displays the work order number on the incident
Failure/Error: rendered.should contain(work_order)
expected the following element's content to include "54785":
and none of the data is displayed, only the HTML template
spec/views/incident_report/show.html.haml_spec.rb code
require 'spec_helper'
describe "incident_reports/show.html" do
before(:each) do
#incident_report = Factory(:incident_report)
end
it "displays the work order number on the incident" do
work_order = #incident_report.work_order
pp #incident_report #displays an incident_report, id => 1
assign(:incident_report, #incident_report)
render
puts rendered #this DOES have the content from #incident_report
rendered.should contain("Work Order:")
rendered.should contain(work_order)
end
end
show.html.haml code
%h1 Display Incident Report
.navigation
= link_to 'Edit', edit_incident_report_path(#incident_report)
|
\#{link_to 'Back', incident_reports_path}
= render 'form'
.navigation
= link_to 'Edit', edit_incident_report_path(#incident_report)
|
\#{link_to 'Back', incident_reports_path}
Gotta be something really simple I'm overlooking.
Turns out it's because I was using simple_form and when simple_form displays for a "show" action, it puts the field values into the html as a 'value="54785"' attribute. If you display it in a browser, the labels and values all show up correctly, but rspec can't see them.
I had to add
rendered.should have_tag 'input', :with => { :value => "54765", :name => 'incident_report[work_order]' }
to my example to get it to work.
Seems like there should be a better solution but at least now I can continue testing.

Rails 3: Will_paginate's .paginate doesn't work

I'm using newes Rails 3 version with will_paginate.
#videos = user.youtube_videos.sort.paginate :page => page
I also added the ##per_page attribute to my youtube_video-model.
But it just won't paginate it. I get always all items in the collection listed.
What have I done wrong?
Yours, Joern.
Why are you calling sort here? That seems unnecessary, and probably would result in it finding all videos and calling pagination on that rather than paying any attention to any variable defined in your Video model. Instead, move the sorting logic into the Video model by using a scope or use the order method.
Here's my solution, my own answer, for all other's having trouble with will_paginate and reading this issue:
Create an ApplicationController method like this:
def paginate_collection(collection, page, per_page)
page_results = WillPaginate::Collection.create(page, per_page, collection.length) do |pager|
pager.replace(collection)
end
collection = collection[(page - 1) * per_page, per_page]
yield collection, page_results
end
Then in your Controller, where you got the collection that should be paginated:
page = setup_page(params[:page]) # see below
#messages = Message.inbox(account)
paginate_collection(#messages, page, Message.per_page) do |collection, page_results|
#messages = collection
#page_results = page_results
end
And in your View:
<% #messages.each do |message| %>
<%# iterate and show message titles or whatever %>
<% end %>
<%= will_paginate #page_results %>
To get the page variable defined, check this:
def setup_page(page)
if !page.nil?
page.to_i
else
1
end
end
So page = setup_page(params[:page]) does the trick, with that simple method.
This WORKS!

Rails clone copy or duplicate

I have a nested form and once I save, I want to be able to click a link on the show page to copy or clone that form and open a new one. From there I should be able to make edits (like a new id) and save as a new record. I have seen some examples like this deep_cloneable gem, but I have no idea how to implement it. I think this should be simple, but I just don't understand where to put things in the controller and in the show view.
If you want to copy an activeRecord object you can use its attributes to create new one like
you can have an action in your controller which can be called on link,
def create_from_existing
#existing_post = Post.find(params[:id])
#create new object with attributes of existing record
#post = Post.new(#existing_post.attributes)
render "your_post_form"
end
I found these answers a little hard to follow. One answer shows this:
#post = Post.new(#existing_post.attributes)
which will not work as it will also pass the id, and timestamp values. I used .dup to fix that and I show that in my answer.
Here's how I achieved creating a new item from an existing item.
The model is for a Product, the controller Products_Controller.rb. We're going to add a new action to the controller called copy and we're going to link to it from the show view on an existing Product and render a filled out new view ready to be edited and saved.
First we create a route for the copy action in routes.rb
# Routes.rb
resources :Products do
member do
get 'copy'
end
end
Then a copy action in Products_controller.rb
# ProductController.rb
def copy
#source = Product.find(params[:id])
#product = #source.dup
render 'new'
end
Now we need to add a Link to the show view to call our copy action.
# show.html.erb
<%= link_to "copy", copy_product_path(params[:id]) %>
Rails 4-6 Update:
The strong parameter scaffold makes it even shorter:
# ProductController.rb
# GET /products/1/copy
def copy
#product = #product.dup
render :new
end
And in the erb template:
# show.html.erb
<%= link_to "copy", copy_product_path(#product) %>
class Foo < ActiveRecord::Base
def self.clone_from(parent)
parent = find(parent) unless parent.kind_of? Foo
foo = self.new
foo.attributes = parent.attributes
# if you want to also clone a habtm:
foo.some_association_ids = parent.some_association_ids
# etc.
foo
end
end
class FoosController < ApplicationController
def clone
foo = Foo.clone_from(params[:id])
respond_with(foo)
end
end
Also worth mentioning is the dup method on a model. It makes a copy with all attributes and outgoing relations but sets id to nil. Like this (borrowing code from Naren Sisodiya):
def create_from_existing
#existing_post = Post.find(params[:id])
#create new object with attributes of existing record
#post = #existing_post.dup
render "your_post_form"
end