Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Rails Generator --singleton

#4863

When generating a scaffold as 'rails g scaffold posts --singleton', show.html.erb contains a "link to 'Back', 'posts_path'". There is no index for a singleton method so loading up /posts will throw an error about that path not existing from dispatches 'resource :posts'.

All that is needed is a couple of lines removed from the rails generator.

Reported by Ellis Berner · June 14th, 2010 @ 09:33 PM

State: resolved
Milestone: 3.0.2
Assigned to: José Valim José Valim
Importance: Low

Activity

  1. Ellis Berner
    Ellis Berner
    • No changes were found…

    June 14th, 2010 @ 09:34 PM

  2. Ellis Berner
    Ellis Berner

    err typo. Should be 'loading up /post' (not posts)

    June 14th, 2010 @ 09:35 PM

  3. Jeff Kreeftmeijer
    Jeff Kreeftmeijer

    I've attached a patch that removes <%= link_to 'Back', posts_path %> from the edit and new actions' views when using the generator with the --singleton option for master.

    It includes tests for this specific change and some tests for running the generator with the --singleton option, since they didn't exist yet.

    June 15th, 2010 @ 06:07 AM

  4. Jeff Kreeftmeijer
    Jeff Kreeftmeijer

    There were some unnecessary tests in test_singleton_scaffold_on_invoke that I directly copied from test_scaffold_on_invoke and some trailing whitespaces in my previous patch. Here's a new one. :)

    June 16th, 2010 @ 02:18 PM

  5. Jeff Kreeftmeijer
    Jeff Kreeftmeijer

    Aaand another one. This is the same as the previous patch, but adds parentheses around the arguments of the assert_match calls to avoid warnings when running the tests (Like I did for the rest of the scaffold_generator tests in #4872 "ambiguous first argument" warning in `test/generators/scaffold_generator_test`). :)

    June 16th, 2010 @ 02:44 PM

  6. José Valim
    José Valim
    • Milestone cleared.

    Awesome mate! Just two quick notes:

    1)

    <%%= link_to 'Show', @<%= singular_name %> %> <%= '|' unless options[:singleton] %>
    <% unless options[:singleton] -%>
    <%%= link_to 'Back', <%= plural_name %>_path %>
    <% end -%>
    

    Could be better written as:

    <%%= link_to 'Show', @<%= singular_name %> %>
    <% unless options[:singleton] -%>
      | <%%= link_to 'Back', <%= plural_name %>_path %>
    <% end -%>
    

    2) And could you please check that:

    <%%= link_to 'Show', @<%= singular_name %> %>
    <%%= link_to 'Edit', edit_<%= singular_name %>_path(@<%= singular_name %>) %>
    

    In fact generates the proper route in singleton cases? I'm sure the second case does not, but we need to check the first.

    And nice additions (assert_no_instance_method and assert_not_in_file)!

    June 19th, 2010 @ 11:46 PM

  7. Jeff Kreeftmeijer
    Jeff Kreeftmeijer

    Thanks José, I've updated my patch and changed the views like you explained in your first note. The previous way of doing it was to keep the generated view exactly the same as before, but I think I like your approach more after all.

    About your second note: I'll check that out and will create a new ticket if find something, but that doesn't really have anything to do with this patch, right?

    June 20th, 2010 @ 11:34 PM

  8. José Valim
    José Valim

    Oh, now I see why you used the previous syntax, to keep the generated view pretty. Maybe we could do it inline? Something like this:

    <%%= link_to 'Show', @<%= singular_name %> %><% unless options[:singleton] -%>  | <%%= link_to 'Back', <%= plural_name %>_path %><% end -%>
    

    Sorry that I missed it earlier. :(

    And about the paths, it's related to this patch, because if the following is not valid for a singleton resource:

    <%%= link_to 'Edit', edit_<%= singular_name %>_path(@<%= singular_name %>) %>
    

    It means it should output this instead:

    <%%= link_to 'Edit', edit_<%= singular_name %>_path %>
    

    June 20th, 2010 @ 11:44 PM

  9. Prem Sichanugrist (sikachu)
    Prem Sichanugrist (sikachu)
    • State changed from new to open

    So, since Jeff's ticket didn't apply on master anymore, I've update his ticket to reflect the changes on the generator on master, while retaining his ownership.

    I've also took advice from José on the edit_<%= singular_name %>_path %> without argument thing, and write my another patch to fix it. (Also, doing some cleaning to make the output look nicer.)

    I've attach both patches below:

    June 23rd, 2010 @ 05:30 PM

  10. Prem Sichanugrist (sikachu)
    Prem Sichanugrist (sikachu)

    I actually found out some more bug with it, will provide another patch soon ..

    June 23rd, 2010 @ 05:41 PM

  11. Prem Sichanugrist (sikachu)
    Prem Sichanugrist (sikachu)

    Urgh.

    I actually stumbled across the usability bug of this patch on the controller side. Consider this snippets generated:

    class TopicsController < ApplicationController
    
      # GET /topics/1
      # GET /topics/1.xml
      def show
        @topic = Topic.find(params[:id])
    
        respond_to do |format|
          format.html # show.html.erb
          format.xml  { render :xml => @topic }
        end
      end
    
      # GET /topics/new
      # GET /topics/new.xml
      def new
        @topic = Topic.new
    
        respond_to do |format|
          format.html # new.html.erb
          format.xml  { render :xml => @topic }
        end
      end
    
      # GET /topics/1/edit
      def edit
        @topic = Topic.find(params[:id])
      end
    
      # POST /topics
      # POST /topics.xml
      def create
        @topic = Topic.new(params[:topic])
    
        respond_to do |format|
          if @topic.save
            format.html { redirect_to(@topic, :notice => 'Topic was successfully created.') }
            format.xml  { render :xml => @topic, :status => :created, :location => @topic }
          else
            format.html { render :action => "new" }
            format.xml  { render :xml => @topic.errors, :status => :unprocessable_entity }
          end
        end
      end
    
      # PUT /topics/1
      # PUT /topics/1.xml
      def update
        @topic = Topic.find(params[:id])
    
        respond_to do |format|
          if @topic.update_attributes(params[:topic])
            format.html { redirect_to(@topic, :notice => 'Topic was successfully updated.') }
            format.xml  { head :ok }
          else
            format.html { render :action => "edit" }
            format.xml  { render :xml => @topic.errors, :status => :unprocessable_entity }
          end
        end
      end
    
      # DELETE /topics/1
      # DELETE /topics/1.xml
      def destroy
        @topic = Topic.find(params[:id])
        @topic.destroy
    
        respond_to do |format|
          format.html { redirect_to(topics_url) }
          format.xml  { head :ok }
        end
      end
    end
    

    There're some issues from this generated controller:

    1. On the show and edit option, the params[:id] would not be assigned, as the URL for it would be /topic. So, what would be the best record to shown here? Topic.last?
    2. On the destroy action, what should we redirect the user to after destroyed? I mean, I know everybody will change it, but what would be the best? redirect_to '/'?

    I'd love to discuss more about this. ;)

    BTW, I've found out there's a bug in the _form.html.erb generated by the generator. I've attached the replacement patch to fix it.

    June 23rd, 2010 @ 06:33 PM

  12. José Valim
    José Valim

    Hey Prem! Nice work!

    About the controller, I don't think there is anything we can do to make it work by default. Usually, singleton resources are nested or depend on something in the session. That said, maybe we could show a message to the user saying that singleton only provides a stub, he still needs to work on controller + tests in order to have it working.

    What do you think?

    June 23rd, 2010 @ 07:14 PM

  13. Prem Sichanugrist (sikachu)
    Prem Sichanugrist (sikachu)

    Urgh ..

    So, after a long discussion with José, it turned out that we should remove the --singleton option for the time being. Because of:

    1. Singleton resource usually tied to another resource. For example, User has_one Profile. The controller generator doesn't actually know how should it find profile object. So, the test will be failed.
    2. I've tried to add argument to the --singleton option, to be --singleton=current_user. It turned out to be more ugly, and there're too many conditions going on in the controller file itself, make it hard to maintain.
    3. I've also tried stub out the find method as José suggest, but then the test case provided with the scaffold will be fail. This is not good, as some user expects the test cases to be pass after they generate the scaffold.

    I've proposed to make another generator as well, such as rails g singleton_generator current_user profile fullname:string, but then I don't think it would be welcomed by the core team. So maybe it could come as the plugin.

    So, thanks to everybody who's involved in this ticket, especially Jeff. I'm sure we'll find out the best solution soon.

    June 24th, 2010 @ 05:37 PM

  14. Repository
    Repository
    • State changed from open to resolved

    (from [67ee6c38b9b112eabe37d5869c23210b9ebf453c]) Remove the --singeleton option from scaffold generator.

    It turned out to be that scaffold for singeleton resource will always depend on another model, and it's not possible at the moment to make the application tests pass after generate the singeleton scafold. So, it would be better to remove it for now and probably provide another generator, such as singeleton_scaffold, in which also require the depended model name.

    [#4863 Rails Generator --singleton state:resolved]

    Signed-off-by: José Valim jose.valim@gmail.com
    http://github.com/rails/rails/commit/67ee6c38b9b112eabe37d5869c2321...

    June 24th, 2010 @ 07:21 PM

  15. Jeremy Kemper
    Jeremy Kemper
    • Milestone set to 3.0.2
    • Importance changed from to Low

    October 15th, 2010 @ 11:01 PM