Record id with cucumber and pickle [Rails] - ruby-on-rails

I am using Cucumber, Webrat, and Pickle in conjunction.
When I write a scenario, I can do something like this:
Given a product exists with title: "Bread"
When I go to the edit page for that product
And I fill in "Title" with "Milk"
And I press "Save changes"
Then I should see "Successfully edited product."
And I should be on that car's page
Notice the for that product. This is something pickle provides which is very convenient for referencing the record for a product I'm checking the existence of. That last line, though, is not working.
Basically I am trying to make sure I am the show page for that record, but since I do not have an ID for it, I don't know how to reference it.
Any help?
Thanks!

To have a reference to the created product or anything else you can use naming that's provided by pickle:
Given product: "bread" exists with title: "Bread"
...
Then I should be on the showing page for the product "bread"
To handle this url you will need to add couple lines into /features/support/paths.rb:
when %r{^the showing page for the (.+)$}
polymorphic_path(model($1))
Also it could be useful to handle edit path for the model like this:
Then I should be on the edit page for the product "bread"
paths.rb:
when %r{^the edit page for the (.+)$}
polymorphic_path(model($1), :action => 'edit')

Related

How can I verify a user doesn't exist before shoveling the user in?

Rails newbie so bear with me...
I created a calendar app and the owner of the calendar can add other users to the calendar. I just realized that they can add the same user many times, which obviously I don't want. I've tried a bunch of different things including methods to check inside of the model, those didn't work... I was using includes to verify...
My current method in my controller is:
def update
if #calendar.calendar_admin?(current_user)
#new_user = User.find(params[:calendar][:user_ids])
if #calendar.users.includes(#new_user)
redirect_to user_calendar_path(#calendar), notice: 'This user has already been added to this calendar.'
else
#calendar.users << #new_user
if #calendar.save
redirect_to user_calendar_path(#calendar), notice: 'Your calendar has been updated.'
else
redirect_to user_calendar_path(#calendar)
end
end
end
end
end
No matter what, it gets stuck at "this user has already been added to this calendar", even if the user hasn't. I am shoveling the new user in but I'm not even sure if that is the right manner to add the new user?
Input?
You want to use include? instead of includes.
include? returns a boolean based on whether a set contains a specific item. includes is a different method and will return a non-nil value that is truthy.
You want to test if #calendar.users already contains a specific user. Unfortunately, includes sounds right, but it is used to add a table/model to join result (if I try to run your line it explodes).
So I suggest the following alternatives:
if #calendar.users.to_a.any{|uu| uu.id == #new_user.id}
this will fetch all users in an array and check if a user exists with the same id. This is easy to understand, but not optimal since it might retrieve a lot of data.
Probably better alternative is to use the database, and count if a user with your wanted id is linked:
if #calendar.users.where("users.id" => #new_user.id).count > 0

Using Wikipedia-Client Gem to Update Rails Database

My ruby and Rails is a bit rusty. I have a table in my database called institutes which has some of the columns filled. I want to use the Wikipedia-Client gem to fill some of the others. I want to use the name attribute to find the page on Wikipedia then use page.summary for the description attribute in my table and page.image_urls.first for the picture attribute. At the moment, I'm struggling to work out how I would go about this.
My current code is:
require 'Wikipedia'
Institute.each do |institute|
school = institute.pluck(:name)
page = Wikipedia.find(school)
description = page.summary
picture = page.image_urls.first
Institute.update!(description: description, picture: picture)
end
I'm clearly doing something wrong here to do with the selection and use of the name attribute to find the Wikipedia page, but can't quite work it out. I think even if I were to pluck the name correctly, it wouldn't assign anything to the right id.
If there's also a way to drop the "The" at the beginning of the name in the Wikipedia search if it exists in :name, that would also be helpful as it seems some institutes drop this on Wikipedia.
You can try to use something like this:
#use https://github.com/kenpratt/wikipedia-client
require 'wikipedia'
#select all Institutes through AR model
Institute.all.each do |institute|
#'institute' is an object, so we can get its name by dot operator
school = institute.name
#try to find school as is
#then try to find without 'The'
#and go ahead only if page exists
page = Wikipedia.find(school)
page = Wikipedia.find(school[3..-1].strip) if page.content.nil? and school[0..2].downcase == 'the'
next if page.content.nil?
description = page.summary
picture = page.image_urls.first
#update Institute object
institute.update!(description: description, picture: picture)
end

Capybara won't select item from select

I'm using Capybara to test a little Web app I'm writing. It refuses to select the right item from a select. Here's the code:
before do
fill_in 'Assignment', with: "blah blah blah"
select student.name, from: "assignment[student_id]"
end
I've tried every supported format in the "from" field. I've used the id, the name, and the label text to try and select the correct element. I've even booted the rails server in test, and manually ran through the steps in my test in the console. No matter what I do, capybara kicks back:
cannot select option, no option with text 'John Doe' in select box 'assignment[student_id]'
As stated before, I have kicked up the rails server in the test environment, and then manually added users to the database the same way I have done in my tests. I am 100% confident of the fact that there is indeed an option with text 'John Doe' in select box 'assignment[student].' This leads me to believe that I must be using the select method incorrectly. Can someone enlighten me?
Does the select from: need the select fields name or the ID?
Try it with the ID instead (assuming standard form style):
select student.name, from: "assignment_student_id"
If you inspect source on the select element you can confirm the fields ID.
Does it use the value of the option element rather than the text? Again, inspect and see what the value of "John Doe" is and see if it works by using student.id.
select student.id, from: "assignment[student_id]"
Lastly, have you tried the syntax in the documentation that includes the page?
page.select student.name, :from => 'assignment[student_id]'
The problem wasn't with the select code. I forgot how FactoryGirl's let works. I called build through a relationship on a User created by Factory Girl, and then tried assigning that result to student via let. Unfortunately, since let is lazy, it wasn't being created when it needed to be, so basically the page was getting called up before the student object was even created. I moved the code in my let statement into a before, and then assigned student using let and User.students.first.

Data inserted in Cucumber tests not populating Dropdown

DISCLAIMER: I am still a Rails/Cucumber newbie but I am trying to learn. I am still using the "web_steps" for Cucumber while I work through the RailsInAction book and I have experimented with writing my own steps. I understand why they were taken out and I will get there.
Problem:
In one of my Cucumber Scenarios I am populating some data and trying to use that data to populate a dropdown. The data is definitely being inserted, I know this because I wrote a step to test to see if the data is in fact there and it is.
When then DropDown is suppose to populated and I try "select" from that DropDown I get the error "*cannot select option, no option with text 'Steven' in select box 'result_winner' (Capybara::ElementNotFound)*"
I am sure I am missing something basic but I have lost about an hour to this now and I just need some help.
My Code:
The tests:
When I follow "Record new Result"
And the users "Steven, Joshua" exist
And I select "Steven" from "result_winner"
The test steps:
When /^the users "([^"]*)" exist$/ do |playerNames|
#names = playerNames.scan(/[\w']+/)
for name in #names
#newPlayer = Player.new
#newPlayer.name = name
#newPlayer.save
end
end
Then the view code in the _form.html.erb:
<p>
<%= f.label :winner %>
<%= select("result", "winner", #players.map {|p| [p.name, p.id]}) %>
</p>
The Controller:
def new
#result = Result.new
#players = Player.find(:all)
end
If I manually populate the development database with names and load it up in the browser, the dropdowns have data populated in them and work perfectly. I am pretty sure I am misunderstanding when/where test data is visible, or how to test for and select data from a dropdown.
Any help would be greatly appreciated.
It looks to me like a simple problem with the step sequence. You're visiting the page, and then populating the database, but the page doesn't get reloaded to take account of the new database values. If you swap the order of the first 2 steps around, I expect that would fix it.
To be clear, cucumber will literally step through your scenario one line at a time:
Load up the webpage (which doesn't contain your test data)
Insert your data into the DB
Look for that data in the dropdown (which won't be there as the page was loaded before the data was in the DB)
Your "the users "Steven, Joshua" exist" should be in a Given step.
It describes a state before an action is done.
Given the users "Steven, Joshua" exist
When I follow "Record new Result"
And I select "Steven" from "result_winner"

RESTful nested conventional routing

I have the model:
User -1---n- Transaction(amount,description, date)
User -1---n- TransactionImport -1---n- TransactonImportField(name,value)
(personal expense tracking app).
What I want to achieve is this:
User opens URL and pastes the CSV with the list of transactions.
User submits it.
System extracts data from CSV into TransactionImport (row) + TransactionImportField (cell).
User can choose which column means what (amount, description, date) from the imported data in TransactionImport(Field).
User click save and the system transfers TransactionImport into the Transaction.
What I can't seem to get right is the fact that step 3 creates multiple records of TransactionImport (and related TransactionImportField).
So doing POST /transaction_imports?csv=abcd is expected to produce one record if we would be RESTful. But the code is supposed to be something like this:
# TransactionImportsController
def create
result = TransactionImports.parse(params[:csv])
flash[:notice] = result.message
redirect_to transaction_imports_path
end
I am probably approaching the task from a wrong angle as I feel that implementation doesn't fit in tp the inherited_resources.
Could you please advise what would be the most conventional way of implementing this?
Thanks,
Dmytrii.
REST/HTTP has no expectation that doing POST will only create one record. That maybe the default rails behaviour, but you should not constrain your design because of that.

Resources