nested routes in rails linking to wrong model - ruby-on-rails

If my route looks like this
get 'users/:id/doc/:id', to: 'users/docs#show', as: :show_doc
and if my show controller action looks like this
def show
user = User.find(params[:id]) #in this case it should be user id 6
doc = Doc.find(params[:doc_id]) #in this case it should be doc id 29
end
and if the link in the index view looks like this
<% user.docs.each do |i| %>
<%= link_to "#{i.id}", show_doc_path(user.id, i.id), target: :_blank %>
<% end %>
why does the link go to localhost:3000/users/29/doc/29?

The issue is that the route definition uses the same key (id) for both user id and document id. Use doc_id for document id and you should be good to go.
get 'users/:id/doc/:doc_id', to: 'users/docs#show', as: :show_doc

Related

Linking to the latest post from home page in a Rails application

I'm building a Rails app where I have individual entries called films. I would like to display the latest entry's link on the homepage (separate controller) and I'm struggling to make it work.
My films_controller.rb is as follows (excerpt):
def show
#film = Film.find(params[:id])
end
My home_controller.rb only has the following:
def index
end
And my view file (index.html.erb) has the following:
<%= link_to #film.last.filmTitle, film_path(#film) %>
I'm getting the following error:
Couldn't find Film with 'id'=#<Film::ActiveRecord_Relation:0x007fc93f2d1fd0>
With the #film.find(params[:id]) highlighted.
Thanks!
The last method:
Find the last record (or last N records if a parameter is supplied). If no order is defined it will order by primary key.
source
You can add a #last_film instance variable in your index controller and use it in the view.
def index
#films = Film.all
#last_film = Film.last
end
and in your index.html.erb
<%= link_to #last_film.filmTitle, film_path(#last_film) %>
The index method need something, currently, it didn't connect with ActiveRecord like model or table, that's why
Couldn't find Film with 'id'=#<Film::ActiveRecord_Relation:0x007fc93f2d1fd0>
So if you need to show recent posts in the index then you could something like this
def index
#films = Film.limit(10).order(created_at: :desc) #=> or you can use id
end
it will show last 10 records, for this in the index.html.erb like this
<% #films.each do |film| %>
<%= link_to film.filmTitle, film_path(film) %>
<% end %>
In the other hand if you need to show only one post which is the last then you should modify this query like this like limit(10) to limit(1) or you can use use the last method like this
def index
#film = Film.last
#or
##films = Film.limit(1).order(created_at: :desc) #=> or you can use id
end
if you use this #film = Film.last then your index file will like this
<%= link_to #film.filmTitle, film_path(#film) %>
otherwise, you need to use each method which describes before.

Rails URL helper for sorting filters

I have a table Companies with field city_id. I need in sorting companies by cities. I do next:
# companies_controller.rb
def sort_by_city
#cities = City.joins(:company).uniq
#companies = Company.where("city_id = ?", params[:city_id])
render 'index'
end
# routes.rb:
get '/companies/city/:city_id', to: 'companies#sort_by_city'
and in index.html.erb I try make links for this filter:
<% #cities.each do |city| %>
<li><%= link_to city.name, UNKNOWN_path(city.id) %> (<%= city.companies_count %>)
<% end %>
I want links like this: "www.site.com/companies/city/23"
What I must write instead of UNKNOWN_path? Or I do something wrong before (in controller or in routes.rb)?
You can give a name to your route with the as option :
For example :
get '/companies/city/:city_id', to: 'companies#sort_by_city', as: 'companies_city_sort'
And then use
companies_city_sort_path
Also, have a look at resourceful routing, it may be more adapted.
If you type rake routes in your terminal you can find the name of the current path.
Just look for the line where companies#sort_by_city is listed.

Rails 3: how to code a route path

I'm creating a rails app and I can't figure out or find answer for this problem.
What is the route for:
#example = Example.find_by_notId(params[:notId])
I want my route to look better then /example/1 and would rather have it read /notId (where notId would be title or some other non-ID int). Normally I would use show_path but in my html <%= link_to image_tag(pic), show_path(example) %> doesn't work. Here is my code and it works when I hard code it into the URL (localhost:3000/notId) but I need a way to route it through a link. Any ideas?
Show
def show
#example = Example.find_by_title(params[:title])
end
Routes
match '/:notId', to: 'example#show', via: 'get'
_example.html.erb
<div class="example">
<% Movie.all.each do |example| %>
<%pic = example.title + ".jpg"%>
<%= link_to image_tag(pic), show_path(example) %>
<% end %>
e</div>
You probably need to override the :id param in your routes:
resources :examples, param: :title
This will generate routes like:
/examples/:title
/examples/:title/edit
Then in your views:
example_path(example.title)
Alternatively, you can change the method to_param(used for building urls) in your model:
class Example < ActiveRecord::Base
def to_param
title
end
end
This allows you to keep using example_path(example) (without .title)

Render a rails partial based on the id of an action

I'm building a small ecommerce site that sells a variety of mens and womens clothing. i would like to render a partial based on which taxonomy the user is in. For example, if the user is at mysite.com/t/women/pants I would like to render _women.html.erb, or, if the user is at mysite.com/t/men/shirts I would like to render _men.html.erb.
I have a Taxonomy model that has_many taxons, and the Taxon model has_many products.
In taxons_controller.rb I have:
def show
#taxon = Taxon.find_by_permalink(params[:id])
return unless #taxon
#taxonomy = Spree::Taxonomy.all
#taxon_title = Spree::Taxon.all
#searcher = Spree::Config.searcher_class.new(params.merge(:taxon => #taxon.id))
#searcher.current_user = try_spree_current_user
#searcher.current_currency = current_currency
#products = #searcher.retrieve_products
respond_with(#taxon)
end
And in taxons#show I have: (which I know is wrong)
<% #taxon_title.each do |title| %>
<% #taxonomy.each do |taxonomy| %>
<% if title.name == taxonomy.name %>
<%= render "spree/shared/#{title.name.downcase}" %>
<% end %>
<% end %>
<% end %>
When I go to mysite.com/t/women/long-sleeve the rails debugger displays :
controller: spree/taxons
action: show
id: women/long-sleeve
How do I access the id of the action im inside, so that in the controller/view I can do something like:
'if id equals 'women' render "spree/shared/#{title.name.downcase}"'
where title is the name of the taxonomy?
I imagine I need to find(params[:something] in the show action of the controller, but I'm a little unclear about params.
*
*
*
#beck03076 That's a great trick. Thank you very much. But it's still not working.
In my controller I put:
#taxon_id = Spree::Taxon.find(params[:id])
Then in the action I put:
render 'spree/shared/women' if #taxon_id == params[:id]
And when I load the page it says 'the page you were looking for doesn't exist'. My partial is in the correct directory. Is my syntax correct?
My params are:
{"controller"=>"spree/taxons", "action"=>"show", "id"=>"women/long-sleeve"}
Thanks again for your help!
Whenever you are unclear about params, just put the lines below in the action and execute the action.
p "****************************"
p params
p "****************************"
Now, goto the terminal in which you started your server.
Locate those two "*******" and everything thats in between them are params.
params is basically a ruby hash.
example:
params look like this, {:controller => "hello",:action => "bye", :id => 7, :others => "OK"}
In your controller to access the id, use params[:id].(=7)
to access others, use params[:others].(="OK")

how to connect my model to my app

Hey all,(im a beginner in rails)
i've created a controller that look like that:
class HomeController < ApplicationController
def homepage
end
def showmsg
#postword = params[:p]
end
end
the showmsg view looks like that:
<%= #postword %>
and my homepage view looks like that:
<%= form_tag( {:controller => 'home', :action => 'showmsg'}, :method => "post") do %>
<%= text_field_tag(:p,#postword) %>
<%= submit_tag("post") %>
<% end %>
now i have a form that i can write something in it and it will show on the showmsg view.
i created a model with the param :posts with a :description "text" field too.
MY QUESTION is how do i implement the model in the code so any thing i write will be in a list with the things i wrote before, because now (obviously) anything if i write something its deleting the one i wrote before.
thank you all!
I would argue that you're approach is not very rail's like... so if you're learning rails... you're learning it wrong.
Make a Model. Call it "Message":
rails generate model Message content:string
remember to migrate (hopefully you have your databases setup properly):
rake db:migrate
Then in your controller, when you post, you can create message like this:
def create #instead of showmsg... 'create' is the standard name for this
Message.create(params[:message])
#messages = Message.all
end
This will create the message in the database, and then it will get all the messages out of the database and put them into #messages.
You need to edit your form so that it uses form_for. You need to pass it #message, which is an instance of Message.new that your first controller action created. You should call this new
In your create.erb.html file, you show all the messages like this:
<ul>
<% #messages.each do |message| %>
<li><%= message.content %></li>
<% end %>
</ul>
I actually wouldn't recommend showing all the messages in the create action - it should really happen in the index action and you should redirect... but we need to keep this simple. Just google this or watch some of Ryan's screencasts and you'll get it.
And you're done. This is the "Rails Way" to do things. It's best to learn it the way they want you to learn it.
I would also commend that you format your code properly by indenting, and start naming your methods to be real english. For example, showmsg is bad and show_message is a lot better.
If all of this is totally confusing, then just create a new project, and then type:
rails generate scaffold message content:string
It will basically build the application you want and a lot more. You can just read the code and see how they did it.
Hope it helps.
Your approach is not really rails like so some tweaks and fixes are needed. Suggestions: check rails approach to REST. The following code will work it is a little more rails like, but still not all the way there.
Generate a model
rails generate model Message postword:string
this will generate the model and create the migration necessary to create the table in the database.
Create the table
rake db:migrate
Define a post action
It will save the postword in the database. In your controller:
def create
#message = Message.create!(params[:message])
if #message.save
redirect_to "/home/showmsg"
else
render :action => "/home/homepage"
end
end
Create and instance of Message to use in your form
def homepage
#message = Message.new
end
Fix your form tag
<%= form_for #message, :url => "/home/create" do |f| %>
<%= f.label :postword %>
<%= f.text_field :postword %>
<%= f.submit "Create" %>
<% end %>
Now let's show the words in the showmsg page
In the controller select the postwords from the database:
def showmsg
#postwords = Message.all
end
Showing them: /showmsg.html.erb
<H1>postwords list</H1>
<ul>
<% #postwords.each do |p| %>
<li><%= p.postword %></li>
<% end %>
</ul>
Your routes.rb file will have this routes:
get "home/homepage"
get "home/showmsg"
post "home/create"
Define an attribute :new_text in a way similar to this:
class TheModel
# Virtual writer - everything assigned to this attribute
# will be added to self.text
#
def new_text=(v)
self.text += v.to_s
end
def new_text
"" # This is write-only attribute
end
end
Now, use the field 'new_text' in your form.
Of course, this is a very simple example. You should decide whether you want to add the content on every call to :new_text=, maybe some validation would help, the read accessor may need some care, and so on.
For some good guides which may help you start, see the site http://guides.rubyonrails.org/

Resources