Rails partial for different controllers - ruby-on-rails-3.1

So I have different controllers that share a lot of functionality and I'm wondering if there is a way to share that similar functionality between them.
For example this:
= link_to 'Edit', dvd_path(dvd), :class => 'btn'
Where the only thing that changes between controllers is the object, instead of dvd it will be books or games. So I'm thinking there has to be a way to create a partial that uses that controller's correct path without having to rewrite each one. And without having to send the object.
Ideas are appreciated.
Edit
#defaye: what I'm trying to do is reuse the code that I have above and apply it to 7 or so different controllers.
The above code is just an example of a bunch of links and paths that are always the same and the only thing that changes is that dvd_path(dvd) becomes book_path(book), etc.
I'd like the simplest, more straightforward way of doing it.
In fact, I am now wondering if it's possible to have the same view that handles multiple controllers since they are so similar. This would be fantastic!
Thanks.

If your code is just a couple of methods, you don't need a partial at all. Helpers can help you.
Here's an example. You can define it in ApplicationHelper.
# application_helper.rb
def link_to_edit(object)
link_to('Edit', polymorphic_path(object, :action => 'edit'), :class => 'btn')
end
And in your view
= link_to_edit(object)

Related

How can I add 'pages' in addition to 'tags' with acts-as-taggable-on

I am just in the last few months learning Ruby from a client project, and have now decided to port my legacy CMS into Ruby.
I have successfully installed the gem and implemented acts-as-taggable-on with tags and taggings so that I have tags working in my Post controller. I can add tags to my edit form, and they are linked in my posts as expected.
What I am hoping to do is use the enhanced features of acts-as-taggable-on to define another set of 'tags' which are actually pages. In my current application I have a table called Pages, and the Posts have a field called PageID. The Pages table holds the name of the page, as well as some config features for that page, such as layout and css. Posts can only appear in the Page they were assigned/created from.
Since all Posts are stored in the same table, I was hoping to extend the acts-as-taggable-on to handle both my tagging and pages, if this makes sense.
I understand how the same tagging model can be extended to other controllers such as Photos, Video etc, but I am unsure how I would go about applying 2 different 'tagging' models to the same Controller. If I don't use tagging for the pages, I am unsure about how I would define the 'pages' in a Ruby context, since I need the page names to be dynamic per user. I understand theoretically how to do this in routes.rb but am stuck as how to define my pages.
Thanks for any help! Let me know what .rb file code to post to illustrate what I am doing now.
You could use the following approach:
Create two classes "Page" and "Post" that inherit from a base "UserContent" class. The "Page" and "Blog" classes would have to each have their own controller.
You could route to each of them with something like:
scope '/blog' do
resources :posts
end
scope '/about' do
resources :posts
end
To use the post name instead of an id, I would highly recommend you checkout stringex which will allow you to do just that. It will involve adding a url attribute to your models but I'll let you check out their documentation to find out how it all works. This should be the answer to your original question and it should be a better tool for dynamic page/post page names than acts-as-taggable-on.
This setup should give you "site.com/about/page-name" for pages and "site.com/blog/post-name" for posts.

Unhappy with the rail way of rendering partials

my question considers the partial handling in Rails. I just can't get the reason for some design decisions.
If I render a partial like this:
<%= render partial: 'foo/bar', object: #herbie %>
Where #herbie is an object of class Car. Why is the local variable called bar by default instead of car which - at least for me - would be more reasonable in most cases.
If various partials share a common layout I have to add the layout: ... each time I use render partial:. This seems odd to me! Isn't it more likely to have various partials wich share the same layout then the other way around? Wouldn't it be more reasonable to define the layout within the partial, or to add a to_layout_path method to the ActiveRecord Model?
Update:
I get the point that it might be better to use the partial name, as this is well known in the partial context. However the use of the tags :locals and :as screws up this argumentation.
In an actual case I want to use different partials depending on the state of an object (questions that could be open or closed). I moved the decision which partial to render to the Question.to_partial_path method which seems to be quite elegant. However I named the partials open_question and closed_question and this makes the partial code unreadable.
It gets even worse if I consider different types of questions.
I expect that within a partial we always make some presumptions about the model that is passed in. Thus in closed_question I am quit sure that I get a question - thus I would expect the variable to be called question. On the other hand I can imagine situations where we pass in something different that just behaves appropriated (Duck-typing).
My temporal meaning about partials is that within the partial it should be possible to define the name of the given parameter as well as a layout file that is used.
The parameter indeed can be realized by introducing a new variable ( question = open_question) which feels a little bit unclean to me.
When you pass in an argument to a method there's no way of knowing what the "name" of that variable is. The only thing the partial rendering method here has at its disposal is the foo/bar name, the object attribute, and some model.
That your model originated in a variable called #car is completely lost in the process of making the call.
It's convention in Rails that the variable used within the partial is the same as the name of the partial itself. You can override this if you want to have non-standard behaviour:
render(partial: 'foo/bar', locals: { car: #car })
As a note, though, going down the non-standard path is usually a bad idea. Whenever possible, just rename your partial to better match your expectations.
This is related: render partial :object vs :locals
The documentation is pretty good: http://api.rubyonrails.org/classes/ActionView/PartialRenderer.html
The default is to name the object after the partial. If you want to be explicit, you can use :as or locals.
render partial: 'foo/bar', locals: {car: #car}
render partial: 'foo/bar', object: #car, as: 'car'

How do you handle single table inheritance in SimpleForm so a single helper handles all models?

We have a model "EventSession" which has several subtypes via STI, including "NetworkingEventSession" and "DiningEventSession"... we want to be able to handle all of them from one controller and one view in some cases, but simple form is looking at the objects when iterating through in simple_form_for #session and trying to use the networking_event_session_path helper, which we don't currently have defined, instead of the regular event_session_helper path, which would work fine and is what we want.
I could define new routes to get helpers for each subtype, all directing to the same path, but that will be very unDRY, and we may not always want them going to the main event session path... is there some way to override simple_form_for in this particular view to tell it explicitly what model/class to use?
Specify :url=> networking_event_session_path in the simple_form_for.
Something like this:
<%= simple_form_form #session, :url => networking_event_session_path %>

Ruby/Rails: How to specify an arbitrary route path via a string in a View, or a route URL in a Model

This bit has been frustrating me all night and I can't find a helped or clean way to do it.
I had a non-ActiveRecord Model (so not stored in the DB) that reflects a dynamic navigation menu, and one attribute of the model's menu items is naturally a route link. (the Model in question essentially has a class with links/routes stored in it, to other Model routes) I don't like the idea of storing URLs, or any navigation data for that matter, in a model, but I can't see a better way to design this.
The link_to attribute could be a route path (e.g. user_path) as a string which would be used in the View to determine the URL. Or, it could be stored in the Model as the URL by retrieving it from the routes via the url_helper. (I think)
So, does anyone have any suggestions on a helper or trick that could solve the problem? url_helper and url_for kind of expect a model with a matching route. In this case the non-ActiveRecord Model is not a normal Model, but a representation of the site's Navigation Menu, linking to other parts of the site.
I really just want a helper or function to say, route_to 'user_path'. Does anyone know if this is possible?
Any help would be appreciated. Thanks!
The answer, beside the fact I'm probably abusing MVC models, is Rails.application.routes.url_helpers. you can call it with the route path as a direct method and it'll return the url, but the trick that I found is the send method allows calling it with a string representation of the route path. This makes coding for it much easier. Note saying this works as is. It's just an example:
class Something
attr_accessor :somethings
def all()
#somethings = Array.new
somethings << Something.new('user_root_path')
somethings << Something.new('edit_user_path')
somethings << Something.new('edit_pets_path')
end
...
def initialize(link)
#link = Rails.application.routes.url_helpers.send link
end
end

Multilang Webites : Where to store the langs list?

We have a website translated in almost thirty languages. Each article will have a field saying which language it've been written for.
I wonder what's the best rails way to implement this. Create a full model Language with something like this :
Class Language
has_many :article
end
Class Article
belongs_to :language
end
Or hardcode this directly in a field of the articles table with a constant to list all the available langs. (Mainly to show it in a drop-down list) :
LANG_LIST = {:en => 'english', :de => 'german', :fr => 'french' ...}
The two work, but what's the best rails way and the cleanest to maintain ?
Thanks for your opinion !
You can just create a language attribute on the article model to store the information, your second option may be just enough.
A language model would just be too much for no real gain, i think.
If you want to encapsulate it further, you can create a module that extends your model to instance methods that handle languages. And that is probably the preferred way, if you want to make things clean.
Should you wish to stick with a model, remember that you can use the delegate helper to make things transparent to your language model. So, instead of article.language.locale, you can directly call article.language_locale (a very subtle but important design pattern).
Many things that you can do, but i will probably keep it simple with a module here.

Resources