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.

    1. module PostsHelper
    2. def posts_smth_path(post)
    3. case post.content.class.to_s.downcase
    4. when "topic" : posts_topic_path(post)
    5. when "link" : posts_link_path(post)
    6. when "podcast" : posts_podcast_path(post)
    7. end
    8. end
    9. def posts_smths_path(post)
    10. case post.content.class.to_s.downcase
    11. when "topic" : posts_topics_path
    12. when "link" : posts_links_path
    13. when "podcast" : posts_podcasts_path
    14. end
    15. end
    16. 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.

    1. <%if can? :edit, @post%>
    2. <%= 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" %>
    3. <%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.

    1. classPosts::TopicsController< PostsController
    2. def index
    3. @posts = Post.topics.find(:all)
    4. end
    5. defnew
    6. @topic = Topic.new
    7. @topic.build_post
    8. @selectable_categories = Category.all.collect{|c|[c.title, c.id]}
    9. end
    10. def edit
    11. @topic = Topic.find(params[:id])
    12. @post = @topic.post
    13. @selectable_categories = Category.all.collect{|c|[c.title, c.id]}
    14. end
    15. def create
    16. @topic = Topic.new(params[:topic])
    17. @topic.post.author = current_user
    18. if@topic.save
    19. redirect_to post_path(@topic.post)
    20. else
    21. @selectable_categories = Category.all.collect{|c|[c.title, c.id]}
    22. render:action=> "new"
    23. end
    24. end
    25. defupdate
    26. @topic = Topic.find(params[:id])
    27. if@topic.update_attributes(params[:topic])
    28. redirect_to post_path(@topic.post)
    29. else
    30. @selectable_categories = Category.all.collect{|c|[c.title, c.id]}
    31. render:action=> "edit"
    32. end
    33. end
    34. 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 .

    Also popular now: