Updating joined table associated with order... keeps creating instead of updating - ruby-on-rails

Situation:
An order is created by ordercontroller create method into a orders table.
Then a video is uploaded by videoordercontroller create method into the videoorder table associated with the order_id.
I have this in the orders show page to upload the video to the order:
<%= form_for([#order, #video_order]) do |form| %>
<%= form.file_field :video %>
<%= form.submit "Upload", class: "btn btn-success" %>
This form technically disapears after submission but i am testing updating the video because i also want to give the ability to update the video in case a wrong video is uploaded.
I tried:
<%= form_for([#order, #video_order], :url => edit_order_video_order_path(#order.id, #video_order), remote: true ) do |form| %>
<%= form.file_field :video %>
<%= form.submit "Upload", class: "btn btn-success" %>
But this gives me the
"(No route matches [POST] "/orders/150/video_orders/150/edit")"
Which, of course this wouldn't work but i also can't figure out how to allow to update the video tables order_id from the same URL page. I don't want to send the user to a new page for convenience.
So basically, how can i allow updating the orders video in the video table?
Here's the models:
video_order model
belongs_to :order
validates :order_id, uniqueness: true
order order model
has_one :video_order
The video_order model has the order_id and video only.
the order model doesn't have a video_id column.
Also, if you see any associations being wrong or have better ways, feel free to let me know.
Rake:
edit_order_video_order GET /orders/:order_id/video_orders/:id/edit(.:format) video_orders#edit
PATCH /orders/:order_id/video_orders/:id(.:format) video_orders#update
PUT /orders/:order_id/video_orders/:id(.:format) video_orders#update
This is taking place in the Order show page
I have this method in the order controller:
def show
#user = current_user
#video_order = VideoOrder.new
end
This where the uploading of the video takes place. i also want to allow updating from it with a seprate form

form_for method has a options parameter, you can set the form method as 'patch' as follows:
form_for #object, url: 'some_url', method: 'patch'

Looks like this works for updating the table and not creating a new row:
<%= form_for(#order.video_order) do |form| %>
Only issue I'm currently having is the redirect after. I get "Cannot redirect to nil!" but i will figure that out soon enough.
Redirect needed to be along the lines of this:
redirect_to order_path(#video_order.order_id)
In orde to redirect back to the order show page
This solution ended up being so simple! :)

Related

Creating a Model in Rails within the controller of a different Model

I'm trying to implement a quote saving feature in a Rails app. I have a User Model that has_many :quotes and a Quote Model that belongs_to :user. Now I have a separate Book Model that would be the source of these quotes.
Within the Book's show.html.erb file, I have a form to save quotes for the current user
<%= form_for (#new_quote) do |f| %>
<div class="field">
<%= f.hidden_field :book_id, :value => #new_comment.book_id %>
<%= f.text_field :body %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
And in the Book controller, I have
def show
#new_quote = current_user.quotes.create(book_id: params[:id])
end
The quote saves fine but the problem is, since I have this Quote creation statement in the show method, everytime I go to the show.html.erb page of my Book model, it creates a Quote with an empty body.
What can I do to solve this? I was thinking it probably would involve moving this Quote creation to the actual create method of the Quote controller but I don't know how to exactly pass the parameters through.
You could just build that quote, but not save it to the database. Then the user need to send the form to save that record. Just change your show method to:
def show
#new_quote = current_user.quotes.build(book_id: params[:id])
end

How to access a single, visible element from an array of objects being displayed by will_paginate?

I am working on a rails web app which manages students and courses. I have a courses controller which has the following index action:
def index
#courses = Course.paginate(:page => params[:page], :per_page => 1)
#courses.order(:startDate)
##thisCourse = Course.find(params[:page])
end
So pretty standard except for one thing - all the details of a single course are shown on one page and to show the details of the next course, you move to the next page of the pagination.
The problem is that in this index page showing the details of 1 course per pagination, I have a "Sign Up!" button which when pressed needs to create a a new record in the 'signups' db table which has the automated 'id' field and then the 'user_id' and the 'course_id' fields.
The 'user_id' is easy to find (current_user.id).
The 'course_id' is proving difficult. I imagine that pressing the Signup button should send the course_id to the signups_controller where a create function can do the work. But how can I get this exact course ID from the index page to the signups_controller's create action?
As you can see in the code I pasted from the courses_controller's index action,the '#thisCourse' variable has been commented out because I have found no way to define which course is currently being shown on the page.
The fields are rendered by the will_paginate Gem so I'm not sure how it's generating the fields but I was thinking that maybe I could create a named hidden field which includes the course_id and use that when the sign up button is pressed, however I'm not sure how to go about it.
Does anybody have any ideas?
Thanks!
Well, you can use show method (output one course) instead of index(output all courses) method, that will always get your course id through params.
Basically I changed my approach to the problem. I removed the button which was supposed to call the signups_controller and create the new record in the signups table. This button was replaced by adjusting the form_for helper so that it's submit button would send all the necessary data to the signups_controller (including the id value which was added to the form as a hidden field).
The form ended up looking like this:
<%= form_for course, :url => {:controller => "signups", :action => "create"}, :method => "post" do |f| %>
<%= hidden_field_tag :course_id, course.id %>
<%= f.label :"Course Title" %>
<%= f.text_field :courseTitle, class: 'form-control' %>
+ all fields included in the form....
<%= f.submit "Sign Up!", class: "btn btn-primary" %>
<% end %>
This parameter of form_for defines which controller and which action in that controller is the submission target:
:url => {:controller => "signups", :action => "create"}
and this parameter overwrites the default http action (default is PATCH but in this case I wanted to POST i.e. create a new entry in the signups table):
:method => "post"
I'm not sure if this is a very quick and dirty solution but technically it gets the necessary data to the correct destination controller.

Update two non-associated models with one submit button, using nested form

I have a User controller that possesses the two following records:
user.vehicles from VehiclesController
user.trip_distances from TripDistancesController
In the Vehicles view, I need to display and update both models (Vehicle and TripDistance)
I figured out that I need to use a nested form. However, I don't understand how to implement it since my #trip_distances record needs a loop in order to display all of its content.
First, I tried to put this in the Vehicle model, but since both are NOT linked, I wonder if this is correct:
accepts_nested_attributes_for :trip_distances, allow_destroy: true
Then, in the Vehicle view's _form file, during the edit action, I have:
<%= form_for(#vehicle) do |f| %>
I need to put my nested form inside it. Here's what I got so far:
<% #trip_distances.each do |t| %>
<%= f.fields_for t do |fields| %>
<div class="field">
<%= fields.text_field :id_contract %>
<%= fields.number_field :length %>
</div>
<% end %>
<% end -%>
My trip_distances records are correctly displayed, but the unique Submit button doesn't work anymore. I'd like to update both model while clicking on one button. What am I missing?
I was able to make it work by associating the two models. Then I use the following fields_for tag:
<%= f.fields_for :trip_distances do |builder| %>
My submit button is now working, but the :trip_distances fields are not updated, I don't know why.

Trying to fire an action in my controller when a selection in a drop down menu is made but getting a no route matches error

I'm building a web interface to accompany a mobile app I'm building. I have a drop down select menu that lists a bunch locations.
On selection of a location I want to make a call to a method in my controller and grab some destinations within the location that was selected (each location has several destinations).
I then would like to render my show template with these results allowing the user to select a destination and make a booking.
This is what I have so far:
My view with a list of resorts:
<%= form_tag :url => { :action => :show } do %>
<%= select_tag :resort , options_for_select(#resorts), :prompt => 'Select Resort', :onchange => 'submit()' %>
<% end %>
Controller:
class HomeController < ApplicationController
def index
#resorts = ["A","B", "C", "D", "E"]
end
def new
end
def edit
end
def create
end
def show
#activities = Parse::Query.new("Activity").tap do |a|
a.eq("resort", params[:resort])
end.get
end
end
Just slightly confused. Using form_for makes more sense to me with CRUD in mind and also because the form is object based.
I'd like to just take the selected resorted and pass it into a method in my controller that goes into a database and grabs a bunch of destinations. I then want to list these destinations on my show page where a user can click and be taken to another page where they can make a booking at that destination.
My above code doesn't work. I have resources :home in my routes file.
However when I try to load my page with the form I get:
No route matches {:action=>"show", :controller=>"home"} missing required keys: [:id]
How do I pull this off?
I went on my lynda account and pulled up a rails essential tutorial which I'll have to use to refresh my memory some time tomorrow but the tutor doesn't cover use of select_tag.
Would appreciate some help here
Thanks for your time
So a few thoughts. Not sure why you are using form_tag and also not sure why you aren't using Rails idiomatic conventions.
Declare a resource in your routes for #resorts, like so:
resources :resorts
Then just use Rails form_for helper like:
<%= form_for #resorts, url: {action: "create"}, html: {class: "nifty_form"} do |f| %>
<%= f.select :resort, (insert your other options) %>
<%= f.submit "Create" %>
<% end %>
I have not tested the above code, so play around with it, but that should work.
However, let me save you some headache. Checkout SimpleForm.
For your models, you would want to setup an association between your locations and destinations.
class Location < ActiveRecord::Base
belongs_to :resort # or whatever the relation is
has_many :destinations
end
class Destination < ActiveRecord::Base
belongs_to :location # This assumes there is just a one-to-many relationship between Location and Destination
end
Make sure you have a LocationsController with all the actions.
In this case, your SimpleForm form would look something like this:
<%= simple_form_for #locations do |f| %>
<%= f.input :name %>
<%= f.association :password %>
<%= f.button :submit %>
<% end %>
That approach will make your life much easier. Take a look at the collections methods in Simple Form. Rails can make your life difficult with the built in form helpers.
Hope that helps!
In your routes, add
get '/choose_resort' => 'home#show' #you can name the get whatever
Then in your form...
<%= form_tag choose_resort_path do %>
That being said... you should have your query at a separate endpoint, and redirect to the show page. That should get you moving, methinks.
The show action needs an id of the object you are showing. Change your controller:
class HomeController < ApplicationController
def index
#resorts = [["A",1], ["B",2], ["C",3], ["D",4], ["E",5] ]
end
And your view
<%= select_tag :id , options_for_select(#resorts), :prompt => 'Select Resort', :onchange => 'submit()' %>
That gives your show action the proper resort id. You'll have to adjust that action to find the right activities relevant to the resort.

How to select current model in a 3 model system?

I have 3 models. Users have multiple Portfolios and Portfolios have multiple Assets.
When a user signs in, that makes him a current_user by find_by_id. When they first register, it creates a portfolio for them. That becomes the current_portfolio.
Subsequent to this, they can create portfolios which redirects them to the list of all their portfolios. Clicking the link to each will make that portfolio the current_portfolio.
#current_portfolio = current_user.portfolios.find_by_id(params[:id])
The show view for portfolios has an assets form so that they can quickly add assets to the portfolio. This is where I get stuck. Because the assets form is on the portfolios show view, my Asset controller needs to reference current_portfolio, but this is in my Portfolio controller.
Portfolio Controller:
def show
#current_portfolio = current_user.portfolios.find_by_id(params[:id])
#asset = #current_portfolio.assets.build
end
When the form is submitted, it goes to my Assets controller Create function. Create can't simply have #current_portfolio because it's on a different controller. I also can't use find_by_id(params[:id]) because :id is not providing anything.
How do I reference the second model when I have 3 models? (Sorry I'm a newb to rails...)
EDIT Update: I thought I found the solution but realized it didn't work.
I passed <%= hidden_field_tag :portfolio_id, params[:id]%> in my form and set my Create in the Asset controller to be
def create
#asset = Asset.new(params[:asset])
#asset.save
end
but it's not getting the portfolio_id which is a required field in my model.
Full form in my view
<%= form_for(#asset) do |f| %>
<%= hidden_field_tag :portfolio_id, params[:id]%>
<%= f.text_field :asset_symbol %>
<%= f.text_field :shares %>
<%= f.text_field :cost %>
<%= f.text_field :purchase_date, :type=>'date' %>
<%= f.submit "+ Add to Portfolio" %>
<%end%>
My guess would be that the portfolio_id in the hidden field isn't coming back as part of the asset hash. Maybe it's as simple as assigning the #asset.portfolio_id = params[:portfolio_id] before the save. Check you logs to see EXACTLY what is coming back in the POST

Resources