
Polymorphic connections. Little addition
In December on Habré there was a good article, about polymorphic connections in Rails. There she is . Before reading further, please read it.
However, the author of the article has several unanswered questions. Here we are today and find the answers.
Firstly, in the text of the article there is such a code.
It certainly works, but ... it’s not at all the Rails style. Everything should be simpler. And there is. Rails offer us a great option - the polymorphic_path () method . As well as new_polymorphic_path () and edit_polymorphic_path () . The essence of the method, and that it, depending on which models are fed into it, will produce the urls we need. Like this.
Here, depending on what kind of content in @post ( the Topic, Link, Podcast ), will be entered url to edit it. It is clear that polymorphic_path () and new_polymorphic_path () work similarly.
Secondly, during the course of the article, the author was told that it would be nice to use accepts_nested_attributes_for and even then made an article on this topic, but this article does not say how this combines with polymorphic relationships. But it fits very well, the main approach is to know :)
Let's take an example to consider the controller that Topic will create.
We see that everything is very easy. And most importantly, it works. A working example of all this can be seen here .
PS For all who program on the Rail, look at my link yesterday to Habré . Very interesting things about ActiveRecord in Rails 3.
UPD. I forgot another little detail. For ease of editing and easy scalability, you can still appropriately drank view. An example is here (here I do not want to upload it, because there will be too much code). The link with the view for Post is a link from which, depending on the type of content, the view for Topic or Link jerks .
However, the author of the article has several unanswered questions. Here we are today and find the answers.
Firstly, in the text of the article there is such a code.
- module PostsHelper
- def posts_smth_path(post)
- case post.content.class.to_s.downcase
- when "topic" : posts_topic_path(post)
- when "link" : posts_link_path(post)
- when "podcast" : posts_podcast_path(post)
- end
- end
- def posts_smths_path(post)
- case post.content.class.to_s.downcase
- when "topic" : posts_topics_path
- when "link" : posts_links_path
- when "podcast" : posts_podcasts_path
- end
- end
- end
It certainly works, but ... it’s not at all the Rails style. Everything should be simpler. And there is. Rails offer us a great option - the polymorphic_path () method . As well as new_polymorphic_path () and edit_polymorphic_path () . The essence of the method, and that it, depending on which models are fed into it, will produce the urls we need. Like this.
- <%if can? :edit, @post%>
- <%= link_to "Edit this #{@post.content.class.to_s.downcase}", edit_polymorphic_path([:posts, @post.content]), :class=> "b-post-edit_link g-link-no-visited" %>
- <%end%>
Here, depending on what kind of content in @post ( the Topic, Link, Podcast ), will be entered url to edit it. It is clear that polymorphic_path () and new_polymorphic_path () work similarly.
Secondly, during the course of the article, the author was told that it would be nice to use accepts_nested_attributes_for and even then made an article on this topic, but this article does not say how this combines with polymorphic relationships. But it fits very well, the main approach is to know :)
Let's take an example to consider the controller that Topic will create.
- classPosts::TopicsController< PostsController
- def index
- @posts = Post.topics.find(:all)
- end
- defnew
- @topic = Topic.new
- @topic.build_post
- @selectable_categories = Category.all.collect{|c|[c.title, c.id]}
- end
- def edit
- @topic = Topic.find(params[:id])
- @post = @topic.post
- @selectable_categories = Category.all.collect{|c|[c.title, c.id]}
- end
- def create
- @topic = Topic.new(params[:topic])
- @topic.post.author = current_user
- if@topic.save
- redirect_to post_path(@topic.post)
- else
- @selectable_categories = Category.all.collect{|c|[c.title, c.id]}
- render:action=> "new"
- end
- end
- defupdate
- @topic = Topic.find(params[:id])
- if@topic.update_attributes(params[:topic])
- redirect_to post_path(@topic.post)
- else
- @selectable_categories = Category.all.collect{|c|[c.title, c.id]}
- render:action=> "edit"
- end
- end
- end
We see that everything is very easy. And most importantly, it works. A working example of all this can be seen here .
PS For all who program on the Rail, look at my link yesterday to Habré . Very interesting things about ActiveRecord in Rails 3.
UPD. I forgot another little detail. For ease of editing and easy scalability, you can still appropriately drank view. An example is here (here I do not want to upload it, because there will be too much code). The link with the view for Post is a link from which, depending on the type of content, the view for Topic or Link jerks .