How to define a link path - ruby-on-rails

I'm trying to figure out how to make an app with Rails 4. I keep getting stuck on basic things and I don't seem to be able to identify principles to use going forward.
I have a profile model and a industry model. The associations are:
Profile:
has_and_belongs_to_many :industries, join_table: 'industries_profiles'
Industry:
has_and_belongs_to_many :profiles, join_table: 'industries_profiles'
In my profile show page, I'm now trying to link to the industry page:
<% #profile.industries.limit(5).each do |industry| %>
<%= link_to industry.sector.upcase, industry_path(#industry) %>
<% end %>
I can't find anything that works for this link.
I have tried the following:
industry_path(#profile.industry)
industry_path(#profile.industry_id)
industry_path(industry)
industry_path(profile.industry)
industry_path(industry.id)
industry_path(industry_id)
But all of them are guesses. I don't know how to ready the API dock so I can't understand any of its content.
Can anyone see how to link to a show page of the other side of the HABTM association for a single record?

You can grab a list of your routes by running rake routes | grep industry in your command line, which will give you a table with the prefix, action, and uri pattern. For example:
industries GET /industries(.:format) industries#index
POST /industries(.:format) industries#create
new_industry GET /industries/new(.:format) industries#new
edit_industry GET /industries/:id/edit(.:format) industries#edit
industry GET /industries/:id(.:format) industries#show
PATCH /industries/:id(.:format) industries#update
PUT /industries/:id(.:format) industries#update
DELETE /industries/:id(.:format) industries#destroy
In your case, you should look at the show path. Which is industry and you append _path to the end of whatever your prefix is above, which comes out to be industry_path. And since you have declared your variable industry when defining your loop, you can use that instead of the instance variable.
Short answer: industry_path(industry)

Related

In Rails, how do I write a link_to expression that results in a "/path/id" format?

This question is for Rails 5. I have a model
class Vote < ApplicationRecord
belongs_to :person
and then a config/routes.rb file that contains
resources :votes
The issue is I want to create a path
/vote/person_id
in which "person_id" is actually the ID of a person object and not a vote object. I thought I could write a "link_to" expression like the below to achieve this
<%= link_to person.name, votes_path(person), :class => 'unvotedPersonLink' %>
but instead what's happening is the link that's generated is
/votes.11
How do I adjust my "link_to" or routes file so taht I can generate a link in the format I want?
If you want to see all routes, you should run rails routes command. Your vote resource like the below:
votes_path returns /votes
new_vote_path returns /votes/new
edit_vote_path(:id) returns /votes/:id/edit
vote_path(:id) returns /votes/:id
You can see more info about Rails routes in the following link:
http://guides.rubyonrails.org/routing.html
this might solve the routing problem.
routes.rb
resources :votes, param: :person_id
view
votes_path(person_id: person.id)
In your views you need to pass person id as below:
votes_path(person: person)
Or like this:
votes_path(person, #vote)
Or :
votes_path(person: current_user)
Also, if you want to use the person id to add vote I would recommend you to inject the person id through controller using current_user

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

Combine 2 paths

I'm new to rails and i'm sure this is a simple question but I haven't been able to find it. I have a product model and a sku model. A product has_many skus. I have a route setup to use a path like this: /products/1/skus/3
What I'm trying to figure out is how to link to different skus from this view using a link_to method. e.g.: = link_to #product_path + #sku_path and have it come out to be <a href="/products/1/skus/2">
#product and #sku are variables from the controller.
I know I could use a join and pass in the id's etc. But I wasn't sure if there was a better way of doing it. Maybe use a helper?
Thanks!
Give that you have
#routes.rb
resources :products do
resources :skus
end
you should be able to do
product_sku_path(#product, #sku)
to get a given sku associated with a product, good luck :)

Nested Ressources in Ruby on Rails

It's actually supposed to be very trivial, but I'm experiencing strange issues.
I'm developing a Game Database, where Users can chart Game Entries and also write reviews to those reviews. Of course a Reviews URL (the show view) must be dependent of the game's id, like localhost:3000/games/1/reviews/2
So these are my routes
resources :games do
resources :reviews
end
And I want to open the show-view of a review with
<%= link_to "zum Review", game_review_path(#game, #review) %>
this is all basic tutorial stuff.
But I only recieve a Routing error. Trying instead this approach
url_for([#game, #review])
At least won't result in a routing error, but Not the reviews show-view is opened, but the game's show view, which is where this link is actually placed!
My models associations are set corretly and my controllers actions are all basic tutorial stuff. What am I doing wrong?
In your erb file try passing the local variable in the left argument and the name of the nested model in the field to the right. If you use 2 local variables you will get a routing error. #game is the local variable and review is nested under games so the below code should fix your issue.
Try:
<%= link_to "zum Review", game_review_path(#game, review) %>

Remove nested attribute rails

I have a Post model that
has_many photos
The Post model has
accepts_nested_attributes_for :photos
In my Post edit form i show all the images that are currently associated with the post
<% for photo in #post.photos %>
<%= image_tag(photo.avatar.url(:thumb)) %> <%= link_to "Remove Photo", post_photo_path(#post, photo), :method => :delete %>
<% end %>
When hovering over over the Remove Photo link the path looks like so
http://localhost:3000/posts/17/photos/45
I get uninitialized constant PhotosController, but that's expected as there isn't one.
My question is do i create one and have a destroy action in there that will just delete that photo.. Is this the way to go about it or is there a better way?
EDIT
Photos Controller
def destroy
#photo = Photo.find(params[:id])
#photo.destroy
redirect_to edit_post_path, :notice => "Successfully deleted Photo"
end
Routes
resources :posts do
resources :photos
resources :departments
end
Rake Routes
edit_post GET /posts/:id/edit(.:format)
Thanks
The option you described, invoking the destroy action of a PhotosController, would certainly do the trick and would probably be the simpler and quicker solution. Be careful that if a user makes changes to other aspects of the Post and then clicks a link to delete the Photo in the same form, their changes would probably get lost. However, using AJAX might help alleviate this concern.
Another option would be to leverage rails existing support for nested forms. Because you are already using a nested form with accepts_nested_attributes_for you're about halfway there. If you haven't seen this yet, check out Ryan Bates' podcast on Nested Forms:
http://railscasts.com/episodes/196-nested-model-form-part-1
http://railscasts.com/episodes/197-nested-model-form-part-2
And if you're willing to pay (trust me, it's worth it), the revised solution is a little nicer:
http://railscasts.com/episodes/196-nested-model-form-revised
The meat and potatoes of what you're interested in is towards the middle to the end of the podcast where Ryan uses the hidden _destroy field in the nested element's params to indicate to the controller than when the parent object is updated, the nested association should be destroyed.
You can also find an off the shelf gem that wraps up this same Rails/Javascript functionality that Ryan implemented from scratch. I've used cocoon in the past and have been quite pleased.
This technique is a little more complicated but I tend to prefer it in this case because the focus of the form is to modify a Post, not a Photo. In the first solution, you would have to make the PhotosController#destroy action redirect back to the form. Or if you use AJAX, then you would have to write javascript that was tailored to the layout of your Post HTML to properly hide/remove the element after it was destroyed. This may be ok for small applications, but as the project grows you may find yourself trying to use the same PhotosController for other work-flows and that could become brittle to maintain.
My opinion is that the best thing to do would be to create a PhotosController to handle the destroy action. That way you will preserve the Single Responsibility Principle, and have less workaround with adding custom routes.
Also, there is the option to put that one action in the PostsController if you are really sure you won't be adding any additional actions connected to Photos (like tagging photos, or whatever).
It's really up to you, but i believe the first one is easier.
If your going with the second option, be sure to create a route for the destroy photo action in the PostsController and the link should be pointing at that exact action.
Your routes.rb:
resources :posts do
resources :photos, :only => [:destroy]
resources :departments
end

Resources