default URL for a model in rails? - ruby-on-rails

I have a class Post
I want the default URL of each posts to be http://domain.com/9383 instead of http://domain.com/posts/9383
I tried to fix it in the routes. I manage to accept domain.com/222 but if I use <%= url_for(#posts) %> I still get domain.com/posts/222
How can I do it? Thank you

You can't change the behaviour of url_for(#post) with routes. url_for will assume a map.resources setup if an ActiveRecord instance is passed to it.
You should rather do this:
# routes.rb
map.post ":id", :controller => "posts", :action => "show"
# named route
post_path(#post)
# full link_to
link_to #post.title, post_path(#post)

If you're using url_for, there's no way to tell it to omit the /posts/ section. I think you would need to create helper, maybe in application_helper.rb
def post_url(post)
"/#{post.id}"
end

Overriding url_for seems to not be considered a best practice in Rails, although it seems terribly convenient to me. Here's a description of how to do it by customizing ApplicationController: http://arjanvandergaag.nl/blog/generating-fancy-routes-with-rails.html

Related

how to route your sub-folder in views Ruby on Rails?

Can anyone please shed some light on how to route your sub-folder's .html.erb files?? which is placed like this:
view/pages/en/index.html.erb
and to route this i am doing following things on route.rb
match ':lang/index', :to => 'pages/en#index'
and for a link code, I have this on the header
<%= link_to "Home", index_path %>
The error i am getting is
Routing Error
uninitialized constant Pages
routes:
Namespaces will organize your code and views in subfolders: http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing
If just need only the views/pages folder organized that way, you could do in PagesController something like:
render "#{I18n.locale}/#{action_name}"
A question: why would you like view/pages/en/index.html.erb instead of view/pages/index.en.html.erb? That would work out of the box.
UPDATE
This is how it works for route.rb:-
match ':lang/index', :to => 'pages#index'
Render it on your controller:-
def index
render "pages/en/index"
end
def about
render "pages/#{params[:lang]}/about"
end
AFAIK, There is no way to route to a view. You can route an URL to a controller's action. That action is responsible for rendering the views.
you can use namespaced routing to put the resources in the sub folder.
...
What i wanted to write already written by #TuteC. Just follow that link and yes you can get language specific thing out of box as he explained.
I have been struggling with this for a while and finally figured out an easy solution:
config/routes.rb
get 'pages/:first/:second/:third' => 'pages#show'
Then in your PagesController
def show
render "/pages/#{params[:first]}/#{params[:second]/#{params[:third]}"
end
Then in your views it will render any of the following:
pages/index => pages/index.html.erb
pages/index/en => pages/index/en.html.erb
pages/foo/bar/hello-world => pages/foo/bar/hello_world.html.erb
The best thing about this is that it is simple and you can extend it indefinitely. Allows easy cleaning up of the views folders if all you are doing is rendering basic templates.

Rails: changing the default method called on the ActiveRecord::Base object by link_to

I have a gem which is essentially just a bunch of ActiveRecord::Base classes in the gems namespace. For all of them I get the same type of problem. I have the model...
module MyGem
class User < ActiveRecord::Base
...
end
end
Then in my app I have the routes...
resources :users
What gets screwed up is in the link_to...
<% #users.each do |user| %>
<td><%= link_to 'Show', user %></td>
<% end %>
I get...
undefined method `my_gem_user_path' for #<#<Class:0x0000000305f728>:0x00000003055408>
I've tried various things in routes.rb, but I'm thinking the solution may be to configure the model/link_to to call user_path(user) instead of my_gem_user_path(user) by default. I just don't know how, if at all possible, to do this.
Anybody know the best practice here?
I think the best practice here is to namespace your routes. Your class is namespaced as MyGem::User. #link_to uses #polymorphic_path to query the class for its class name and then calls #underscorize on that class name to get the path, so it assumes that the path will be my_gem_user_path, not user_path. That means the resources call should be wrapped like so:
namespace(:my_gem) do
resources :users
end
Then, my_gem_user_path will resolve to the MyGem::UsersController. Make sure your controller is namespaced like that as well. If you don't want the route to resolve to that controller, you can provide the controller name as an option to #resources.
edit: That's interesting, I didn't think it would run into that problem. There may still be some configuration to fix that, so I wouldn't mark this as solved yet. You can always replace the polymorphic_path (which is what is getting called when you use the resource-oriented path like above) with named routes. For example, instead of
link_to "User", user
you can always explicitly use
link_to "User", my_gem_user_path
When you use RESTful routes in your routes.rb file (with the #resources method), it provides you with those named routes.
For the form_for, the syntax is slightly different:
form_for(#user, #task)
becomes
form_for([#user, #task], :url => my_gem_user_my_gem_tasks_path(#user, #task), :method => :post)
for a new form. For an edit form, it would be
form_for(#task, :url => my_gem_user_my_gem_tasks_path(#user, #task), :method => :put)
Does that make sense? Here's a link to the documentation for form_for http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for

Destroy? Delete? What's going on here? Rails 2.3.5

I am new to rails. My rails version is 2.3.5. I found usage like:
In controller, a destroy method is defined and in view, you can use :action => "delete" to fire that method. Isn't the action name has to be the same as the method name? Why delete is mapped to destroy?
Again, in my controller, I define a method called destroy to delete a record. In a view, I have <%= link_to "remove", :action => 'destroy', :id => myrecord %>. But it never works in practice. Every time I press the remove link, it redirects me to the show view, showing the record's content. I am pretty sure that my destroy method is:
def destroy
#myobject = MyObject.find(params[:id])
#myobject.destroy
#redirect_to :action = 'index'
end
If I change the method name from destroy to something like remove_me and change the action name to remove_me in the view, everything works as expected.
In the above two weird problems, I am sure there is no tricky routing set in my configuration.
All in all, seems the destroy and delete are mysterious keywords in rails. Can anyone explain this to me?
You probably set MyObject as a resource in routes.rb. Resources get a couple of routes that don't directly match the name of the action. When you use an action name that does not match the routes defined by the resource, you'll get the default route which directly maps to the name of the action.
I found that this link explains rails' routing very well. Take a look at the "RESTful routing" section.
If you are using REST routing, destory only support delete method. you can change your code like this
link_to "remove", :action => 'destroy', :id => myrecord", :method => :delete
Adding :method => :delete
rails will add a hidden input with name "_method", value "delete"
Replace all :post => true with :method => :post

Pretty URL in Rails when linking

Let's say I have a Ruby on Rails blogging application with a Post model. By default you would be able to read posts by http://.../post/id. I've added a route
map.connect ':title', :controller => 'posts', :action => 'show'
that will accept http://.../title (titles are unique) and the controller will do a query for the title and display the page. However when I am now calling <%= link_to h(post.title), post %> in a view, Rails still gives me links of the type post/id.
Is it possible to get Rails to automatically create the pretty links for me in this case?
If you are willing to accept: http:/.../1234-title-text you can just do:
def to_param
[id, title.parameterize].join("-")
end
AR::Base.find ignores the bit after the id, so it "just works".
To make the /title go away, try naming your route:
map.post ':id', :controller => 'posts', :action => 'show', :conditions => {:id => /[0-9]+-.*/ }
Ensure this route appears after any map.resources :posts call.
You can override ActiveRecord's to_param method and make it return the title. By doing so, you don't need to make its own route for it. Just remember to URL encode it.
What might be a better solution is to take a look at what The Ruby Toolbox has to offer when it comes to permalinks. I think using one of these will be better than to fixing it yourself via to_param.
I would use a permalink database column, a route, and I normally skip using link_to in favor of faster html anchor tags.
Setting your route like:
map.connect '/post/:permalink', :controller => 'post', :action => 'show'
then in posts_controller's show:
link = params[:permalink]
#post = Post.find_by_permalink(link)
You link would then be
Link
then in your create method, before save, for generating the permalink
#post = Post.new(params[:post])
#post.permalink = #post.subject.parameterize
if #post.save
#ect
There is a Gem for you to get this done perfectly
https://github.com/rsl/stringex

rails routing controller action change

I'm struggling here with a problem:
I have a controller questions which has action new.
Whenever I need to create new question, I'm typing
/questions/new
What changes to routes.rb should I make to change the URI to
/questions/ask
Thank you.
Valve.
Try this:
map.ask_question '/questions/ask', :controller => 'questions', :action => 'new'
Then you'll have a named route and you can:
link_to "Ask a question", ask_question_path
If you are using RESTful routes maybe you'd like to use map.resources for your questions.
To rename the action urls you may do this:
map.resources :questions, :path_names => { :new => 'ask', :delete => 'withdraw' }
(I added delete for the sake of the example)
Which version of rails?
Generally the default route should catch anything like /:controller/:action, so you could just create an ask method in your questions controller. Take a look at the api documentation for named_route and map_resource if you want something a bit smoother to work with.

Resources