Loop thru values code - ruby-on-rails

This is what I’m trying to do:
When an order is created, click view link and and get redirected to the show page which contains the invoice. I'm using the below code to loop thru values in the invoice. But its not working correctly, all invoices are showing up instead of only the selected one.
I already tried deleting the <% #orders.each do |order| %> but without any luck.
What am I missing here? Any idea?
<% #orders.each do |order| %>
<% order.line_items.each do |line_item| %>
Order #<%= line_item.order_id %>
<%= order.first_name %> <%= order.last_name %>
<%= line_item.product.title %>
<%= number_to_currency line_item.product.price %>
<%= line_item.quantity %>
<%= number_to_currency line_item.total_price %>
<% end %>
<% end %>
Update 1
route.rb: resources :orders, only: [:index, :new, :create, :show]
I don't have an invoice controller, everything is going thru the orders controller.
def show
#orders = Order.all
end
def new
#cart = current_cart
if #cart.line_items.empty?
redirect_to root_url, notice: "Your cart is empty"
return
end
#order = Order.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: #order }
end
end
def create
#order = Order.new(order_params)
#order.add_line_items_from_cart(current_cart)
#order.user_id = current_user.id
if #order.save
if #order.process
redirect_to root_path, notice: "Successfully charged."
and
return
end
end
render 'new'
end

Change the method In Controller to
def show
#order = Order.find(params[:id])
end
and in views remove
<% #orders.each do |order| %>
and call the order attributes by
<% #order.line_items.each do |line_item| %>
Order #<%= line_item.order_id %>
<%= #order.first_name %> <%= #order.last_name %>
<%= line_item.product.title %>
<%= number_to_currency line_item.product.price %>
<%= line_item.quantity %>
<%= number_to_currency line_item.total_price %>
<% end %>
you were showing all the orders instead you only need to show order that got created in latest.

The Show method needs to look like this
def show
#order = Order.find(params[:id])
end
Make sure the route has the id in it, it should look like this where ":id" is a number (most likely)
/orders/:id
If the route doe snot look like that change the route in the link to that,
probably something like the params[:id] bit is grabbing that id from the route and that is how it finds that specific order.
In your view you will not need to do the each loop. You will be able to use the #order variable you create, so your view would look like this
<%= #order.first_name %> <%= #order.last_name %>

#Theopap
The issue currently is the show method which returns the all the orders found in the Order database, refactor the show method to look for orders of a specific id, therefore your show method should look something like this:
Current show should become index action
def index
#orders = Order.all
end
This will get the order id from the route, so the
def show
#order = Order.find(params[:id])
end
Routes
Something like this should done with your routes so that your params[id].
get ‘\order\:id’, to:‘order#show’
Better still use the option below to generate the 7 default rails actions.e.g. index, show, create etc.
resources orders (http://guides.rubyonrails.org/v2.3/routing.html)

Could you please display your show method, the issue is likely to be from there. Use the ruby on rails debugger in the mean time, to ensure that #orders contains the invoice information for just the order placed.
try this: <%= debug #orders %>

Related

How can I order posts in descending order

I'm making a blog type site, and I'd like the posts to be displayed newest first(descending order) Ive tried a few different things and haven't been able to figure it out. This is my current code:
post.html.erb
<%= #posts.each do |post|%>
<div>
<p><%= avatar_for(post.user, size: 40) %>
<%= link_to post.username, post.user %></p>
<h2>
<%= link_to post.title, post %>
</h2>
</div>
<% end%>
post controller
class PostsController < ApplicationController
before_action :authenticate_user!
def posts
#posts = Post.all.order("created_at DESC")
end
def new
#post = Post.new
end
def create
#post = current_user.posts.new(post_params)
if #post.save
redirect_to post_path(#post)
else
render :new
end
end
def show
#post = Post.find(params[:id])
end
private
def post_params
params.require(:post).permit(:title, :body, :all_tags)
end
end
I believe, based on the Guide, that the syntax you're looking for is:
Post.order(created_at: :desc)
See if that works for you.
This should be #posts as you are calling #posts in you post.html.erb to retrieve and display all the posts:
def posts
#posts = Post.all.order("created_at DESC")
end
The method should look like
def posts
# Plural #posts
#posts = Post.all.order(created_at: :desc)
end
Just a small fix, in your posts method you're declaring #post variable but in the ERB file you're calling #posts.
That should be giving you a Nil error. Declare #posts (plural), and then your ERB file with better indentation:
<%= #posts.each do |post| %>
<div>
<p>
<%= avatar_for(post.user, size: 40) %>
<%= link_to post.username, post.user %>
</p>
<h2>
<%= link_to post.title, post %>
</h2>
</div>
<% end%>
In case this question hasn't been answered yet:
It looks like the problem is coming from the name of the method in your PostsController.
You're expecting to have access to #posts from a method called posts, but your file name for the view you're trying to render is post.html.erb. I believe it should be posts.html.erb.
Why not call it index? That's the Rails convention.
As others have said, the query is correct. Hope this helps.

Edit page to display all category names with edit inputs on each

I have categories nested inside of guides. I'm building an app to learn rails better and I'm trying to make a page that will display all categories that belong to a guide and have edit inputs under them and a save button next to it so the user can edit the names of the categories they want to change.
Bit stuck on how exactly how get this done.
here is the category_item_keys controller
def edit
#guide = Guide.friendly.find(params[:guide_id])
#category = Category.friendly.find(params[:category_id])
#key = #category.category_item_keys
end
def update
#guide = Guide.friendly.find(params[:guide_id])
#category = Category.friendly.find(params[:category_id])
#key = #category.category_item_keys.friendly.find(key_params) # no idea what to make this equal because it isn't one set key being edited on the page
if #key = #category.category_item_keys.update_attributes(key_params)
flash[:success] = "Key updated"
redirect_to #guide
else
render 'edit'
end
end
private
def key_params
params.require(:category_item_key).permit(:key, :slug)
end
routes
match '/guides/:guide_id/:category_id/keys/edit' => 'category_item_keys#edit', :via => :get
match '/guides/:guide_id/:category_id/keys/' => 'category_item_keys#update', :via => :post, as: :category_item_keys_update
edit.html.erb
<ul>
<% #key.each do |key| %>
<li><%= key.key #just shows key name %><br>
<%= form_for([#category, #keys], url: category_item_keys_create_path) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :key, "Key name" %>
<%= f.text_field :key %>
<%= f.submit "Save" %>
<% end %>
</li>
<% end %>
</ul>
This just gives me an error of:
undefined method `to_key' for #<CategoryItemKey::ActiveRecord_Associations_CollectionProxy:0x007fe20a86b480>
Later I plan on using an in-place editor gem but i would like to learn how this can be done fist.
EDIT:
Fixed the error ( changed form_for([#category, #keys] to form_for([#category, key] and turns out this way works for displaying and allowing all categories to be edited... to an extent.
I get another error when i submit a form
undefined method 'update_attribute'
EDIT 2
slowly getting there. I Changed the update #key variable to #key = #category.category_item_keys.all to fix the error. But this line is now giving me problems
if #key = #category.category_item_keys.update_attributes(key_params)'
THIRD EDIT
ERROR
Couldn't find CategoryItemKey without an ID
on line
#key = #category.category_item_keys.find params[:id]
paramaters:
{"utf8"=>"✓", "_method"=>"patch", "authenticity_token"=>"egj/OebdSbxxaoaTkr46WVIOIIu4Ezijzu45kqxLT0krjFWHqi67SRJDSgV7bcL6SeoGpUSYsrolspylCXBu9g==",
"category_item_key"=>{"name"=>"def1111"},
"commit"=>"Save",
"guide_id"=>"dbz",
"category_id"=>"characters"}
Here's how to clean up the code:
#config/routes.rb
resources :guides do
resources :categories, path: "" do
resources :category_item_keys, path: "keys", only: [:update] do
get :edit, on: :collection #-> url.com/guides/:guide_id/:category_id/keys/edit
end
end
end
#app/controllers/keys_controller.rb
class KeysController < ApplicationController
def edit
#guide = Guide.find params[:guide_id]
#category = Category.find params[:category_id]
#keys = #category.category_item_keys
end
def update
#guide = Guide.find params[:guide_id]
#category = Category.find params[:category_id]
#key = #category.category_item_keys.find params[:id]
if #key.update key_params
redirect_to #guide, success: "Key Updated"
else
render 'edit'
end
end
private
def key_params
params.require(:category_item_key).permit(:key)
end
end
#app/views/keys/edit.html.erb
<% #keys.each do |key| %>
<%= form_for [#guide, #category, key] do |f| %>
<%= f.text_field :key %>
<%= f.submit %>
<% end %>
<% end %>
If you wanted to use an in-place editor gem, I'd recommend looking at X-Editable, as we've applied it here (its only a demo app, just sign up for free and go to profile):
Looks like you are trying to do update_attributes on a collection instead of an object. Try to first fetch the key object
#key = #category.category_item_keys.friendly.find(params[:id])
and then try to update its attributes
if #key.update_attributes(key_params)
...
end
use nested forms available in rails 4.

Rails: If my Quiz model should be created on completing the quiz, how does form_for know what to refer to?

I've been told that I should not create my Quiz object before my quiz is completed; A user could go to the quiz page, not complete it, and there would be an 'unused' quiz sitting on the database. I can see the logic of that.
I CAN'T see how my quiz is supposed to work without being passed a #quiz object. Here's my QuizzesController, which, when the quiz is needed, gets routed to the 'new' action:
class QuizzesController < ApplicationController
def index
end
def new
#user = current_user
#quiz = Quiz.create(user_id: current_user.id)
end
def create
#results = Quiz.where(user_id: current_user.id).last
redirect_to results_path
end
end
At the moment, you can see that I'm coding the actions as simply as possible. Later, in the 'new' action, I'll add a test to see if the current_user has done the quiz and, if so, redirect to results_path.
Here is my form partial which is rendered as part of quizzes/new.html.erb:
<%= form_for(#quiz) do |f| %>
<p>
<%= f.check_box(:answer1) %>
<%= f.check_box(:answer2) %>
<%= f.check_box(:answer3) %>
<%= f.check_box(:answer4) %>
<%= f.check_box(:answer5) %>
<%= f.check_box(:answer6) %>
<%= f.check_box(:answer7) %>
<%= f.check_box(:answer8) %>
</p>
<p>
<%= f.submit("Get my results!") %>
</p>
<% end %>
Once again, the quiz is very simple while I figure out what's going on.
But I'd like to know, if the #quiz object is not created in the 'new' action, what would I pass into form_for to build the form?
You can instantiate a Quiz object without saving it to the database:
def new
#user = current_user
#quiz = Quiz.new(user_id: current_user.id)
end
The generally used sequence of requests/actions is the following:
The new action just initializes the model's instance with default values, and renders the record with empty fields, usually in a edit view.
def new
#quiz = Quiz.new(user_id: current_user.id)
render :edit
end
create action create the record, and after the create action you should render either the view of the newly created record by redirection to show action with the same view, or to redirect to a new action, in case you are creating a sequence of the same instances of a model.
def create
#quiz = Quiz.create(params)
render :show # or redirect_to :new
end
edit action is to prepare edit fields, is it renders edit view with filled-in fields.
def edit
#quiz = Quiz.where(id: params[:id]).first
end
update action updates the record with values set in edit view, then it renders the show view on the current record.
def update
#quiz = Quiz.update(params)
render :show
end
show action just shows the model's found out with stored in the DB values, then it renders show view with filled-in fields.
def show
#quiz = Quiz.where(id: params[:id]).first
end
So in your show.erb view you get rendering the newly built, or found out instance of Quiz:
<%= form_for #quiz, url: {action: "create"} do |f| %>
<p>
<%= f.check_box(:answer1) %>
<%# ... %>
</p>
<p>
<%= f.submit "Create Quiz" %>
</p>
<% end %>
But I prefer simple-form gem:
<%= simple_form_for #quiz do |f| %>
<%= f.input :answer1, as: :boolean, checked_value: true, unchecked_value: false %>
<%= f.button :submit %>
<% end %>

Displaying models as a list of a particular attributes

I have a contacts model, with an attribute :area. I'd like to display one page (/listarea) as a list of all the areas. I have this part working
In contacts_controller.rb
def listarea
#listarea = Contact.order(:area).uniq.pluck(:area)
respond_to do |format|
format.html # index.html.erb
format.json { render json: #contacts }
end
end
And the listarea.html.erb
<table class="table table-striped table-hover">
<% #listarea.each do |area| %>
<tr class="tablerow">
<td><%= link_to area, :action => :areacontact, :area => area %></td>
</tr>
<% end %>
</table>
I'd like to be able to click on the area and lead to another page (areacontact) which will show a full list of all the contacts in that :area. This part is not working.
In contacts_controller.rb I have
def areacontacts
#contacts = Contact.order(:name).find_all_by_area(params[:area])
respond_to do |format|
format.html # index.html.erb
format.json { render json: #contacts }
end
end
And in areacontact.html.erb I have
<% #contacts.each do |contact| %>
Hello
<% end %>
The error when I view /areacontact is
ActionView::Template::Error (undefined method `each' for nil:NilClass):
Can anyone help?
Don't use <%= link_to area, :action => :areacontact, :area => area %> instead of use the path like areacontact_path check the proper path using rake routes. and
In the line #contacts = Contact.order(:name).find_all_by_area(params[:area]) seems like no attributes are passing properly pleas check what are the params you are getting in the action.
In your contacts_controller.rb, you need some tweaks when u have nothing to show in the view. I mean when your database contacts tables is empty.
So you can do like this in contacts_controller.rb
def areacontacts
#contacts = Contact.order(:name).find_all_by_area(params[:area]) rescue []
.....
...
end
You got error because of #contacts is not any result from your find_all_by_area query.
Also you can check nil in areacontact.html.erb before lopping #contacts like this:
<% if #contacts.present %>
<% #contacts.each do |contact| %>
Hello
<% end %>
<% end %>

problem with request.post

I have a controller that has the following index action :
def index
if request.post?
flash[:notice] = "Searching.."
redirect_to songs_path # where songs_path is this index page that i am on
end
end
in my application layout i have defined the flash section as such
<% if flash[:notice] %>
<div id='notice'><%= flash[:notice] %></div>
<% end %>
and on my pages_path i've got
<% form_for :search do |f| %>
<%= f.label :search_text %>
<%= f.text_field :search_text %>
<p>
<%= f.submit "Search" %>
</p>
<% end %>
The final result should be a search through a youtube api ( youtube-g) but now i would only wish to make that flash notification appear when i click on the "Search" button , and it doesn't .. any ideas why ?
index action ordinary is GET request. So, if in your routes.rb there is something like resources :searches then your code won't work.
try this:
def create
render :text => "Searching.."
end
because POST /searches will refer to create action
you should update your RESTful route to like this
resources :songs do
collection do
get 'search'
end
end
Then in your Controller
def search
# Perform Your search here like Youtube ..
flash[:notice] = "Searching.."
redirect_to songs_path # This should work now.
end

Resources