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:in
block (3 le vels) in '←[0m ←[36m # ./spec/controllers/stylesheets_controller_spec.rb:44:in `block (3 le vels) in '←[0mFinished 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
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:
Browser requests the forum page. This is handled by ForumsController#show
or something like that.
In a before filter or otherwise, you need to determine the id for the stylesheet somehow, for the <link>
tag.
Your layout application is wrapped around the page for the action, and the request ends.
Browser notices it needs to request stylesheets / javascripts, one of which is your custom stylesheet.
Your StylesheetsController#show
is called, and the stylesheet is rendered back. This and all the other assets requests are completed.
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