Rails reverse autolink - ruby-on-rails

I have the following code in my Rails app:
link_to('???',{:controller => 'profile', :action => 'show', :id => id})
I want to get rid of '???' and it to show the dynamically generated URL. How do I this? It's kind of like what the autolink gem does, but I want Rails to convert URL options into text, not vice versa.

link_to(nil,{:controller => 'profile', :action => 'show', :id => id})
From the link_to documentation:
If nil is passed as the name the value of the link itself will become the name

Use url_for() to get the string.
url_for({:controller => 'profile', :action => 'show', :id => id)}
In the code:
url_hash = {:controller => 'profile', :action => 'show', :id => id}
link_to(url_for(url_hash), url_hash)
See this question to also get the host name:
url_hash = {:controller => 'profile', :action => 'show', :id => id}
link_to("#{request.host_with_port}#{url_for(url_hash)}", url_hash)

Related

How to routes to a specific controller with a variable value ahead of it in rails 5?

Normally its like:
resources :users
To keep a value ahead we can do like
scope :url do
resources :users
end
but, issue is that I have the just variable in front of the routes not a fixed value with few conditions for it.
Example in rails 2. and want to convert the routing accoding to rails5
map.with_options :controller => 'users' do |user|
user.forgot_user ':url/users/forgot', :action => 'forgot', :url => /([a-zA-Z0-9\-]*)/
user.user ':url/users/retrieve', :action => 'retrieve', :url => /([a-zA-Z0-9\-]*)/
user.login ':url/users/login', :action => 'login', :url => /([a-zA-Z0-9\-]*)/
user.logout ':url/users/logout', :action => 'logout', :url => /([a-zA-Z0-9\-]*)/
user.new_user ':url/users/new', :action => 'new', :conditions => { :method => :get }, :url => /([a-zA-Z0-9\-]*)/
user.users ':url/users/:id', :action => 'show', :conditions => { :method => :get }, :url => /([a-zA-Z0-9\-]*)/
end
Thanks in advance.
scope "/(:subdomain)", :defaults => {:subdomain => "default"} do
...
end
use subdomain as a variable.

Disable enforce utf8 in a redmine form

I have a redmine installation running fine. I have an issue to disable the utf-8 enforcement tag when doing searches. This is because on my network there is a url policy check that will prevent me from opening the url containing the utf-8 enforcement parameter.
So I went to /usr/share/redmine/app/views/issues/index.html.erb and changed this line:
<%= form_tag({ :controller => 'issues', :action => 'index', :project_id => #project },
:method => :get, :id => 'query_form') do %>
to this
<%= form_tag({ :controller => 'issues', :action => 'index', :project_id => #project },
:method => :get, :id => 'query_form', :enforce_utf8 => false) do %>
but the utf8 enforcement parameter shows up
What am I doing wrong? Can I disable it on a global base?

How to use link_to so that all parameters passed to controller are preserved in Ruby on Rails 2?

I have a bilingual site with nice URLs for SEO. Using Ruby on Rails 2.3.10.
routes.rb fragment:
map.connect 'order-jira-hosting/:option.html',
:controller => 'order', :action => 'index', :locale => 'en'
map.connect 'order-jira-with-greenhopper-hosting/:option.html',
:controller => 'order', :action => 'index', :locale => 'en', :greenhopper => true
map.connect 'zamow-hosting-jira/:option.html',
:controller => 'order', :action => 'index', :locale => 'pl'
map.connect 'zamow-hosting-jira-z-greenhopper/:option.html',
:controller => 'order', :action => 'index', :locale => 'pl', :greenhopper => true
As you can see, :locale and :greenhopper are "hidden" in the URL.
There is a switch so that you can change the language of the current page. See my views/layouts/default.erb:
<%= link_to image_tag('icons/polish.png', :alt => 'polski'), { :locale => 'pl'}, :class => 'a' %>
<%= link_to image_tag('icons/english.png', :alt => 'English'), { :locale => 'en'}, :class => 'a' %>
I simply don't specify a controller and action so that I am redirected to the current controller and action with different locale. Unfortunately, :greenhopper parameter gets lost.
I am at /order-jira-with-greenhopper-hosting/11.html
(:option => 11, :locale => 'en', :greenhopper => true)
Generated links for switching languages are /order-jira-hosting/11.html and /zamow-hosting-jira/11.html
(:option => 11, :locale => 'pl' and 'en', :greenhopper => false)...
...But they should be /order-jira-with-greenhopper-hosting/11.html and /zamow-hosting-jira-z-greenhopper/11.html
(:option => 11, :locale => 'pl' and 'en', :greenhopper => true)
How to use link_to method so that all parameters passed to controller are preserved? Thanks for your help.
You can base the hash you send to link_to off the params hash, which, if you passed it into link_to as-is, would reload the current page. You can use Hash.merge(other_hash) to reset the :locale key for each link:
<%= link_to '<polish image />', params.merge({:locale => 'pl'}), :class => 'a' %>
Now, params does contain controller and action keys, but they're the controller and action that generated the current page, so the link should behave just like a page refresh, with only the parameters you changed via params.merge changing.
Hope this helps!
PS: params.merge doesn't change the params hash, if you're concerned about that - the result of the merge is returned as a new hash.

Rails: Mapping Conflicting Routes by Detecting Param

Hey! I am trying to set up routes in a Rails application so that, depending on the type of parameter passed, Rails sends the request to a different action.
I have courses which have an attribute state which is a string with a two letter state abbreviation. When a user visits /courses/1, I want Rails to display the show action in the courses controller (and pass the parameter as :id). When a user visits /courses/CO though, I want Rails to display the index action and pass the parameter as :state.
So /courses/1 would be equivalent to
:controller => 'courses', :action => 'show', :id => '1'
And /courses/CO would be equivalent to
:controller => 'courses', :action => 'index', :state => 'CO'
I have tried this:
map.resources :courses, :except => { :index, :show }
map.connect 'courses/:state', :controller => 'courses', :action => 'index', :state => /[A-Z]{2}/
map.connect 'courses/:id', :controller => 'courses', :action => 'show', :id => /[0-9]+/
But it breaks (the rails server wont even start). I don't usually do things like this with routes, so I am outside of my know-how. Thanks!
Edit: Fixed a typo, thanks JC.
Current solution looks like this:
map.resources :courses, :except => [ :index, :show ]
map.courses '/courses', :controller => 'courses', :action => 'index', :state => 'AL', :method => :get
map.courses '/courses/:state', :controller => 'courses', :action => 'index', :requirements => { :state => /[A-Z]{2}/ }, :method => :get
map.course '/courses/:id', :controller => 'courses', :action => 'show', :requirements => { :id => /[0-9]+/ }, :method => :get
This works, but you will need to go edit all your links to the index to say things like courses_path('AA') and you won't be able to use some of the nice helpers, like form_for, which assume you are following the convention that #create is simply #index with a POST request. (Get comfortable with form_tag)
ActionController::Routing::Routes.draw do |map|
map.resources :courses, :except => [ :index, :show ]
map.courses '/courses/:state', :controller => 'courses', :action => 'index', :requirements => { :state => /[A-Z]{2}/ } , :method => :get
map.course '/courses/:id', :controller => 'courses', :action => 'show', :requirements => { :id => /[0-9]+/ } , :method => :get
end
It will keep your routes named the same, though.
(by the way, your /co does not match your regex, which requires upper case chars)
Fun aside: Do we really need the abstraction of a router? http://blog.peepcode.com/tutorials/2010/rethinking-rails-3-routes
I'm afraid this won't work since the structure that maps paths to controllers and actions is setup on start of the rails application, parameter handling happens at request time.
What you could do is to match the :id-parameter in the show-action of the CoursesController against a list of valid states and then either redirect or render a different action.
Hope this helps.

Rails: Routing subdomain to a resource

Is it possible to map a subdomain to a resource? I have a company model. Currently, using subdomain_fu, my routing file contains:
map.company_root '', :controller => 'companies', :action => 'show',
:conditions => { :subdomain => /.+/ }
My Company model contains a "subdomain" column.
Whilst this works as intended, it's a named route and isn't restful. Essentially, I need to map "name.domain.com" to the show action for the companies controller. Is a named route the way to go, or can I use a resource route?
One can pass conditions to a resource route as well as a named route. In an application I am involved with everything is scoped to an account. A :before_filter loads the account using the subdomain. Thus for resources scoped to an account, we want to scope the routes to urls with subdomains. The DRY way to do this is to use map with options:
map.with_options :conditions => {:subdomain => /.+/} do |site|
site.resources :user_sessions, :only => [:new, :create, :destroy]
site.resources :users
site.login 'login', :controller => "user_sessions", :action => "new"
site.logout 'logout', :controller => "user_sessions", :action => "destroy"
…
end
map.connect 'accounts/new/:plan', :controller => "accounts", :action => "new"
map.resources :accounts, :only => [:new, :create]
As you can see a named route will accept a conditions hash with a subdomain too. You can also adopt the approach Ryan illustrated above or you can specify conditions on a per resource basis:
map.resources :users, :conditions => {:subdomain => /.+/}
I don't know of a way to do this with map.resources. It does accept a :conditions option but I'm not sure how to remove the /companies/ portion of the URL. However, map.resources is primarily a convenient way to generate a bunch of named routes, which you can do manually. Something like this.
map.company '', :controller => 'companies', :action => 'show', :conditions => { :subdomain => /.+/, :method => :get }
map.new_company 'new', :controller => 'companies', :action => 'new', :conditions => { :subdomain => /.+/, :method => :get }
map.edit_company 'edit', :controller => 'companies', :action => 'edit', :conditions => { :subdomain => /.+/, :method => :get }
map.connect '', :controller => 'companies', :action => 'create', :conditions => { :subdomain => /.+/, :method => :post }
map.connect '', :controller => 'companies', :action => 'update', :conditions => { :subdomain => /.+/, :method => :put }
map.connect '', :controller => 'companies', :action => 'destroy', :conditions => { :subdomain => /.+/, :method => :delete }
Untested, but it should get you close.
Here's a complete example implementation of Rails 3 subdomains with authentication (along with a detailed tutorial). It's much easier to do this in Rails 3 than in Rails 2 (no plugin required).
Using the resource linked from Daniel's answer, in Rails 3 the way to route '/' to a different controller depending on the subdomain is as follows:
match '/' => 'somecontroller#action', :constraints => { :subdomain => 'yoursubdomain' }

Resources