1

I am building a forum and I wish for the admins to be able to edit the css in the admin control panel (like most PHP forums).

I've stored the css in a table called stylesheet.

I need to be able to call this specific row in the stylesheets table in layout/applications so the css shows on ALL pages.

I was wondering if there is a way of using the stylesheet_link_tag to call the location of the css inside the database table?

If not... How exactly do I do it?

I tried using this: Best way to handle dynamic css in a rails app but it did not work.

EDIT: All I am trying to do is instead of calling the assets/stylesheets/layout (<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>) I call the database/stylesheet/id1.code.

I just need to get ID 1 and extract the code from it and display it for every single page as the main CSS.

This is the error I get now:

No route matches {:controller=>"stylesheets", :action=>"show", :id=>nil, :format=>:css} missing required keys: [:id]

Stylesheet Controller

class Admin::StylesheetsController < ApplicationController
    caches_page :show # magic happens here

    def index
        @stylesheets = Stylesheet.all
  end

    def show
        @stylesheet = Stylesheet.find(params[:id])
        respond_to do |format|
          format.html # regular ERB template
          format.css { render :text => @stylesheet.code, :content_type => "text/css" }
        end
    end

  def edit
    @stylesheet = Stylesheet.find(params[:id])
  end

    # When you edit/update the category, update the information
    def update
        @stylesheet = Stylesheet.find(params[:id])
        if @stylesheet.update_attributes(params[:stylesheet].permit!)
            redirect_to edit_stylesheet_path
        else
            render :edit
        end
    end
end

Layout/Application.html.erb

<!DOCTYPE html>
<html>
<head>
  <title>Ruby Ibis | <%= yield(:title) %></title>

    <link rel="stylesheet" href="<%= stylesheet_path(@stylesheet, format: :css) %>" type="text/css" />

  <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
  <%= csrf_meta_tags %>
   <%= render 'layouts/shim' %>

  </head>
   <body>
    <%= render 'layouts/header' %>
        <div class="container">
      <% flash.each do |key, value| %>
        <div class="alert alert-<%= key %>"><%= value %></div>
      <% end %>
      <%= yield %>
      <%= render 'layouts/footer' %>
      <%= debug(params) if Rails.env.development? %>
    </div>
  </body>
</html> 

Results of test

$ rspec spec/controllers/stylesheets_controller_spec.rb ←[31mF←[0m

Failures:

1) StylesheetsController#show should have the correct css ←[31mFailure/Error:←[0m ←[31mlet(:stylesheet) { Factory(:stylesheet) }←[0m ←[31mNoMethodError←[0m: ←[31mundefined method Factory' for #<RSpec::Core::ExampleGroup::Nested_1 ::Nested_1:0x47793f0>←[0m ←[36m # ./spec/controllers/stylesheets_controller_spec.rb:42:inblock (3 le vels) in '←[0m ←[36m # ./spec/controllers/stylesheets_controller_spec.rb:44:in `block (3 le vels) in '←[0m

Finished in 0.02 seconds ←[31m1 example, 1 failure←[0m

Failed examples:

←[31mrspec ./spec/controllers/stylesheets_controller_spec.rb:43←[0m ←[36m# Style sheetsController#show should have the correct css←[0m

Randomized with seed 18359

Community
  • 1
  • 1
Lindsiria
  • 187
  • 1
  • 4
  • 16

2 Answers2

3

Don't worry about caching right now. Just see if it renders at all:

class Admin::StylesheetsController < ApplicationController

  respond_to :css

  def show
    @stylesheet = Stylesheet.find(params[:id])
    render text: @stylesheet.code, content_type: "text/css"
  end

end

Write a test for GET /stylesheets/:id.css. And in the markup:

<link rel="stylesheet" href="<%= stylesheet_path(@stylesheet, format: :css) %>" type="text/css" />

It seems like you're confusing the stylesheet for the forum. The stylesheet is a resource, and it is requested implicitly with the <link> tag. You put the link to the stylesheet as part of the forum html page.

Your stylesheets/:id.css path returns the css only, no markup. A test for this assuming the field in your stylesheet model is called :code would be:

describe '#show' do
  let(:stylesheet) { Factory(:stylesheet) }
  it 'should have the correct css' do
    get :show, id: stylesheet.id
    expect(response.body).to eq(stylesheet.code)
  end  
end

Seems like you're confused about the way Rails works with requests. I'll walk you through the timeline:

  1. Browser requests the forum page. This is handled by ForumsController#show or something like that.

  2. In a before filter or otherwise, you need to determine the id for the stylesheet somehow, for the <link> tag.

  3. Your layout application is wrapped around the page for the action, and the request ends.

  4. Browser notices it needs to request stylesheets / javascripts, one of which is your custom stylesheet.

  5. Your StylesheetsController#show is called, and the stylesheet is rendered back. This and all the other assets requests are completed.

  6. Now the user with the browser can see the custom css.

So you see, the @stylesheet is not set when the page is rendered, and istance variables are set per controller per request. Not globally. Setting @stylesheet in StylesheetsController#show only sets it for the route GET /stylesheets/:id.css.

You might want to consider using sublayouts - http://www.ajostrow.me/thoughts/sublayouts-with-rails-revised

AJcodez
  • 31,780
  • 20
  • 84
  • 118
  • Okay, I changed my stylesheets controller to your code. How would I go about creating a test for a certain field in a database? I'm use to using rspecs for controllers, but not for finding an actual field in a table. – Lindsiria Oct 27 '13 at 20:41
  • undefined method `stylesheet' for nil:NilClass is an error I get when i put your markup in my application. – Lindsiria Oct 27 '13 at 21:31
  • i have a sneaking suspicion you have no idea what you're doing! go through this tutorial until it all makes sense: http://ruby.railstutorial.org/ruby-on-rails-tutorial-book – AJcodez Oct 27 '13 at 21:43
  • I actually did that tutorial to learn RoR. I just do not know how to test the :id.css and where to put that link in the markup. Trust me, I went back to that tutorial when he posted that response. I can show you guys what I have for testing thus far, but I know it is not correct. – Lindsiria Oct 27 '13 at 21:50
  • I don't get what you mean by confusing the stylesheet for the forum. Yes, I know the stylesheet is a resource, and i need to request it with the link tag. I put the link to the stylesheet on the layout/application.html.erb page because I need to have it show up as the custom.css for every single page. If I put it in the forum html pages... it will only show up in the forum, not on every page. Isnt (@forum.stylesheet) stating you are trying to find stylesheet in the forum... because there is no foreign key. Forum is a completely different table than stylesheet. – Lindsiria Oct 28 '13 at 00:12
  • I put the results of the test up (for some reason rspecs didn't want to work for awhile.) – Lindsiria Oct 28 '13 at 01:24
  • don't worry about @forum, that was just a suggestion for how to structure it – AJcodez Oct 28 '13 at 03:49
  • Thank you for everything you have done thus far. I knew I am so close to getting it. The most recent error (with your edited code) is (I think i need ID is to be equal to 1... somewhere): No route matches {:action=>"show", :controller=>"stylesheets", :id=>nil, :format=>:css} missing required keys: [:id] – Lindsiria Oct 28 '13 at 04:19
  • `@stylesheet` needs to be set in the controller – AJcodez Oct 28 '13 at 04:20
  • Shouldn't @stylesheet = Stylesheet.find(params[:id]) in the stylesheet controller be what sets it? – Lindsiria Oct 28 '13 at 04:40
  • I know it has been a few days, I have been very busy. I want to thank you again for everything. I have managed to get rid of the errors by placing @stylesheet = Stylesheet.find(1) in all the controllers (such as category). However, it is not showing the layout. Somehow this: does nothing. – Lindsiria Nov 02 '13 at 22:35
  • try rendering it inline: `` – AJcodez Nov 03 '13 at 17:21
  • I found a way based off some of your code. I don't think it's necessarily proper, but it works :D. I believe the reason your link code didn't work was because my stylesheet folder was in the admin namespace and it was linking to just the stylesheet in the non admin namespace. I'm going to answer my question with what I did but give you the credit as I couldn't have done it without you. Thanks :D – Lindsiria Nov 03 '13 at 20:19
0

Due to my stylesheets being in the admin namespace, the code we have been trying to used failed. I figured out a way around it, even if it is probably not a good method of doing things.

I ended up linking directly to the stylesheet. It works perfectly, even if it isn't a conventional or probably accepted way. I can look for a better method later, I just needed to finish my project to graduate...

 <link href="/admin/stylesheets/1/" media="screen" rel="stylesheet" type="text/css" />
Lindsiria
  • 187
  • 1
  • 4
  • 16