Section or Controller based class-highlighting in Rails 3.2 views - ruby

I've looked at this article and am getting strange behavior in a HAML partial. When I access two different controller actions, one instance works while the other fails. Here's the code:
= link_to_unless_current(t('some.string', :en=>'SomeString'), '/url',{:class=>(controller.controller_name == 'randomController' ? 'current' : 'header-link')})
When I output = controller.controller_name in either view, I get 'randomController.' On the main listing page (where all objects are shown paginated), the class is not applied, but when moving to the 'show' page, the class suddenly appears. As the controller is the same in both (same string is printed in either case), why is it that the class isn't applied equally?
In general, is there a better way to style links based on the current controller, instead of checking the controller name? The current_page helper requires both controller + action, meaning it's not a fitting candidate here.

I'm going to mark this as the answer in case others stumble over the same problem. Hopefully this formats properly:
= link_to_unless_current(t('some.string', :en=>'SomeString'), '/url',{:class=>(controller.controller_name == 'randomController' ? 'current' : 'header-link')}) do
%span.current
= (t('some.string', :en=>'SomeString'
This can be obviously be cleaned up to remove repeated elements, and will probably end up as an application decorator using draper so that I can use it within any view on the site.

Related

Rails Active Admin unpermitted parameter

I have some problem/issues with active admin on rails, specifically unpermitted params error:
existing active admin parameter
here is the existing active admin parameter
model associated with the main model im working with
As per active admin documentation I should be doin right, as the other attributes for dispatch_information model is being accepted by rails and I was able to read and write with out any issues. Just with this recently added attribute "custom_attorney". Associations already set. and with out declaring an attr_accessor on model file it says this error
No method error
as it seems it cannot read or detect the column that I added for dispatch_information model, while in my console its already there.
When I add it with attr_accessor "while it should not, just to proceed on the form page" then I fill in the attributes need, im getting weird stuff in my console
Console view
as you can see it seems it being added inside efile_order hash instead of dispatch_information_attribute hash, and at the bottom part of the image you can see it says unpermitted parameters, even I added it inside the correct attribute block, we can also notice that the other attributes pf dispatch_information works really fine, just this recently added custom_attorney attribute. I already did everything like migration and other stuff.
Form Input
here is my form where we can see that input is on the same block where dispatch_defendant and dispatch_plaintiff is included and those two attribute works fine as well.
I really dont know what I missed here. TIA
The problem is that custom_attorney should be nested under dispatch_information_attributes you have it in the wrong place so it's unpermitted.
The correct way to do that is to add a block for those attributes and nest them.
- f.simple_fields_for :dispatch_information do |d|
- d.input :custom_attorney, :input_html => { id: 'new-attorney' }
It may be a good idea to provide an object for dispatch_information if you care for existing data. Assuming your ivar is named #e_filling_order then you should have the following.
- f.simple_fields_for :dispatch_information, #e_filling_order.dispatch_information || #e_filling_order.build_dispatch_information do |d|

Following Test Automation best practise of "Methods return other PageObjects" in Ruby

I am a big advocate of the Page Object Pattern (POP) as defined by the experts at Selenium:
https://code.google.com/p/selenium/wiki/PageObjects
A key view of theirs that I have always followed when using Appium with Java is:
"Methods return other PageObjects"
e.g. LoginPage loginPage = homePage.gotoLoginPage();
I am now trying to following POP using Calabash with Ruby and so have been writing code like this:
e.g. #login_page = #home_page.goto_login_page
However, since Ruby doesn't know what type of object #login_page is or #home_page is, you dont get any of the benefits of intellisense showing what methods are available for a given page.
Anyone know a good way around this?
As much as I appreciate and apply PO design pattern, as much I disagree with returning page object by page object. Page object should be independent and don't need to know about other page objects. Look at two examples:
You test form validation. Click on submit button returns page object which is subsequent in the workflow, but in this case you remain on page with validation errors. Your page object won't know about it and will return the other page.
Page which you get to after clicking a button may differ depending on the context (e.g. from what other page you got to current page). It can lead to having multiple versions of actually same method, which will return different page objects depending on context. This is not good and overcomplicates simple thing.
If you want to return current page object, you can benefit from it e.g. in Java, when you return this at the end of the method. Then you can chain all methods you execute as long as you are on the same page. But when it comes to the question 'how to implement returning different page objects' - answer is simple - 'just don't'. Please note wiki entry you quoted has not been updated for a good while and best practices has evolved since it was originally published.
It seems like you already have your solution. However for others and perhaps also for you the x-platform approach to calabash uses page objects so you could check out that implementation https://github.com/calabash/x-platform-example
An alternative method would be as follows. Not as neat as I would like (given the need to manually create new instances of subsequent pages), but available as an alternative option:
When(/^I buy a movie from the movie page$/) do
movie_page = MoviePage.new
movie_page.buyMovie("Test Movie")
purchase_page = PurchasePage.new
purchase_page.confirmPurchase
end
Found a way of getting this to work after much research and applying well known Java/C#/Obj-c principles to Ruby:
Given(/^I am on the launch page$/) do
#launch_page ||= LaunchPage.new
end
When(/^I open the set alarm time page$/) do
#set_alarm_page = #launch_page.goto_set_alarm_page
end
When(/^I open our apps from the home page$/) do
#launch_page.navigation_toolbar.open_our_apps
end
Then(/^I should see the homepage alarm time is (\d+)$/) do |alarm_time|
alarm_time_actual = #launch_page.get_alarm_time
assert_equal(alarm_time, alarm_time_actual)
end
As long as somewhere on the step definition class you explicitly create a new page object (in the above example: LaunchPage.new), then all subsequent pages will provide intellisense method/property values, since the resulting page types returned will be known by RubyMine.

Silverstripe 3: how to sort pages in the CMS sitetree by title, date etc

I'm looking for a working example of how to sort my pages in the sitetree by title by default. Ideally I only want to sort child pages of a certain type. In my case I want all my Gallery pages under the parent Portfolio to be sorted Alphabetically by their title.
This is for easy searching in the backend CMS as I know how to sort them in the template.
I have found these examples but not enough to work this out for SS3.1+
http://www.ssbits.com/tutorials/2011/custom-sorting-in-the-cms-sitetree/
https://github.com/silverstripe/silverstripe-cms/issues/848
Having a look at the examples you gave and the current Silverstripe source, there is a few ways you could go about this. My solution involves using Silverstripe's extension system to manipulate how the hierarchy is generated.
How the SiteTree is loaded
The way the CMS loads the site tree is a little lengthy so I will quickly simplify:
The template CMSPagesController_Content.ss (used for the pages section) has markup to lazy-load the linked tree view
The linked tree view (a function specified in CMSMain) calls a few internal methods to basically load the CMSMain_TreeView template
This template calls the SiteTreeAsUL function back in CMSMain
Note: SiteTreeAsUL allows us to hook in before returning using the extension system in Silverstripe though we don't want to manipulate
the HTML directly.
getSiteTreeFor, a function part of LeftAndMain, is called inside the SiteTreeAsUL.
getSiteTreeFor calls getChildrenAsUL, a function part of Hierarchy, which actually does the HTML building but most importantly, calls the correct "children" method.
I say correct children method as there is a few:
AllChildren
AllChildrenIncludingDeleted
AllHistoricalChildren
Children
Because getSiteTreeFor is called without specifying the children method, it uses a hardcoded default of AllChildrenIncludingDeleted.
Now, time to sort the children...
Calling the function AllChildrenIncludingDeleted does a few calls but what we want to know is that it internally calls the extension method augmentAllChildrenIncludingDeleted.
So, to do what you are wanting to do, you likely will want to write an extension for SiteTree with the extended function augmentAllChildrenIncludingDeleted. First argument is the list of all children which are stored as an ArrayList.
Technical Note: It actually can be an ArrayList OR DataList
because if there are no live children, it returns the raw result of
stageChildren which is a DataList.
While both have sort functions, they may act differently.
ArrayList provides a sort function which would allow you to do what you were intending.
Something like this should work:
class CMSSiteTreeSortingExtension extends Extension
{
public function augmentAllChildrenIncludingDeleted($Children, $Context = null)
{
if ($this->owner->ClassName == 'GalleryPage')
{
//Do your class specific sorting here....
}
$Children = $Children->sort('Title DESC');
}
}
And just set the extension against SiteTree (or Page if you want, should still work).
Disclaimer: I haven't personally tried this however it follows the standard pattern for how Silverstripe works with extensions so you shouldn't have a problem.
I've been searching for a way to achieve this in SS4 when I couldn't get the above code to work. This is what I've come up with.
use SilverStripe\ORM\DB;
class MemberPage extends Page
{
public function onAfterWrite(){
parent::onAfterWrite();
$pages = MemberPage::get()->sort('Title');
$sortIndex = 0;
foreach ($pages as $page){
//sort indexes start at 1
$sortIndex++;
if ($page->Sort != $sortIndex){
//we can't use $page->write() here, otherwise it'll cause infinite loops,
//we'll just have to run the query on the database directly
DB::query("UPDATE SiteTree SET Sort = {$sortIndex} WHERE ID = {$page->ID}");
}
}
}
}
It's not exactly 'the silverstripe way' but it works.

Smarty getting page content

I need to edit a page on prestashop, I've found that code
<ul id="idTab2" class="bullet">{$agencies->content}</ul>
And where should i search for that $agencies variable ?
I have found the text which is being displayed into that place in CMS.
However I'd that variable need to be define somewhere, am I right ? Anyone knows where should i search for that ? I'm new to prestashop.
Why am i asking for this ? I need to add another page for example
<ul id="idTab2" class="bullet">{$test->content}</ul>
- but I can't just simply add another page called test.
The {$agencies} variable is being set in a object derived from either the Controller or Module classes but to be honest it looks like you're working with code that has been customised (via a class override or a module) making it impossible to provide a definitive answer to your question without knowing more detail.
If you can locate the term 'agencies' in a file located under \controllers, \modules or \override in your installation, then you will be closer to finding your answer. It will be contained in a function call similar to:
$this->context->smarty->assign('agencies' , [some-variable]);
Note that the parameters to the function may also be passed as an array for multiple assignments.

What is The Rails Way for requesting an alternate view of all records?

I have a rails app that has a list of Products, and therefore I have an index action on my ProductsController that allows me to see a list of them all.
I want to have another view of the products that presents them with a lot more information and in a different format -- what's The Rails Way for doing that?
I figure my main options are:
pass a parameter (products/index.html?other_view=true) and then have an if else block in ProductsController#index that renders a different view as required. That feels a bit messy.
pass a parameter (products/index.html?other_view=true) and then have an if else block in my view (index.html.haml) that renders different html as required. (I already know this is not the right choice.)
Implement a new action on my controller (e.g.: ProductsController#detailed_index) that has it's own view (detailed_index.html.haml). Is that no longer RESTful?
Is one of those preferable, or is there another option I haven't considered?
Thanks!
Another way of doing it would be via a custom format. This is commonly done to provide mobile specific versions of pages, but I don't see why the same idea couldn't be applied here.
Register :detailed as an alias of text/html and then have index.detailed.haml (or .erb) with the extra information. If you need to load extra data for the detailed view you can do so within the respond_to block.
Then visitors to /somecollection/index.detailed should see the detailed view. You can link to it with some_collection_path(:format=>'detailed')
I'm not sure whether this is 'bettrr' than the alternatives but there is a certain logic I think to saying that a detailed view is just an alternative representation of the data, which is what formats are for.
After doing some reading, I think that adding a new RESTful action (option #3 in my question) is the way to go. Details are here: http://guides.rubyonrails.org/routing.html#adding-more-restful-actions
I've updated my routes.rb like this:
resources :products do
get 'detailed', :on => :collection
end
And added a corresponding action to my ProductsController:
def detailed
# full_details is a scope that eager-loads all the associations
respond_with Product.full_details
end
And then of course added a detailed.html.haml view that shows the products in a the detailed way I wanted. I can link to this with detailed_products_path which generates the URL /products/detailed.
After implementing this I'm sure this was the right way to go. As the RoR guides say, if I was doing a lot of custom actions it probably means I should have another controller, but just one extra action like this is easy to implement, is DRY and works well. It feels like The Rails Way. :-)

Resources