by default, when i ask rails controller to do messages/index, he does
def index
respond_to{|fmt| fmt.html}
end
and shows app/views/messages/index.html.erb
there is a customer which wants his instance of the platform to display views differently (and changes cannot be done with css only).
solution i think of would be
create directory app/views/#{customername}, which would have same structure as app/views, but would only have views which have to override default ones.
setting an array constant containing list of views which have to be overriden (if not, they should load the default views)
CUSTOM_VIEWS["messages"]=["index","show","edit"]
somewhere in the customer-specific config file
in all controller actions do something like
def index
respond_to do |fmt|
fmt.html do
if CUSTOM_VIEWS[params[:controller]].include?(params[:action])
#override default app/views/messages/index.html.erb with app/views/customername/messages/index.html.erb
render "#{customername}/#{params[:controller]}/#{params[:action]}"
end
end
end
end
or is there better/faster solution/plugin to do that?
This should help:
http://railscasts.com/episodes/125-dynamic-layouts
i believe "view_paths" along with "prepend_view_path" can be an answer to my question
for example
http://www.axehomeyg.com/2009/06/10/view-path-manipulation-for-rails-with-aop/
upd:
solved with simple add to application_controller
def override_views
if APP_CONFIG['pr_name']!=nil
ActionController::Base.view_paths=[RAILS_ROOT+"/app/custom_views/"+APP_CONFIG['pr_name'],RAILS_ROOT+"/app/views/"]
end
end
where APP_CONFIG['pr_name'] is specific product name.
basically what it does is loading custom view from app/custom_views/customername/ if it exists for specific controller action, if not it loads default view from app/views/
Related
In ActiveAdmin, when there are no items for the model (in my example User), it shows a default 'There are no Users yet. Create one'.
How can I remove this message?
Is there the possibility of customizinig it on per-page basis, that is having a particular message for a particular ActiveAdmin page?
This is a MonkeyPatch:
Create a new file in lib folder and copy:
module ActiveAdmin
module Views
# Build a Blank Slate
class BlankSlate < ActiveAdmin::Component
builder_method :blank_slate
def default_class_name
'blank_slate_container'
end
def build(content)
super(span(content.html_safe, class: "blank_slate"))
end
end
end
end
Customize the content variable in build method to change the default message.
For now you cannot do it by ActiveAdmin settings. Look issues in
repository.
You can render any html or erb.html in your resources
You may use poorly documented (but not so monkey-path) blank_slate_link index page option. It lets you override this message in any of your ActiveAdmin's resource index page.
See https://stackoverflow.com/a/72529909/1744707 for details.
I have two Model/Controllers which are essentially duplicating data (just on different pages). When I iterate through a collection on one of the controllers, it works just as intended, however when I run the collection through the partial on the other controller, it creates another "object"
def show (users_controller.rb)
...
#missions = #user.missions
#mission = current_user.missions.build
...
end
def index (missions_controller.rb)
...
#missions = #user.missions
#mission = current_user.missions.build
...
end
When I call render #missions (app/views/missions/_mission.html.erb) on both the show.html.erb and index.html.erb files. It works as intended on the Users_controller but creates an extra "object" on the Missions_controller. It seems to be rendering both the #mission and #missions variables in the controller when rendering the collection.
Why and how can I fix this? I've tried moving the partial to a shared view directory, but the problem remains. I'm assuming it has to do with how I named my instance variables? I'm super stumped. Thanks guys
This is just a guess, but I would say this is likely happening because the mission you're building is included in #user.missions. Criteria aren't evaluated until they're actually used (by calling .all or .each or something) so by using current_user.missions.build you're adding an empty mission to the end of #user.missions... assuming that current_user and #user are the same.
So you can probably fix this by changing the call to #missions = #user.missions.all which will force it to be evaluated immediately, before the built mission is added to the end.
As I said, just a guess though!
right now I am trying to generalize some of my code. So far it went well, I wrote a few mixins which I can dynamically add to Controllers or Models in order to get things done while obeying DRY.
But with my "Searchform-Helper" I hit a corner in which, right now, I am a bit clueless.
I have a mixin 'SearchIndexController' which adds the methods needed to search for data within a searchindex-table.
After including the mixin I can initialize search-actions within the according controller calling this method:
def init_searchaction(object, name=nil)
singular = object.to_s.classify
plural = singular.pluralize
name = "search_#{singular}".to_sym if name.nil?
unless self.respond_to?(name)
define_method(name) do
# init
success=false
#TODO
# >>> DRAW NEW ROUTE TO THIS ACTION <<<
# evaluate searchform input for Searchindex-Call
needle = params[:query]
success, x, notice = execute_search("#{singular}", needle)
# send selected/filtered data to page
respond_to do |format|
format.js {
render :update do |page|
page.call "sidx_updateSearchResultContentAtIdTag", "##{plural.downcase} tbody", "#{render x}" if success
page.call "sidx_updateNotice", success, "#{notice}"
page.call "sidx_stopSpinner"
end
}
end
end
else
logger.warn("#{__FILE__}:#{__LINE__}:#{self.to_s}: search-action for '#{self.class.name}' can not be created, it already exists!")
end
end
So lets say I have a User-Controller. Within the Userform I have the need to search for several objects. Lets assume I want to be able to search for users, departments and clients... with my mixin I'd just have to initialize the searchactions like this:
init_searchaction :user
init_searchaction :department
init_searchaction :client, :find_clients
these would create actions within the including controller that are called
search_user
search_department
find_clients
The only thing missing is a way to get a route for them. I don't want to have to define the route upfront. I just want to 'init_searchaction' and have the mixin create the necessary route.
So... would it be possible to add the route to the accoring search-action from withing the mixins init_searchaction method dynamically? I think the necessary code would be placed at the #TODO mark in the code example above. But I still haven't found out how to do it... I mean, actually I would be surprised if it would not be possible.
Would anyone have an idea as how to do this? Thanks in advance for any idea that leads to the solution!
You can add work around standart dynamic route
match ':controller(/:action(/:id(.:format)))'
change it to your goals and enjoy :)
I have a variable that I need globally available throughout my app (so I've set #account in the applicationController).
However, a plugin that I have needs access to the same variable.
Note: This variable is distinct on each request.
What is the best way of creating this architecture?
Maybe something like this will work:
class Account
def self.current
#current
# or: Thread.current[:current_account]
end
def self.current=(a)
#current = a
# or: Thread.current[:current_account] = a # ..if you want to be thread-safe.
end
...
end
# your controller's before_filter:
def assign_account
...
Account.current = #account # But remember to set nil if none found!
end
# Any code in your app (view, model, almost anything):
<%= Account.current.name if Account.current %>
Setting #account in your app controller doesn't make it globally available throughout the app - models can't access it for example. Any instance var set in the controller will be available only in the controller or views. If the plugins have controller and view code then this code should be able to access the variable in the normal way, as long as the variable is set before the plugin controller code runs for example.
If you provide more details about what you want to do (ie where/how you want to access #account) then someone may be able to suggest a good approach.
Let's say that I have a widget that displays summary information about how many posts or comments that I have on a site.
What's the cleanest way to persist this information across controllers?
Including the instance variables in the application controller seems like a bad idea. Having a before filter that loads the data for each controller smells like code duplication.
Do I have to use a plugin like the Cells Plugin (http://cells.rubyforge.org/) or is there a simpler way of doing it?
Presumably, you have a single partial that displays this info. You can put the methods that fetch the data you need in ApplicationHelper or as class methods on whatever model(s) you're getting the data from. Then call that method in the partial when you need to display it.
I wound up doing something similar to this:
In controllers/application.rb
def load_sidebar
#posts = Post.find(:all)
end
To include the sidebar in various actions I did this:
before_filter :load_sidebar, :only => [ :index ] #load from application.rb file
I made the sidebar into a shared partial.
def load_sidebar
#posts = Post.find(:all)
end
You mentioned that you were displaying summary info. If you don't really want to load all of your posts into memory, you can do the following.
def load_sidebar
#post_count = Post.count(:id)
end