How do you change the displayed order of ActiveScaffold "actions"? - ruby-on-rails

I am using ActiveScaffold in a Ruby on Rails app, and have replaced the default "actions" text in the table (ie. "edit", "delete", "show") with icons using CSS. I have also added a couple of custom actions with action_link.add ("move" and "copy").
For clarity, I would like to have the icons displayed in a different order than they are. Specifically, I would like "edit" to be the first icon displayed.
I seem to be able to change the order of the action_links by the changing the order of definition in the controller. I have also been able to change the order of the default actions by first config.actions.excluding everything, and then adding them with config.actions.add in a specific order.
However, my custom actions always seem to appear before the default actions in the list.
Ideally I would like them to display "edit" "copy" "move" "delete" (ie - built-in, custom, custom, built-in). Can anyone suggest how I might do this?
One idea I had was to re-define "edit" as a custom action (with the default functionality), but I don't know how to go about this either.

Caveat: I don't know ActiveScaffold. This answer is based on me reading its source code.
It looks like the action_links variable is a custom data structure, called ActionLinks. It's defined in ActiveScaffold::DataStructures.
Internally, it has a #set variable, which is not a Set at all, but an Array. ActionLinks has an add, delete, and each methods that serve as gatekeepers of this #set variable.
When displaying the links, ActiveScaffold does this (in _list_actions.rhtml):
<% active_scaffold_config.action_links.each :record do |link| -%>
# Displays the link (code removed for brevity)
<% end -%>
So, short of extending ActiveScaffold::DataStructures::ActionLinks to add a method to sort the values in #set differently, there doesn't seem to be a way to do it, at least not generally.
If I were you, I'd add something called order_by!, where you pass it an array of symbols, with the proper order, and it resorts #set. That way, you can call it after you're done adding your custom actions.

Related

Ruby on Rails - Update multiple data in a table with select (bulk edit)

(Rail 5 beta 3)
I have a table on an index page (action) of a view with around 15 columns. Some of them are for text and some of them are for integers only. Every entry of this list (table) will be filled out by a 'form_for' form (in new or edit action).
For editing or deleting there are links with each list entry in the index view leading to the corresponding show, edit or destroy actions. This all works well. Some of these entries are entered by a select with pulldown on the new or edit view. This works well, too.
But if one of these selects should be changed for more than one entry in the list it takes too much time to click on 'edit', change the select and click on submit at each list item. To make this a better user experience I would like to be able to change the selects in the list (table) directly. It would be good to have the select/pulldown in place. The change of the state or choosen entry should than be saved in place as well or with an extra button ("save changes") above/below the table.
To say it in short:
I want to update multiple entries in a table in an index view without editig each single entry via edit view. The dates will be changed by a select and the data should be saved by a submit button on this page
Has anybody an idea how I can solve this?
Try best_in_place gem. It can solve the problem you have quoted. here are some links to it
https://github.com/bernat/best_in_place
http://railscasts.com/episodes/302-in-place-editing?view=asciicast
Your original text wasn't that confusing to me...
You want what's called a bulk edit feature. Easiest way would be to set up a new target at the controller level specifically to handle this request. I'll give you the pseudocode and it should be easy enough to fill in the blanks, but essentially:
Create a "bulk edit" form (the drop down select menu above the table)
Create a controller method to handle the bulk edit (controller#bulk)
Update routes.rb to direct a URL to that new method
Handle the bulk update in the controller and redirect back to index upon completion (cheap way of updating the page after editing is done).
Note: I'm assuming your model name is "Resource" because you did not specify what it actually was
On your index page, you want HTML like:
<form method="POST" action="/resources/bulk">
<select name="bulk_value">...</select>
</form>
On change/form submit/whatever, submit that form.
If you're using resourceful routing, you can hook this into config.rb via:
resources :resources do
post :bulk, on: :collection
end
Otherwise, hook the route however you see fit.
Then, in your controller:
def bulk
value = params[:bulk_value]
Resource.update_all value: value
redirect_to {resources_path}
end
Now, you said index view, so I am assuming you want all. But if you just want a subset, you can pass the preferred IDs along with the form as a hidden field, then use a where clause to filter, i.e.
Resource.where(id: parmas[:id_array]).update_all(value: value)
Anyway, that should get you down the right path.

Ember: How to link to sections and actions (without nesting routes)

Let's say that I have a blog where each post can have several sections and comments and I'd like to use a hard-links to navigate and operate on this. There are several samples using some pseudo-code, of course they doesn't work, just demonstring my intends :)
Of course /blog.html#/posts/1 uses PostRoute, PostController etc and uses :post_id for finding object - that's obvoius.
How can I pass (and then access) additional params which doesn't change the controller but I can use them to navigation. ie /blog.html#/posts/1?section=123 should use the same route, controller and view as it was just Post, but I'd like to read the section and just navigate to section with #123
/blog.html#/posts/1/?comments=456 - actually should behave like section from point 1, but navigates to comment and optionally add some class to the container.
Other case: I'd like to go to section 123 AND additionally edit it with link like: /blog.html#/posts/1?section=123&action=edit. Now I'm using a button with an action like {{action editSection section}} and {{#if isEdit}} but I'd like to be able to reflect this in URL and also go to this state from URL (de facto my post can have several different modes not only preview/edit, therefore it should be accesible by the link).
I hope that cases makes sense, TBH I have no idea in which direction should I go. Tried with nested routes, but I'd like to avoid changing the controller. Also have no concept how to reflect the action in the URL...
I'm using Ember 1.1.2
You can use the model method of the route to handle such parameters, separate them from the model parameter and set the appropriate controller state.
Another approach would be to use nested routes that will render un-nested views(and controllers) - as explained towards the bottom here.

Where to put reusable HTML code in rails?

I'm writing a rails app that allows users to delete records of various sorts. After pressing a delete button, I'd like to show a confirm dialog using bootstrap. I'd like to use this same dialog in several of my views, so I'll need to include the same HTML snippet in most of my pages.
I'm new to rails and I'm still learning the conventions. Can anyone suggest the best (or standard) place to put the dialog code? Should it be a partial in views/layouts/_confirm_delete_dialog.html.erb, should it go inside application.html.erb, or should I put it somewhere else?
Thanks in advance for your advice,
D.
Within your Views folder, you can create a general folder (called whatever you want). If you have a variable that you need to pass through to the general layout, you can definitely do so, but you will want to make sure that the information that you're passing through doesn't cause conflicts with the fields pulled from the model. For example, if you have two models and one has a public field but the other doesn't then you will not want to have a generic message that is using the public field. However, something like the created_at or updated_at would be okay.
You would use a code similar to,
<%= render 'general/simple_message', :f => f %>
In your views folder, you would have a directory called general and a file called _simple_message.html.erb.

Still having a hard time with RoR MVC approach

I suppose it should do justice to state what I think I know so far as well as what I've done:
1) I created the app and did my first db migration; I now have my dev, test and production databases. The dev db has a table called 'wines'.
2) I made a scaffold which created the necessary files.
3) The basic index/update/destroy methods are set up and I can browse the pages.
4) From what I gather, the ActiveRecord class "Wine" automatically inherits properties from the database? Each column is a property and each row in the table 'wines' is a potentially instantiated object which is called from the wine_controller script.
The problem I'm having now is that I want to create a common layout that all controllers use. The only things that will change will be the page title, potentially some <link> tags in the header, the <body> attributes (javascript onload events most likely) and whatever lies inside the <body> tag.
I find myself looking up functions that will do what I want (like "favicon_link_tag", "stylesheet_link_tag" and "auto_discovery_link_tag"...) but I can't find the right place to PUT them! I know this has something to do with my lack of understanding of how things are executed/inherited. For example if I were to declare #pageTitle in application_controller.rb and use #pageTitle in ApplicationHelper it won't work. Or even using "stylesheet_link_tag" in application_controller.rb throws an error. I'm just not getting something.
How does each thing relate to another in terms of chronological execution, scope, etc.?
In your "app/views" directory there is a folder called "layouts." By default there should be an "application.html.erb" file in there, but if there isn't you can create it.
Your "application" layout file is the default layout file used by any view. However, if you want a particular controller to use a different view, you can override this. See this railscast, and this one is helpful too.
The main thing to understand is the content from any particular view will show up wherever the yield method appears in your application layout. The main 'yield' block gets the view file specified by your controller action, but you can mark anything inside any view to be passed to another yield block instead. For instance, the "title" example you gave could be passed to the head of your application layout. See this railscast for a detailed example of that.
For more, you should read the Rails Guide, and you might want to consider picking up a Rails starter book.
I got my feet wet with "Beginning Rails 3," which was a phenomenal introduction to the framework. A couple days with that book and it was all making sense to me, and I was developing faster than I ever had before. Rails rocks once you get to know it, but it's definitely worth going through a book.
Please continue to ask questions, I'll help if I can :)
-EDIT- To answer your question about control flow, it basically works like this:
Your browser sends a GET request for a particular URL.
The router takes that request, matches it to a controller action, triggers that controller action, and provides the controller any parameters associated with the request. For instance: if you requested example.com/posts/123?color=red this would trigger the SHOW action of your posts_controller, and would pass {:color => 'red'} to the params hash. You would access that using params[:color]
The controller action does its thing, and when it's done it renders output. By default it renders whatever view is located in app/<controller_name>/<action_name>, and will whichever file matches the extension appropriate to the request (ie an AJAX request would trigger <action_name>.js.erb and a GET request would trigger <action_name>.html.erb.
You can override this using the render method, for example by passing render 'foo/bar' to render using the view for FooController, Bar action instead of your current action.
Note that no matter what you render, the data available to the view is whatever is in the specific controller action the router triggered, not the controller action that would 'normally' render that view.
The view file is parsed using the data from the controller that called it. If you have any content_for methods then the view code that is inside the content_for block will go where you tell it, otherwise everything else will go to the main YIELD block in your application layout (or whatever layout your controller specified instead).
The application layout is parsed, and the content from the view is inserted into the appropriate areas.
The page is served to the user.
That's a simplification in some ways, but I think it answers your question. Again, feel free to keep asking :)

Fallback format in rails

for my CMs i want to be able to easily add new themes, my idea was to simply add a mime type for the new theme (so application.theme1.erb would work).
but for 99% of the themes im not going to want to change the views, well not all of them.
is there someway to have rails fall back on html if the themed view isnt present?
I'm pretty new to Rails, so this might not be a perfect answer:
you might want to try using querystring parameters as part of the route like described here:
http://guides.rubyonrails.org/routing.html#querystring-parameters
so eventually something like this would work
map.connect ':theme/:controller/:action/:id'
As I understand it, the theme would be available as params[:theme] in the controller. If no theme is specified you probably have to add another route like
map.connect '/:controller/:action/:id'
to handle that case.
In the i18n guide something similar is described for locales: http://guides.rubyonrails.org/i18n.html#setting-the-locale-from-the-url-params
Hope that helps.
It depends on how much of the layout you want to change with the themes.
If you build your HTML right, most of the things can be done through css. (changing fonts, colours, where the stuff show up)
Then it is quite easy to add just a theme parameter to style it.
If you don't want to do that, you can always create a separate layout for it, and assign that depending on the parameters passed in (or even set it as a session variable so you won't have it in the url).
Basically, for the default theme, you stick to the layouts/application.erb, then you have say layouts/theme1.erb which you then assign with a method
class ApplicationController
layout :decide_layout
def decide_layout
#session[:layout] || 'application'
end
end
Customizing the views would be possible just by doing something like this in your actions:
def my_action
render "my_action_#{#session[:layout]}" if #session[:layout]
end
if #session[:layout] is not set, it will render the default, otherwise it will render your themed view.
Of course, if you set the layout depending on user input, make sure to sanitize and check the layout parameter before.
I've just had this same problem with mobile_fu, which sets the format to :mobile for mobile requests.
It turns out that if an :action.:format.erb template isn't available, Rails will serve :action.rhtml as a replacement in any format.
I can't say whether this will work for layouts, but it certainly works for actions

Resources