Combine 2 paths - ruby-on-rails

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 :)

Related

How to define a link path

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)

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

Correct method for custom Rails routing

In my routes I currently have resources :users and so I get the routes such as /users/id/ and /users/id/edit and so on...however, I am wanting to have the 'default' URLs for my pages begin with /name where name is the user's unique login name.
So, right now my routes file looks like this.
resources :users
match '/:name' => 'users#show_by_name'
Then in my users_controller.rb file, I have methods defined as such...
def show_by_name
#user = User.find_by_name(params[:name])
render 'show'
end
So, basically it is doing the same thing as def show but instead of an id being passed in the URL, it's a name.
In my views I am linking like this...
<li><%= link_to "My Profile", "/#{current_user.name}" %></li>
As opposed to using <li><%= link_to "My Profile", current_user %></li>
I am wondering if I am going about this the correct way. I feel like I am doing something unnecessary by using extra methods in my users_controller.
Would I be better off just removing the resources :users line and creating my own routes that are more suited towards the type of URLs I want on my application?
Thanks for your time.
You might be better off overriding the to_param method in your User model. Rails has in built function for search friendly URL's
class User < ActiveRecord::Base
def to_param
"#{user.name}"
end
end
Url's will generate as
user_url(#user)
#http://0.0.0.0:3000/users/andrew
# Controller
#user = User.find_by_name(params[:id])
I would advice you to use FriendlyID, it's a neat gem that translates the :id to a value based on one of the table's columns. This could be a title for instance or name in your case.
I found it fairly easy to start using.
Ryan Bates talks about it in this screencast: http://railscasts.com/episodes/314-pretty-urls-with-friendlyid
For installation look here: https://github.com/norman/friendly_id
Both Andrew and Martin are right (the FriendlyID gem actually uses the to_param override method), but you're asking two questions :
can I use another attribute instead of the default id as the id in the route ?
can I use a non-resourceful route ?
In both cases, the answer is yes. You may override the to_param method AND use a non-REST route such as :
match '/:id' => 'users#show'

How to pass a param from one view to another in Ruby on Rails, using POST

I feel like this should be an easy thing to figure out, but I'm stumped.
I have a value in a Project's instance variable called ID. I want to pass that value to a new Photos page to associate each photo that is created with that specific project, but I don't want the Project's ID to show up in the visible query string.
I've tried using link_to and button_to, but (I suspect) since I'm using "resources :photos" in my routes, all of the requests that come to photo#new are being interpreted as GET instead of POST.
Helllllllllllllllp!
Thanks to anyone that can give me some insight, I'v been killing myself over this for the past hour or two already.
--Mark
The usual way to do this in Rails is to create a route that matches urls like this: /projects/4/photos/new. Doing something else is up to you, but Rails makes it really easy to do stuff like this. See more on routes in Rails 3.
Your entry in routes.rb should look something like this:
resources :projects do
resources :photos
end
Then in app/controllers/photos_controller.rb you'd have this for the "New Photo" form page:
def new
#project = Project.find_by_id(params[:project_id])
end
and this for the action that the form in app/views/photos/new.html.erb submits to:
def create
#project = Project.find_by_id(params[:project_id])
#photo = #project.photos.create(params[:photo])
end
Of course you'll want to have error handling and validation in here, but this is the gist of it. And remember, use GET for idempotent (non state-changing) actions (e.g. GET /projects/4/photos), POST for creating a new thing (e.g. POST /projects/4/photos), and PUT for updating an existing thing (e.g. PUT /projects/4/photos/8).

Customizing map.resources in Rails

Suppose I have a Book model, which contains many Page models.
The routing for this would be as so:
map.resources :books do |book|
book.resources :pages
end
Following the Rails default on this quickly leads to problems. Suppose Book #1 has 10 pages. The first Page in Book #2 will have this route:
/books/2/pages/11
This is a pretty bad route, what would make more sense is this:
/books/2/pages/1
Or even this:
/books/2/1
Is there a way to still use map.resources, but get a result like this:
/books/{book.id}/pages/{page.page_number}
No. You have to use custom routing for that.
Feel free to get inspiration from http://github.com/augustl/kii/blob/master/config/routes.rb
As August says you need to use custom routing for that.
But for the pages, you don't need the full resources routes. Only show will be necessary.
So something like :
map.resources :books do |book|
book.page ':page_id', :action => 'index'
end
Will map the default books url for displaying the index, one book and adding/editing them.
But also a page
/books/{book.id}/{page_id}
Which maps to the index action with the parameter "page_id". You only have to display the appropriate books page ;)
You could also try the shallow-option for your routing!

Resources