Couldn't find Movie without an ID - ruby-on-rails

App has 2 simple models and I use TMDb api. Movie & MovieReviews. When I try to to visit this URL
localhost:3000/movies/%23<Tmdb::Movie:0x007ff0608f4398>/movie_reviews/new
where I should see the form for submitting reviews, I get the error. Also, the url seems kinda bad. How can I get the movie id? It also shows
parameters:
{"movie_id"=>"#<Tmdb::Movie:0x007ff0608f4398>"}
and this is MovieReviewsController#new
def new
#movie = Movie.find(params[:id])
#movie_review = #movie.movie_reviews.new
end
Source code

Please replace
<%= link_to "Review it!", new_movie_movie_review_path(#movie) %>
By
<%= link_to "Review it!", new_movie_movie_review_path(#movie.id) %>
Problem is you do not reference movie id but movie object. This is why you have your strange URL parameter.
Once changed, you will have to adapt your MovieReviewsController.
But please be careful, I see you are trying to use "movie review". When I look at link you provided about Tmdb API, I can read " Missing Resources: Review ".

I think you have several issues:
localhost:3000/movies/%23<Tmdb::Movie:0x007ff0608f4398>/movie_reviews/new this will never work. Tmdb::Movie:0x007ff0608f4398 is the internal object id of the class instance. The url should look like localhost:3000/movies/1/movie_reviews/new. This will allow you to add a new review to the movie with id: 1
In your config/routes.rb file you have declared several urls explicitly and added the root route above other resources. The root route should always be the last declared route. Also get "movies/show" and get "movies/index" routes are already handled by resources :movies so you can remove those.
Routes file should look like this:
SampleMovies::Application.routes.draw do
resources :movie_reviews
resources :movies do
resources :movie_reviews
end
root 'movies#index'
end
To see all avalaible routes for your application. Go to the project directory and type: rake routes It will show all available urls included required and optional parameters.
PS looking at the rest of your code, I strongly advice you to have a look at: http://guides.rubyonrails.org/getting_started.html its a most excellent tutorial on the basics of rails.

Related

Can I have several New methods in a rails controller on Rails 5.2?

My application has several ways to create notifications:
A user can create a notification using the standard "new" method
A link in a view can create a notification from an action using a dedicated "new_action"
etc.
So I created additional route and views for the new_action_notification_path:
resources :notifications do
member do
get :new_action
end
collection do
get :index_all
end
end
In the controller
# GET /notifications/new_action
def new_action
#playground = Playground.find(current_playground)
#notification = #playground.notifications.build( playground_id: params[:playground_id], …
And in the view:
<%= link_to t('Reject'), new_action_notification_path(
playground_id: current_playground,
description: t("#{this_object.class.name}#{'Rejected'}"),
But this does not behave as expected:
If I write new_action_notification_path in the view, as above, the generated URL looks like /notification/729/new_action?code=QWSTZ ...
If I write new_notification_path in the same place, the generated URL looks like /notification/new?code=QWSTZ ...
Why is it different, and how can I remove the notification id from the first URL?
Thanks a lot!
The reason your url's are different is because you have a nested route for the new_action.
resources :notifications do
member do
get :new_action
end
end
With a nested route, you are going to get an id number between your resources. The 729 is the id you are passing in to the link_to helper. The other route helper, new_notification_path, is creating a new notification, so it doesn't need an id. If you look at your routes, with rails routes in your console or localhost:3000/rails/info/routes in your browser, you'll see that the new_action needs an id.
new_action_notification_path GET /notifications/:id/new_action
new_notification_path GET /notifications
The :id part of the route is a placeholder for an id number (although it can be anything you pass in, really) to look up the resource before it. In this case, the id is use to look up the notification.

Including attributes in custom Rails routes

I hope the title is not to misleading, as I don't know a better title for the problem I'm working on:
I have a doctor which belongs to location and specialty. I'd like to route to show action of the doc controller like this:
/dentist/berlin/7
I defined my routes like this:
get ':specialty/:location/:id', to: 'docs#show'
And in my views create the following url to link to the show action of the doc controller:
<%= link_to doc.name, "#{doc.specialty.name}/#{doc.location.name}/#{doc.id}" %>
Is this a good solution to the problem? If not, is there a cleaner way to construct urls like this possibly using resources? What the heck is the name for a this problem?
Thank your very much for your help in advance.
For references, you should have a look at this page (especially the end of section 2.6)
If it is only for a single route, it's okay as you did. But then if you want to have more than one route (like /dentist/berlin/7, /dentist/berlin/7/make_appointment, etc.) you might want to structure a bit more your routes so as to take advantage of rails resources.
For example, instead of
get ':specialty/:location/:id', to: 'doctors#show'
get ':specialty/:location/:id/appointment', to: 'doctors#new_appointment'
post ':specialty/:location/:id/appointment', to: 'doctors#post_appointment'
You could have something like this (the code is almost equivalent, see explanation below)
resources :doctors, path: '/:specialty/:location', only: [:show] do
member do
get 'new_appointment'
post 'create_appointment'
end
end
Explanation
resources will generate the RESTful routes (index, show, edit, new, create, destroy) for the specified controller (doctors_controller I assume)
The 'only' means you don't want to add all the RESTful routes, just the ones specified
Then you want to add member actions, ie. actions that can be executed on a particular item of the collection. You can chose different syntaxes
resources :doctors do
member do
# Everything here will have the prefix /:id so the action applies to a particular item
end
end
# OR
resources :doctors do
get 'new_appointement', on: :member
end
By default, the controller action is the same as the path name you give, but you can also override it
member do
get 'appointment', action: 'new_appointment'
post 'appointment', action: 'post_appointment'
end
Rails has some wonderful helpers when it comes to routing !
The correct approach is to give your route a name, like this:
get ':specialty/:location/:id', to: 'docs#show', as: 'docs_show'
Then you can use it like this:
<%= link_to doc.name, docs_show_path(doc.specialty.name, doc.location.name, doc.id) %>
Note 1:
Rails appends _path at the end of the route names you define.
Note 2:
You can see all the available named routes by executing rake routes.

Why ruby on rails link_to redirect to itself?

Lets say I have a controler test.
In test I define 3 actions:
def zah
end
def zeh
end
def zih
end
I have the views:
zah.html.erb
zeh.html.erb
zih.html.erb
and under routes.rb I have:
get 'test/zah'
get 'test/zeh'
get 'test/zih'
If I write under zah.html.erb, using code automaticaly created from rubymine IDE, this:
<%= link_to test_zeh_path%>
I will get my page source code with this:
http://localhost:3000/test/zeh
which makes the redirection from zah be itself.
running rake routes returns this:
Prefix Verb URI Pattern Controller#Action
test_zah GET /test/zah(.:format) test#zah
test_zeh GET /test/zeh(.:format) test#zeh
test_zih GET /test/zih(.:format) test#zih
Can anyone explain to me why is the link going to itself (from zah to zah) instead of another page(from zah to zeh)?
Edit:
I have found out that adding a name to a link makes the generated code works right:
<%= link_to 'zeh', test_zeh_path%>
I have seen the first usage (link_to test_zeh_path) here at 22:45.
Ruby on rails api does says that if nil name is passed then "the value of the link itself will become the name.".
As for a mistake of myself I was wondering why Dave Jones was able to create a link without a name, but he wasnt and that can be seen on his source code.
Because you have written the url in the display part.
You can simply do
<%= link_to 'Goto Zeh', test_zeh_path %>
and you will be good to go.

Polymorphic Routes in Rails 4.1.4

I have a polymorphic association between Posts and Postables, right now with Projects being my only Postables. In my routes, I have:
resources :projects do
...
member do
resources :posts
end
end
I know how to retrieve the right ids from the parameters, and all of my controller specs pass just fine, but when I try to write links in my views, they don't work. Running rake routes, I see a little weirdness:
...
post SHOW /projects/:id/posts/:id(.:format) posts#edit
...
And so on for the rest. If I'm not mistaken, the path should be 'new_project_post', and the first parameter should be :project_id.
Now, in my show view for Projects, I have the index of posts for that particular project. But the links don't work. Lets assume I have a project with an ID of 2, and a post for that project with an ID of 1.
If I try link_to 'Edit', edit_post_path(#project, post), the link comes out as .../projects/1/posts/1/edit, so both :ids get the post's id. If I swap post and #project, both :ids will be the project's id.
If I try passing them as an array, link_to 'Edit', post_path([post, #project]), the resulting link will be .../projects/1%2F2/posts/1%2F2/edit. %2F is a URL-encoded slash character, so I'm not sure what the hell Rails is trying to do here.
If I try using polymorphic_path([#project, post]) for my links, all it does is spit out paths that don't exist: undefined method 'project_post_path'
I've tried several other combinations of parameters without success. So if anyone could point me in the right direction, I'd be extremely grateful.
The appropriate syntax for nested resources in Rails is:
resources :projects do
resources :posts
end
In member block you could only declare additional actions to work with project instances.
You are using nested resource inside member and it is incorrect. Read more about this here: http://thelazylog.com/posts/polymorphic-routes-in-rails

Set Up Route for Accessing Private S3 Content

I've been following
https://github.com/thoughtbot/paperclip/wiki/Restricting-Access-to-Objects-Stored-on-Amazon-S3
and
Rails 3, paperclip + S3 - Howto Store for an Instance and Protect Access to try and get Paperclip's expiring links to work. I believe most of what I'm running into is one of the routing variety.
In my pieces_controller I put a method in like this
def download
redirect_to #asset.asset.expiring_url(1000)
end
And then in my routes, I put this:
match "pieces/download"
Then in my view I have:
<%= link_to download_asset_path(piece)%>
It would seem to be far from working, and I'm not sure what is messed up. I know I'm getting routing errors for one, but it's also telling me that my download_asset_path is undefined, which is likely also routing related... I feel like I'm doing everything all wrong.
Tearing my hair out. Thanks!
Try modifying your routes file to:
match 'pieces/download' => 'pieces#download', :as => 'download_asset'
Your match needs to tell which controller#action to go to, and the as option will allow you to name the route download_asset_path.
If your pieces controller is for a Piece resource it could be cleaner like:
resources :pieces do
member do
get :download
end
end
But then you would want to change the link to:
link_to 'Link text', download_piece_path(piece)
For further reading: http://guides.rubyonrails.org/routing.html

Resources