Find children of a user supplied id in a self-join association - ruby

I have a functioning self-join relationship where a guideline has many children and belongs to a parent. I need to let the user supply an ID via an html form, and then find its children, or its parent (in a separate form of course) When I run in rails console as
#guidelines = Guideline.find(4)
#guidelines.children
I get the proper children, and when i do
#guideline.parent
I get the proper parent.
For some reason when I define a form as
<%= form_tag(guidelines_path, :method => "get", id: "search-form") do %>
<td><%= label_tag(:seeChildren, "See Immediate Children")%></td>
<td><%= text_field_tag :seeChildren, params[:seeChildren], placeholder: "Enter ID" %></td>
<td><%= submit_tag "Search", :name => nil %></td>
<% end %>
(app/views/index.html.erb)
And in the controller i say
if params[:seeChildren]
#guideline = Guideline.find(params[:seeChildren])
#guideline.children
(app/controllers/guidelines_controller.rb)
I get the following error in my rails served in Terminal:
Started GET "/guidelines?utf8=%E2%9C%93&seeChildren=4" for 127.0.0.1 at 2014-10-18 14:25:58 -0500
Processing by GuidelinesController#index as HTML
Parameters: {"utf8"=>"✓", "seeChildren"=>"4"}
Guideline Load (0.3ms) SELECT "guidelines".* FROM "guidelines" WHERE "guidelines"."id" = ? LIMIT 1 [["id", 4]]
Rendered guidelines/index.html.erb within layouts/application (4.1ms)
Completed 500 Internal Server Error in 85ms
ActionView::Template::Error (undefined method `each' for nil:NilClass):
62: <th>Guideline Text</th>
63: </tr>
64:
65: <% #guidelines.each do |guideline| %>
66: <tr>
67: <td><%= guideline.id %></td>
68: <td><%= guideline.guide_desc %></td>
app/views/guidelines/index.html.erb:65:in `_app_views_guidelines_index_html_erb__3376611479089996349_70360485758280'
Rendered /Users/john.dodson/.rvm/gems/ruby-2.1.3#global/gems/actionpack-4.1.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.7ms)
Rendered /Users/john.dodson/.rvm/gems/ruby-2.1.3#global/gems/actionpack-4.1.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.3ms)
Rendered /Users/john.dodson/.rvm/gems/ruby-2.1.3#global/gems/actionpack-4.1.6/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb within rescues/layout (21.6ms)
Any ideas? I appreciate the help. Ive posted a couple questions and was unsuccessful usually because I wasn't supplying enough information, so please let me know if you need to see another file.

It looks like you may have forgotten to define #guidlines in your controller, which would explain why you are getting the undefined method 'each' for nil:NilClass error message when attempting to call .each on #guidelines in <% #guidelines.each do |guideline| %>

Yes, Same as JBMILGROm said, you forgot to mention #guidelines in controller.

In addition to using the wrong singular/plural on guidelines, I found out that I needed to cast a single object into an array. So find a guideline, then call children and cast the results into an array. so in the controller I say:
if params[:seeChildren]
#guideline = Guideline.find(params[:seeChildren])
#guidelines = Array.wrap(#guideline.children())
and magic, my query works. Posting this here so other people having a similar problem can find the truth.

Related

locking and unlocking in a table

HELP!!!!
As I am learning rails I am developing this application and I am caught in a few areas.
In my jobs/index.html.erb file All of the jobs are listed for the users regardless if they are admin or employees. The main difference is that if the job is locked, the employee cannot view the details of the job, and if the job is unlocked the details are fully accessible.
My problem is that whenever the image is clicked, the job gets deleted. I am aiming for the image to be clicked ( when logged in as an admin of course) and the lock image changes to the unlocked one and vice versa.
my code in my jobs/index.html.erb file looks like this :
<% if current_user.admin? %>
<td><%= link_to 'Edit', edit_job_path(job) %></td>
<td><%= link_to 'Delete', job, method: :delete, data: {confirm: 'Are you sure?'} %></td>
<td><%= link_to(image_tag(job.locked ? 'unlock.png' : 'lock.png', size: "18x18"), job, method: :delete) %></td>
<% end %>
currently when the image is clocked the job gets deleted. How can I keep the job and simply change the status from locked to unlocked? I believe I do have to create a method in my controller.
#Bala's suggestion seems like it's on the right track to me. Removing method: :delete won't help you change the locked/unlocked status of your jobs, but you'll at least stop deleting your jobs. Check out this page for more info on the architecture of a link_to tag:
http://apidock.com/rails/ActionView/Helpers/UrlHelper/link_to
By including method: :delete in that part of your link_to tag, you're passing it as a part of the (optional) HTML options hash. The link "name" is the locked/unlocked image, your URL will be populated by Rails (you've pointed it to the Job object), and the method your application will exert on the Job object that link is pointing to is delete. If you've left Rails to its typical routing conventions, this means that you're most likely running the JobsController#destroy method.
You'll want to add a route and method to your controller that allows you to toggle the status of your job from locked to unlocked. Something like this:
In your routes.rb file:
match 'jobs/:id/toggle_lock' => 'jobs#toggle_lock', :as => 'toggle'
In your JobsController:
def toggle_lock
#job = Job.find(params[:id])
#job.locked ? #job.locked = false : #job.locked = true
#job.save!
redirect_to jobs_path ## <= or whatever
end
And finally, in your view:
<%= link_to(image_tag(job.locked ? 'unlock.png' : 'lock.png', size: "18x18"), toggle_path(job)) %>
Feel free to adjust the logic however you like!

instance variable inside edit method for webform (Rails)

Rails (version 4) question: I have a table called "sections" and I generate a controller called Sections like this:
rails generate controller Sections index show edit new delete
When I browse to, for example, http://localhost:3000/sections/edit/4 I don't see the prepopulated values (the values from the DB which I wish to edit) in the webform.
I need to add some details. The edit and update methods (found in sections_controller.rb) are created as:
def edit
#sect = Section.find(params[:id])
end
def update
#sect = Section.find(params[:id])
if #sect.update_attributes(sect_params)
redirect_to(:action=>'index')
else
render('edit')
end
end
The update method doesn't require a template file, but edit does. So in the view\sections\edit.html.erb we have:
<%= form_for(:section, :url => {:action => 'update', :id => #section.id}) do |f| %>
<table>
<tr>
<th> Field 1 </th>
<td> <%= f.text_field(:field1) %> </td>
</tr>
<tr>
<th> Field 2 </th>
<td> <%= f.text_field(:field2) %> </td>
</tr>
</table>
<%= submit_tag("Edit section") %>
<% end %>
So the edit mechanism works perfectly, except that I don't see the prepopulated fields in the edit webform (which is inconvenient to say the least, especially in case of a large number of fields).
I already corrected this by renaming the #sect (only from method edit) instance variable to #section. However, I am puzzled and astounded by this solution. Shouldn't I supposedly be allowed to choose any variable name? Is this a Rails bug? Please enlighten me.
(In every other language I was free to choose any variable name as pleased without any repercussions.)
Take a look at the docs for form_for. You aren't giving it the model object it should be creating the form with, you're just basically specifying the object's name with the :section symbol.
Instead, pass the object you want to edit in (form_for(#section...)), that should get you the pre-populated fields you are looking for.

Rails route, show all elements on the same page

I need to show all my elements on the same page.
In routes:
namespace :nourishment do
resources :diets do
resources :nourishment_meals, :controller => 'meals'
get 'nourishment_meals/show_all_meals' => 'meals#show_all_meals', as: "show_all_meals"
end
end
which will generate:
nourishment_diet_nourishment_meals_path GET /nourishment/diets/:diet_id/nourishment_meals(.:format) nourishment/meals#index
POST /nourishment/diets/:diet_id/nourishment_meals(.:format) nourishment/meals#create
new_nourishment_diet_nourishment_meal_path GET /nourishment/diets/:diet_id/nourishment_meals/new(.:format) nourishment/meals#new
edit_nourishment_diet_nourishment_meal_path GET /nourishment/diets/:diet_id/nourishment_meals/:id/edit(.:format) nourishment/meals#edit
nourishment_diet_nourishment_meal_path GET /nourishment/diets/:diet_id/nourishment_meals/:id(.:format) nourishment/meals#show
PATCH /nourishment/diets/:diet_id/nourishment_meals/:id(.:format) nourishment/meals#update
PUT /nourishment/diets/:diet_id/nourishment_meals/:id(.:format) nourishment/meals#update
DELETE /nourishment/diets/:diet_id/nourishment_meals/:id(.:format) nourishment/meals#destroy
[**THIS**]
nourishment_diet_show_all_meals_path GET /nourishment/diets/:diet_id/nourishment_meals/show_all_meals(.:format) nourishment/meals#show_all_meals
The problem, when I do this:
<%= link_to "Show all meals", nourishment_diet_show_all_meals_path, :class=>"button green" %>
This error raise:
Problem:
Problem:
Document(s) not found for class NourishmentMeal with id(s) show_all_meals.
Summary:
When calling NourishmentMeal.find with an id or array of ids, each parameter must match a document in the database or this error will be raised. The search was for the id(s): show_all_meals ... (1 total) and the following ids were not found: show_all_meals.
Resolution:
Search for an id that is in the database or set the Mongoid.raise_not_found_error configuration option to false, which will cause a nil to be returned instead of raising this error when searching for a single id, or only the matched documents when searching for multiples.
The error is here, on my meals_controller.rb
private
# Use callbacks to share common setup or constraints between actions.
def set_nourishment_meal
#nourishment_diet = NourishmentDiet.find(params[:diet_id])
[***HERE***] #nourishment_meal = #nourishment_diet.meals.find(params[:id])
end
Method:
def show_all_meals
puts "This word does not appear"
end
Can someone help me?
The route below expects a :diet_id. A diet instance has to be provided as an argument for this path to call corresponding action.
nourishment_diet_show_all_meals_path GET /nourishment/diets/:diet_id/nourishment_meals/show_all_meals(.:format) nourishment/meals#show_all_meals
This should be changed:
<%= link_to "Show all meals", nourishment_diet_show_all_meals_path, :class=>"button green" %>
to:
<%= link_to "Show all meals", nourishment_diet_show_all_meals_path(diet), :class=>"button green" %>
Notice the argument (diet) above.
I think you should pass diet_id parameter in params. You should try something like this: <%= link_to "Show all meals", nourishment_diet_show_all_meals_path(#diet.id), :class=>"button green" %>. #diet.id is just an example, use whatever works for your application.

Rails 3: Loop shows more records than there should be

Not exactly sure of what to call this issue. Still new to rails.
Situation: An auction contains many lots.
I'm showing an auction's lots in a url like /auctions/3/lots/.
View:
<ul>
<% #lots.each do |lot| %>
<li><%= lot.auction_id %>: <%= lot.id %></li>
<% end %>
</ul>
Outputs this:
<ul>
<li>3: 1</li>
<li>3: </li>
</ul>
I only have one lot in my database. Not sure where the extra loop instance is coming from.
This happens on any lot listing no matter which auction I'm looking at.
Also,
<%= #lots.length %> displays 2
<%= #lots.size %> displays 2
<%= #lots.count %> displays 1
My lots_controller looks like this:
def index
#auction = Auction.find(params[:auction_id])
#lots = #auction.lots
end
def create
#auction = Auction.find(params[:auction_id])
#lot = #auction.lots.build(params[:lot])
if #lot.save
redirect_to auction_lots_path, :notice => 'Lot was successfully created.'
else
render :action => "index"
end
end
My models:
class Auction < ActiveRecord::Base
...
has_many :lots
end
class Lot < ActiveRecord::Base
belongs_to :auction
...
end
The ...s are just attr_accesssible and validates lines.
The log when I hit the page was requested, here it is.
Started GET "/auctions/8/lots" for 127.0.0.1 at 2013-02-13 16:35:51 -0500
Processing by LotsController#index as HTML
Parameters: {"auction_id"=>"8"}
Auction Load (0.1ms) SELECT "auctions".* FROM "auctions" WHERE "auctions"."id" = ? LIMIT 1 [["id", "8"]]
Lot Load (0.2ms) SELECT "lots".* FROM "lots" WHERE "lots"."auction_id" = 8
[#<Lot id: 18, description: "1923 Morgan", lot_number: 1, auction_id: 8, created_at: "2013-02-13 17:20:04", updated_at: "2013-02-13 17:20:04">]
Rendered layouts/_messages.html.erb (0.1ms)
Lot Exists (0.2ms) SELECT 1 AS one FROM "lots" WHERE "lots"."auction_id" = 8 LIMIT 1
Rendered lots/index.html.erb within layouts/application (9.4ms)
Completed 200 OK in 21ms (Views: 17.8ms | ActiveRecord: 0.5ms)
Update:
Someone mentioned that it looks like I'm using #auction.lots.build somewhere.
And yes, I am. I have a form on the same page (index) where I can add lots.
<%= form_for(#auction.lots.build, :url => auction_lots_path(#auction)) do |f| %>
...
<% end %>
Changing #auction.lots.build got rid of the extra row, although now I can't create lots successfully. I'm not sure what to do. I probably have to set up something in the index method of the lots_controller, but I don't know what.
Any help is appreciated.
This would happen in your create method if the lot failed to save. Because you used #auction.lots.build, that appends a lot record to the auction. If it doesn't save properly, it's still there unsaved. That explains why the "mystery" one doesn't have an id, and also why:
<%= #lots.size %> displays 2
<%= #lots.count %> displays 1
#lots.count is a database query, but #lots.size is just the size of the array in memory.
I would probably do something more like this in the create action:
def create
#auction = Auction.find(params[:auction_id])
#lot = #auction.lots.create!(params[:lot])
redirect_to auction_lots_path, :notice => 'Lot was successfully created.'
rescue ActiveRecord::RecordInvalid
render :action => "index"
end
... but of course others will prefer using if/else rather than rescuing the exception. There are other ways around this. You could do #auction.reload.lots to cull the unsaved one, but that's a little wierd. The normal rails thing to do in this case is re-render the form with the validation errors displayed and ask the user to fix them and try creating again.
This should help:
def create
params[:lot].merge!({:auction_id => params[:auction_id]})
#lot = Lot.new(params[:lot])
if #lot.save
redirect_to auction_lots_path, :notice => 'Lot was successfully created.'
else
render :action => "index"
end
end

HAML Ruby - conditionals

I'm going through examples from 'Agile Web Dev with Rails' book, but mixing it with extra techniques i found useful - like haml.
Got one tricky issue, how to write down this erb partial:
<% if line_item == #current_item %>
<tr id="current_item">
<% else %>
<tr>
<% end %>
<td><%= line_item.quantity %>×</td>
<td><%= line_item.product.title %></td>
<td class="item_price"><%= number_to_currency(line_item.total_price) %></td>
</tr>
In haml?
Tried sth like this:
-if line_item==#current_item
%tr#current_item
-else
%tr
%td!=line_item.quantity.to_s+"×"
%td=line_item.product.title
%td.item_price=number_to_currency(line_item.total_price)
But it prints out an empty TR without TD within...
Rather than having two separate %tr entries (in which case you would need to list your 3 td's under each tr, I think), you could just set the id in a conditional:
%tr{:id => (line_item == #current_item) ? "current_item" : false}
%td!=line_item.quantity.to_s+"×"
%td=line_item.product.title
%td.item_price=number_to_currency(line_item.total_price)

Resources