I've got a form which allows me to add/edit categories and sub categories within the one form. This form uses AJAX and to test it I've been using Capybara with some selectors.
The problem is with the selectors there seems to be subtle differences between when I'm creating a new category with sub categories to when I'm editing a category with sub categories.
Here is my create scenario:
#javascript #wip
Scenario: Create new category with sub categories
Given I am on the new category page
When I fill in "Name" with "Main" within the parent fields
And I follow "Add sub category"
And I fill in "Name" with "Sub1" within the 1st sub category fields
And I follow "Add sub category"
And I fill in "Name" with "Sub2" within the 2nd sub category fields
And I follow "Add sub category"
And I fill in "Name" with "Sub3" within the 3rd sub category fields
And I press "Save"
Then I should be on the "Main" category page
And I should see "Main"
And I should see "Sub1"
And I should see "Sub2"
And I should see "Sub3"
This works with selectors:
when /the parent fields/
"table tr:nth-child(1)"
when /the (\d+)(?:st|nd|rd|th) sub category fields/
pos = $1.to_i + 2
"table tr:nth-child(#{pos})"
On form:
= form_for #category do |f|
%table
%tr
%td= f.label :name
%td= f.text_field :name
%tr
%td(colspan=2)
%b Sub categories
- f.fields_for :children do |child|
= render "child_fields", :f => child
%tr
%td= link_to_add_fields "Add sub category", f, :children
%tr
%td= f.submit 'Save'
child_fields partial:
%tr.subs
%td= f.label :name
%td= f.text_field :name
When I use the same selectors though in my edit scenario I cannot select the 2nd category. Here is my edit category feature:
#javascript #wip
Scenario: Edit category with sub categories
Given a category exists
And category "Books" has sub category "Fiction"
And category "Books" has sub category "Non-Fiction"
And I am on the edit page for category "Books"
When I fill in "Name" with "Cars"
And I fill in "Name" with "Coupe" within the 1st sub category fields
And I fill in "Name" with "Sports" within the 2nd sub category fields
And I press "Save"
Then I should be on the "Cars" category page
And I should see "Cars"
And I should see "Coupe"
And I should see "Sports"
If I change my selector to:
when /the (\d+)(?:st|nd|rd|th) sub category fields/
pos = $1.to_i * 2 + 1
"table tr:nth-child(#{pos})"
Then it works for edit but not the new scenario.
Is there a way to use the same selector for both new & edit scenarios in my case?
Am I better using a different type of selector on my form? If so does anyone have any recommendations?
Use an id on the unique elements, and class combinations on repeated elements. With the right combination of class and id selectors you will always arrive at a unique child. Keep in mind you can group selectors on the one element.
So
Given a category exists
wait_for_xpath = '//element(#class = "categoryClass")'
And category "Books" has sub category "Fiction"
wait_for_xpath = "//element(contains (#class, 'categoryClass') and (#id, 'bookId'))//element(#id='fiction')"
etc
Related
I'm building a form for a class with a belongs_to association, and the parent class is identified by ID and has a ton of records - a select doesn't make sense at all. I would like to just ask for the ID of the parent record instead. I tried just changing the input type:
= semantic_form_for #child do |f|
= f.input :parent, as: :number
But that renders the incorrect name on the input field:
<input name="child[parent]" type="number">...</input>
So I swapped the input name to parent_id:
= semantic_form_for #child do |f|
= f.input :parent_id, as: :number
This renders the input as I want, but it doesn't hook the validations up correctly because they are attached to the parent association rather than parent_id.
class Child
belongs_to :parent
validate do
if parent.name != "valid name"
errors.add :parent, "is invalid"
end
end
end
That validation attaches to parent instead of parent_id so it doesn't render on the form. Attaching to parent_id also doesn't feel right.
What's the correct way to do this?
I have a drop-down menu that lists a collection of locks. I would like to set two params when an option is selected:
:name => l.name (which works with the code below)
:device_id => l.id
<%= f.select(:name, Lock.all.collect {|l| [ l.name ] } ,{:include_blank => true} ) %>
I've tried passing the value in a hidden_field, but the field isn't aware of the lock that was selected. Any input is much appreciated.
Hi you can do this:
<%= select_tag(:name, options_from_collection_for_select(Lock.all, :id, :name, params[:name]) )%>
or in your controller add this code:
#locks = Lock.find(:all)
and in your views
<%= select_tag(:name, options_from_collection_for_select(#locks, :id, :name, params[:name]) )%>
when you submit your form that contains this select_tag the params[:name] will get the selected name from the url of your app.
Hope it helps.
So You need to get two values in controller side ?
Ex:-
I have below values in my db
ID Name
4 gggg
5 tttt
2 iiii
So dropdown will show the all names gggg,tttt,iiii if you select tttt from dropdown in server you required both 5, tttt right?
Then you need to use below code
In controller
#locks = Lock.all.map{|l| [l.name, "#{l.id};#{l.name}"]}
In your view
<%= select_tag(:name, options_from_collection_for_select(#locks) )%>
So it will send the both id and name values saparated by ";" .
In your controller you need to split by ";"
We have a table with Categories containing unique categories. And our posts should link to any of these categories. I tried to add checkboxes for selecting the categories in the following manner:
Add the checkboxes containing the categories in a field called "post[categoriesss][]", containing as value the :id of the category.
Update the new and update method to take these these ids and collect the associated Categories with them, and then add each category to the categories attribute through the << operator as stated in the documentation.
We added the code to new and update to be sure not to have to do this in multiple controllers.
However we get the following error:
undefined property or relationship '<<' on Category
What are we doing wrong here? Is there another method to achieve our goal? Our code is below.
class Post
include DataMapper::Resource
property :id, Serial
has n, :categories, :through => Resource
def self.new(hash={})
if hash.key? :categoriesss
hash[:categoriesss].each do |category|
categories << Category.get(category)
end
hash.delete! :categoriesss
end
super hash
end
end
class Category
include DataMapper::Resource
property :id, Serial
property :name, String, :required => true
has n, :rekenservices, :through => Resource
end
<% Category.all.each do |category| %>
<label>
<input type="checkbox" name="post[categoriesss][]" value="<%= category.id %>" />
<%= category.name %>
</label>
<% end %>
UPDATE:
I now changed the names for the checkbox back to categories and updated the new and update methods to this:
def self.new(hash={})
if hash.key? :categories
hash[:categories].map! {|id| Category.get id}
end
super hash
end
def update(hash={})
if hash.key? :categories
hash[:categories].map! {|id| Category.get id}
end
super hash
end
Adding categories the first time works. When updating checking an extra category works great as well. Unchecking a category however yields an error message:
columns category_id, post_id are not unique
I have a Rails app that is using the simple_form gem. I have two models that are related, trades and stocks. In the form for trades, I want users to be able to enter their stock ticker symbol in a text field. Currently, I'm using the association function which renders a select box. The problem is that I want a text field instead since I have about a thousand stocks to choose from.
Is there a way I can do this (with or without Simple Form)?
the models:
class Trade < ActiveRecord::Base
belongs_to :stock
end
class Stock < ActiveRecord::Base
has_many :trades
end
the form on trades#new
<%= simple_form_for(#trade) do |f| %>
<%= f.association :stock %>
<% end %>
You should be able to just use this syntax:
<%= f.input :stock_id, :label => 'Enter your ticker:' %>
The problem here is that the user will not know what :stock_id is, as it's a reference to one of your many Stock objects.
So you probably want to implement a simple jquery autocomplete interface that returns a list of stocks like so:
[{:ticker => 'AAPL', :name => 'Apple Inc', :id => 1}, {:ticker => 'IBM', :name => 'International Business Machines', :id => 2}, etc ]
You can then display something like this as autocomplete results:
AAPL - Apple Inc
IBM - International Business Machines
and allow the user to select the one they are looking for. Behind the scenes you capture the :id and use that as your associated :stock_id.
You will need to add a stocks_controller action that takes a string and looks up Stocks based on a partial ticker and returns a max-number of stocks like 20.
def search
ticker_query = "%#{params[:ticker]}%"
stocks = Stock.where('ticker LIKE ?', ticker_query).limit(20)
render :json => stocks
end
I'm using Rails 3.0.7 with awesome_nested_set and I'm trying to create a nested form which will allow me to enter a category and sub categories all in one create form.
Here is my category model, controller & form
category.rb
class Category < ActiveRecord::Base
acts_as_nested_set
end
categories_controller.rb
class CategoriesController < InheritedResources::Base
def new
#category = Category.new
3.times { #category.children.build(:name => "test") }
end
end
form
= form_for #category do |f|
-if #category.errors.any?
#error_explanation
%h2= "#{pluralize(#category.errors.count, "error")} prohibited this category from being saved:"
%ul
- #category.errors.full_messages.each do |msg|
%li= msg
.field
= f.label :name
= f.text_field :name
%p Sub categories
= f.fields_for :children do |child|
= child.text_field :name
.actions
= f.submit 'Save'
The problem here is that I only end up with one sub category in my form and it doesn't have name set to 'test' so I don't believe that it's actually the child of the category showing here.
What am I missing here?
Can this be done?
Is there an easier way?
Update
If I change my form to the following then it displays three sub categories each with name set to 'test'. This will not save correctly though.
%p Sub categories
- #category.children.each do |sub|
= f.fields_for sub do |child|
= child.label :name
= child.text_field :name
%br
Found my answer and wrote a wiki page about it here:
https://github.com/collectiveidea/awesome_nested_set/wiki/nested-form-for-nested-set