Generate a `link_to` to the controller action `edit`, dynamically - ruby-on-rails

I am using Ruby on Rails 3.0.7 and I would like to generate a link_to to the controller action edit, dynamically. I have to use it in a partial template but the issue is that I am rendering that same partial template for different model data (that is, I pass local variables of different class instances in that).
So I can not use the route "magical RoR way"
`edit_<singular_name_of_the_resource>_path(<resource_class_instance>)`.
I would like to make something like the following:
link_to( #resource_class_instance, :action => 'edit') # This example is wrong, but it suggests the idea
Is it possible? If so, how can I do that?

You can write routes using the "array style" like this :
= link_to "Edit", [:edit, #your_resource]

There is a edit_polymorphic_url and (edit_polymorphic_path) helper available:
https://github.com/rails/.../polymorphic_routes.rb#L32

Related

Rails: link_to only if route exists

I'm writing a Rails Engine and in one of my views I'd like to create a link to main_app if a named route exists.
I will give an example to clarify the question:
The Main application may or may not define in routes.rb:
resources :my_resource, only: :index
In my rails engine I need to add a link to my_resource_path only if main_app defined that route. I think it should be something like the following:
<%= link_to "Link", main_app.my_path if my_resource_path_exists? %>
I tried:
<%= link_to "Link", main_app.my_resource_path if
main_app.respond_to?(:my_resource_path) %>
but, when the path does not exist, that raises NoMethodError:
undefined method `my_resource_path' for #<Module>
How my_resource_path_exists? method could be implemented? I'm using ruby 2.2 and rails 4.2
The question is related to: Determine if path exists as route in Rails controller
But in this case, I have a named route (my_resource_path), so I need something slightly different, but can't figure out by myself.
I found a solution wich does not require to recover from fail. It's possible to check if the route is defined using url_helpers:
Rails.application.routes.url_helpers.method_defined?(:my_path)
So, the code could be written like that:
<%= link_to "Link", main_app.my_resource_path if
Rails.application.routes.url_helpers.method_defined?(:my_resource_path) %>
You could either use main_app.try(:my_path) or rescue NoMethodError to return false.

How to create a new_X_path url dinamically in template

I have a link in my partial template:
link_to 'Add', new_photo_path
But I want to make this partial template shared. Is there any way to make 'new_CONTROLLER_path' url automatically? The CONTROLLER must be replaced by current controller.
Try this:
link_to 'Add', [:new, params[:controller].singularize]
Internally, Rails will convert [:new, params[:controller].singularize] to a call to new_controller_name_path(e.g. if controller posts then [:new, params[:controller].singularize] generate a path helper like new_post_path).
Most (if not all) Rails methods that expect a path will also take an object representation of your resource, like respond_with, link_to, render, redirect_to, form_for, etc.
Try something like this:
link_to 'Add', eval("new_#{params[:contoller].singularize}_path")
params[:contoller].singularize will return you photo or any controller name related to request eval will do rest.

link_to custom action but wrong method?

all, I'm trying to get a custom action to work with a put method: in the
in _post.html.erb i have a link_to statement:
<%= link_to 'End now', post, :method => :put, :action => endnow %>
routes.rb contains:
resources :posts do
member do
put :endnow
end
and posts_controller.rb looks like:
class PostsController < ApplicationController
helper_method :endnow
[.. code for create, edit, destroy, etc ..]
def endnow
puts params
end
end
rake routes's relevant line looks like:
endnow_post PUT /posts/:id/endnow(.:format) posts#endnow
However, the action endnow helper doesn't run when clicking on this link.
Strangely, it does run with an index action (which i can tell from the puts command.
Of course, eventually the code for endnow will update #post, but for now, it just doesn't run properly.
Maybe i'm going about this the wrong way - all I'm trying to achieve is to update #post upon clicking the link to that post, and before showing it.
Any ideas / Alternatives?
Why not use the route helper method provided to you? Change your link to
<%= link_to 'End now', endnow_post_path(#post), method: :put %>
Things you're doing wrong:
If you want to specify the :action, use the Symbol for the action (you're missing a colon). :action => endnow should be action: :endnow
I will assume you have a #post instance variable you're passing from your controller to your action. You should be using that instead of post (unless you do in fact have a local post variable you're omitting from your code)
You are using endnow as an action; you should remove the helper_method :endnow line in your controller because it's not something you want to/should be accessing from your view.
This can all be avoided by using the route helper (for endnow_post you'd append _path to get the local route path: endnow_post_path), and pass in your #post as an argument.
Because you're trying to do a PUT request, you must make sure you have something like jquery-ujs included in your asset pipeline to convert these links to form submissions behind the scenes; browsers don't support PUT via the click of a link on their own.
As for why you're getting the template error when you get your link_to working, Rails is telling you that you need to create a app/views/posts/endnow.html.erb file. Your action has only puts params which does not terminate execution, leaving Rails to assume you still are trying to render some endnow.html.erb template.
Are there other ways to do what you're trying to do (change a single attribute of a specific model)? Sure. Are there better ways? That's pretty subjective; it may not be the most RESTful way, but it's arguably easier to deal with (if for example there are very specific authorization rules to check before updating the attribute you are modifying in endnow. Does the way you've started fleshing out work? Absolutely.
Finally, as a bump in the right direction, after you fix your link_to and remove the the helper_method as I have described above, your endnow action might look like this:
def endnow
post = Post.find!(params[:id])
post.some_attribute_here = some_new_value_here
post.save
redirect_to :root and return # <- this line sets a redirect back to your homepage and terminates execution, telling rails to do the redirect and **not** to render some endnow.html.erb file
end

How to get a named route from a class in rails?

I have a common partial for index where i want to insert some links.
On this links i would like to use the named_routes, like
link_to "Say hi",things_path(:param1=>:hello, :params2=>:there)
but i dont know if things_path is users_path, places_path or reviews_path, because this partial is shared for all controllers. There is any way to get the named route associated to the class or the current controller.
I want something like this
link_to "Say hi", path_of(#current_class)(:param1=>:hello, :params2=>:there)
There are several approaches to this. The simplest thing is to rely on polymorphic routing, such as: link_to "Say hi", #my_object. In this case rails will look at the class of #my_object and its current state (new_record?) and use the appropriate route and restful action. Assuming your partial is named _foo.html.erb then this can be as simple as
link_to 'Say hi', foo
... which is pretty awesome. This question has been asked before, here: Polymorphic Routes in Rails - in views but I guess it's hard to find answers without knowing the magic words "polymorphic routing" :-)
A path helper like cars_path is ultimately just a shortcut to setting :controller, :action and other params like :id. If you want to make the controller always equal to the current controller you can just say
link_to "Say hi", :action => "index", :param1=>:hello, :params2=>:there
Because the :controller option is omitted, it will be assumed to be the current controller.

How to do user content from CMS in Rails

I'm trying to build a CMS in Rails from scratch, and for showing the user generated pages I'm having trouble deciding exactly how to do it.
The way I have it right now, I have a controller named 'content' with a single action called 'show'. In routes.rb I have a rule that passes any name after the name of the website to the content controller, show action with parameter name.
For example, www.mysite.com/about_us would route to
:controller => 'content', :action => 'show', :page => 'about_us'
Inside the content controller, I do a find on the Pages model to locate the named page:
#markup = Page.find_by_name(params[:page])
And then in the show.html.erb view I use the raw helper to display the content:
<%= raw #markup.text %>
Does this method violate anything about the way I should do be doing things in Rails? Or is this an OK solution?
I ended up using the sanitize helper, by default it removes <script> tags which is essentially what you need to prevent XSS, as far as I understand. For those who have found this via a search, the only code that changes from what I described above is that in the view you change to:
<%= sanitize #markup.text %>

Resources