Destroying an entry using cucumber - ruby-on-rails

I have a Ruby on Rails application in which I'm writing a CRUD test suite for all of my pages.
The first three CRUD actions - Create, Retrieve, and Update I can do no problem.
What I'm having trouble with is the last one - Destroy - since I need to start from the index page of whatever model I'm testing, and all of the links have the same "Destroy" text. If I just follow "Destroy" I get an ambiguous match.
I realize this is probably pretty simple - but I'm new to cucumber and capybara.
Thanks!

If you are listing the elements in a table then you can select a specific element with specific text (for example, if you are testing deletion for users then you can select a table row which has the user fullname as the text.
Something like this:
When /^I click the 'Delete' button for the "([^"]*) user $/ do |value|
within(".users") do
page.find("tr", :text => value).click_link "Delete"
end
end

Related

Rails 5 Dynamically Load Nested Form

I'm working on a basic Rails app that currently has two models, Payperiod and Expense. A Payperiod has many Expenses, and an expense belongs to one Payperiod. I have my expenses resourced nested under payperiods, like so:
resources :payperiods do
resources :expenses
end
I am attempting to create an expense on the Payperiod show page. Ideally, I'd like to have a button for adding individual expenses. This is turning out to be trickier than I thought it would be. I know I need to use ajax to dynamically add the form for each expense and submit it but I can't figure out exactly how to make it work. In my Payperiod show.html.erb page I have a button with an id that I can click and make an action happen via jquery. My next step is to make this button render a form. I'm not sure if I can do this via jquery inside of an html.erb file, or if I should convert my payperiod show view to be show.js.erb.

ActiveAdmin - how to delete ALL objects (not only those on current list page) (Rails ')

On my ruby on Rails app using ActiveAdmin, I wish to delete not only the 30 Users displayed but all the 456 users (that's an example of course).
When I select "select all' and then confirm deletion, it only deletes the 30 users visible on the current screen page.
I want to select ALL users (across all view pages, not only the one I currently see), and then manually deselect the first 4 users (or any I would manually pick on the current view page). So not really deleting ALL users. that's my problem.
How to customize ActiveAdmin to be able to do this ?
Maybe something like this would work:
https://github.com/activeadmin-plugins/active_admin_scoped_collection_actions
Plugin for ActiveAdmin. Provides batch Update and Delete for scoped_collection (Filters + Scope) across all pages.
If you want to delete some users from a list of all of them, I suggest you to write a custom active admin action. Minimize your markup, make it easy to render for browser and prepare for the worst. If you have 1 million records, there is no way it will work properly, there is no solution for that.
I suggest you to accept the fact that user will delete records by using search, probably and if you literally want to be able to delete all you can provide a custom button delete all that will do that for you.
The alternative is write a custom active admin action with a lot of javascript to provide pagination. It's still a lot of custom code, no generic solution provided.
Last alternative, you can disable pagination for that active admin page, but you may have a lot of problems loading the entire table every time
You can override the default batch action to destroy/delete all the users like this:
ActiveAdmin.register User do
batch_action :destroy do |ids|
User.delete_all
redirect_to collection_path, alert: "Deleted all the Users!"
end
end
See this for more information.

How to trigger different actions based on submit button in rails

I have a form with a list of stuff, and an action already in place to update items.
I want to have another button, which when clicked triggers a different action to remove the selected items.
= form_for #new_item,:url => {:controller => "item_lists",:action => "update_list" } do |f|
- #items.each do |it|
%input{:type=>"hidden",:name=>"item_list[#{it.id}]position",:value=>it.position, :class=>'position'}
%textarea{:name=>"item_list[#{it.id}]field1"}
=it.field1
%textarea{:name=>"item_list[#{it.id}]field2"}
=it.field2
%input{:type=>'checkbox', :name=>'selected_items[]', :value=>it.id}
=(it.valid?) ? "" : it.errors.full_messages
%input{:type=>"submit", :value=>"Save changes", :name=>'save'}
%input{:type=>"submit", :value=>"Remove selected", :name=>'delete'}
This question seems to indicate I should inspect params in my action to figure out what was clicked. But that feels messy, my controller could quickly degenerate into a mass of ifs when I add more actions.
Is there a more elegant way to do this, i.e. get it to just route to the correct method?
Thanks for any help...
This doesn't really gel with REST. In REST and Rails you're typically going to have one action per endpoint, not decide on the endpoint based on some criteria in the request.
That being said, you can filter actions based on the submit button by checking the name of the button pressed. See this SO question.
I'd argue though that this is only appropriate if your form is doing slightly different things, like perhaps a submit button that updates in place versus a submit button that redirects somewhere afterward, e.g. "Update" versus "Update and Continue" (contrived, but you get what I mean).
Addressing your concern in the comments, your method wouldn't have to devolve into a long sequence of ifs. You could just write some code to determine which method to call based on the name of the submit button. A simple implementation might be:
# your form action
def update_list
send update_list_action
end
protected
def update_list_action
# just return the first action name found in the params
action = %w(save delete).detect {|action| params[action] }
"update_list_#{action}"
end
def update_list_save
# handle save
end
def update_list_delete
# handle delete
end
I would suggest you to add a dropdown menue with the option "delete", "update",... and add some jQuery code that observes the selected item and changes the action of your form depending on the value because you shouldnt use one action to update and delete objects! There should be one action for updating and one for deleting!

custom action for a nested resource without adding to routes

This is probably really simple but I have a nested resource lets say:
map. resources :book, :has_many => :pages
I write an action called "turn" that increases page.count by 1. How do I call this action using a link_to? Thanks a lot in advance.
It's hard to tell where your page.count comes in. In Railish, you would find pages.count (note the 's'). Further, count (and also size) is a read-only attribute on arrays and hashes et.al. provided by ruby that returns the number of elements. You don't set count.
Next, I'm not sure where your turn action is supposed to live, on the Book or the Page? And what is supposed to happen after it does what it does? Finally, a route is what makes an action an action -- without it, it's just a function.
For a moment, we'll assume you are trying to store the number of times a Page in a Book has been visited. It would be a better idea to have an instance variable called reads or times_viewed etc. in your Page model. Assuming your Book model is using restful routing, in Book's show action, you create an instance variable of the Page model being viewed and increment its reads attribute before rendering the view.
If you are trying to make a link sort of how 'Like' works in Facebook, meaning you want to update a record in a table without sending the user to a different page, you'll need to use link_to_remote* and some javascript. In that case, I'd just refer you to the Railscasts on that subject.
*I think as of Rails 3, link_to_remote became just link_to with :remote => true.

Where to put this code?

[Rails] Where to put this code?
I have a user1 and when another registered user2 sees the profile of user1, has some buttons on it: ['add as friend', 'give me your number', 'give me your email', 'ask her out', 'view photos']. The 1,2,3,4 are POST, with AJAX. Now, i have to make a new controller named 'ProfileActionsController' or i should put this code in the 'UsersController'?
or maybe a another posiibility? thanks ;)
You can do both. To avoid UsersController from becoming too bulky you should put it new controller which will help for maintainance .
You will most likely have to store some of these relationships in different database tables. For example, User has_many :friends. This design encourages a Friend model. Which leads to a FriendsController and to urls like POST /user/1/friend to create a friendship between the current user (user2) and user 1.
Those belong in a separate controller.
If you need more Ajax actions on a user, defining them in UsersController is the right place. "Give me your number", "Give me your email" and "View Photos", depending on requirements, could be hidden sections of the html, or simple Ajax GET requests to the UserController to render partials or JSON.
Those can stay on the UserController
GENERAL ADVICE: Always try to stay within the 7 actions for each controller (new, create, edit, update, index, show, destroy) - when you feel you need to define your own action, think about which of the 7 it is closest to. Can it be combined gracefully? If not, then is it acting on a separate concept?
If it's an action made on an user (i.e., that in someway modifies a user through its model), then ideally you should put those actions inside the users_controller.

Resources