wicked wizard passing arguments to steps - process

I would like to make a smooth streamlined process for placing customer orders.
I feel the best tool for the job is a wizard - unless there are other suggestions?
I need to pass arguments to next steps in my wizard.
My controller looks like this:
include Wicked::Wizard
steps :item, :customization, :upsell
def show
# #order_session_id = params[:order_session_id]
#order = Order.new
#order.order_session_id = params[:order_session_id]
case step
when :item
#items = Item.all # change with group...
when :customization
# item = Item.find(#order.item_id)
# item = Item.find(params[:item_id])
item = Item.find(1)
#customizations = item.customizations.split("|")
when :upsell
#upsells = Upsell.find_all_by_group_id(item.group_id)
end
render_wizard
end
def update
#order_session_id = params[:order_session_id]
#order.attributes = params[:order]
render_wizard #order
end
The view for item looks like this:
<%= form_for #order, url: wizard_path(:customization), :method => :get do |f| %>
<table border="1">
<% #items.each do |item| %>
<tr>
<td class="item_selection" onclick="$(this).children('input').attr('checked', 'checked');return false;">
<%= f.label :item_id, "#{item.name}" %>
<%= f.radio_button(:item_id, item.id) %>
</td>
</tr>
<% end %>
</table>
<div class="actions">
<%= f.submit "Continute" %>
</div>
<% end %>
I need to pass the selected item_id to the customization step so that the next part of the wizard can work.
How can I do this?
Thanks

You can pass parameters in the url after the step parameter.
wizard_path(:step_1, item: item)

Related

Rails SQL query in controller method

I want to retrieve brand name depending on brand_id which is mentioned in the another table products. My brand ids are stored as an array in 'brandids'. Here is my controller code.
def index
catids = Array.new
brandids = Array.new
#products = nil
if(!(params[:catid].nil?) && params[:catid].to_s.downcase != "all")
catids = arrayConvertion(params[:catid])
end
if(!(params[:brandid].nil?) && params[:brandid].to_s.downcase != "all")
brandids = arrayConvertion(params[:brandid])
end
if(catids.length == 0 && brandids.length == 0)
#products = Product.solr_search do
paginate :page => params[:page], :per_page => 3
end
#brands={}
#products.each do |p|
brand = p.BrandsTest.first(p.brands_test_id)
#brands[p.id] = BrandsTest.name
end
end
and the view for this controller is:
<% #products.results.each do |p| %>
<%= image_tag("Images/#{p.id}.jpeg",:alt => p.name) %>
<p> Name: </p>
<%= p.name %>
<p> Price: </p>
<%= p.price %>
<p> Discount: </p>
<%= p.discount %>
<p> Brand Name: </p>
<%= #brands[p.id] %>
<% end %>
Product Model code is:
class Product < ActiveRecord::Base
belongs_to :brands_test
belongs_to :categories_test
attr_accessible :id, :name
searchable do
integer :id
text :name
integer :brands_test_id
integer :categories_test_id
end
end
What query should I need to add and where I have to add?
Please help me with this.
#products = Product.solr_search do
with :brands_test_id, brandids[0..brandids.length]
paginate :page=>params[:page], :per_page=>3
end
#brands={}
#products.each do |p|
brand=Brand.find_by_id(p.brand_id)
#brands[p.id]=brand.name
end
views:
<% #products.results.each do |p| %>
#other code
<p> Brand: </p>
<%= #brands[p.id]
<% end %>
I don't sure if I understood what are you trying to do.
I did some modification according my app with the answer that you gave.Here is the controller part.
if(catids.length == 0 && brandids.length == 0)
#products = Product.solr_search do
paginate :page=>params[:page], :per_page=>3
end
#brands={}
#products.results.each do |p|
brand=BrandsTest.find_by_id(p.brands_test_id)
#brands[p.id]=brand.name
end
end
Here is view part:
<% #products.results.each do |p| %>
<%= image_tag("Images/#{p.id}.jpeg",:alt => p.name) %>
<p> Name: </p>
<%= p.name %>
<p> Price: </p>
<%= p.price %>
<p> Discount: </p>
<%= p.discount %>
<p> Brand Name: </p>
<%= #brands[p.id]%>
<% end %>

nested resources with form_for losing first id

This is a strange error that has really got me bugged. First, some background.
I have the following nested resources in my config/routes.rb:
scope :requirements => { :protocol => 'https' } do
resource :user
resources :orgs do
resources :members
resources :events
resources :levels
resources :attendances
end
resources :sessions, :only => [:new, :create, :destroy]
end
Then, in app/controllers/levels_controller.rb I have:
def edit
#org = Org.find(params[:org_id])
#level = OrgLevel.find(params[:id])
end
def update
#level = OrgLevel.find(params[:id])
if #level.update_attributes(params[:level])
flash[:success] = "Level details updated"
redirect_to #level
else
render 'edit'
end
end
Finally, in app/views/levels/edit.html.erb, I have:
<% provide(:title, "Edit #{#level.name} for #{#org.name}") %>
<div class="hero-unit">
<h2>Edit "<%= #level.name %>" membership level for <%= #org.name %></h2>
<div class="row">
<div class="span6 offset3">
<%= form_for [#org, #level], :url => org_level_path do |f| %>
<%= render 'shared/error_messages' %>
<table class="editor">
<tr>
<td class="label_x">
<%= f.label :name %>
</td>
<td colspan="3">
<%= f.text_field :name %>
</td>
</tr>
</table>
<% end %>
</div>
</div>
</div>
The result of calling https://spot-macbook.local/orgs/55/levels/162/edit is normal, but clicking "Save Changes" results in a redirection to https://spot-macbook.local/orgs/162/levels/162 and the following error:
ActiveRecord::RecordNotFound in LevelsController#show
Couldn't find Org with id=162
Rails.root: /Users/ogod/Projects/rails_projects/nom_de_joye_app
Application Trace | Framework Trace | Full Trace
app/controllers/levels_controller.rb:71:in `correct_user'
Request
Parameters:
{"requirements"=>{"protocol"=>"https"},
"org_id"=>"162",
"id"=>"162"}
Note that the org_id has changed to "162" instead of "55". What am I doing wrong?
Doh!
Five seconds after I post this question, I realised there error and corrected it.
The original has the update method with the following:
redirect_to #level
This should be:
redirect_to org_level_path(#org, #level)
Such a simple error, but I was looking in the wrong place!

Update don´t get the value of local when doing an update using i18n

I have tried to use i18n internationalization in my application.
It works very well when I do a Show (index), Create, and Edit. My problem is when I do an update.
When I press the update button I don´t get the :locale value back
Normaly I get these values back.
--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
level: '5_3'
menu_item: '5'
menu_level: '5_3_1'
action: index
controller: communication_mails
locale: dk
The URL looks like:
localhost:3000/dk/communication_mails
When I press the Edit button I get these values back. (The “Button” is a link). Locale is still ok.
--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
level: '5_3'
menu_item: '5'
menu_level: '5_3_2'
action: edit
controller: communication_mails
locale: dk
id: '2'
The URL now looks like:
localhost:3000/dk/communication_mails/2/edit
My problem is when I now press the “Update” button under the form field the redirection don´t get the value of locale back... It instead uses the ID.
--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
level: '5_3'
menu_item: '5'
menu_level: '5_3_1'
action: index
controller: communication_mails
locale: '2'
The URL now looks like:
localhost:3000/2/communication_mails
My route looks something likes this:
scope "/:locale" do
resources :communication_mails
end
resources :communication_mails do
collection do
get 'communication_mails'
post 'communication_mails'
put 'communication_mails'
end
end
root :to => redirect("/dk/tests/")
match '/communication_mails/:id/edit(.:format)', :to => 'communication_mails#edit'
match '/communication_mails/:id/', :to => 'communication_mails#index'
match '/communication_mails', :to => 'communication_mails#index'
My Controller is made like this.
def edit
#communication_mail = CommunicationMail.find(params[:id])
#show_calendars = Calendar.where(:calendar_priority => '1')
#show_email_text = CommunicationMail.find_by_sql("SELECT calendars.id,
calendar_name, communication_mail_headline, communication_mail_text
FROM calendars LEFT OUTER JOIN communication_mails
ON communication_mails.communication_mail_calendar_id = calendars.id
WHERE communication_mails.communication_mail_priority = '1'")
end
def update
#communication_mail = CommunicationMail.update(params[:id], params[:communication_mail])
#show_calendars = Calendar.where(:calendar_priority => '1')
#show_email_text = CommunicationMail.find_by_sql("SELECT calendars.id,
calendar_name, communication_mail_headline, communication_mail_text
FROM calendars LEFT OUTER JOIN communication_mails
ON communication_mails.communication_mail_calendar_id = calendars.id
WHERE communication_mails.communication_mail_priority = '1'")
if #communication_mail
redirect_to communication_mails_path(:menu_item => '5', :level => '5_3', :menu_level => '5_3_1'),
:notice => 'Opdateringen af E-mail tekst lykkedes'
else
redirect_to communication_mails_path(:menu_item => '5', :level => '5_3', :menu_level => '5_3_1'),
:notice => 'Opdateringen af E-mail tekst lykkedes IKKE'
end
end
I have solved many questions by looking through these pages. But I can´t find an answer to this one.
I hope some one can help me out. Thanks in in advance.
UPDATE
My routes looks like this:
GET /:locale/communication_mails/communication_mails(.:format) communication_mails#communication_mails
POST /:locale/communication_mails/communication_mails(.:format) communication_mails#communication_mails
PUT /:locale/communication_mails/communication_mails(.:format) communication_mails#communication_mails
GET /:locale/communication_mails(.:format) communication_mails#index
POST /:locale/communication_mails(.:format) communication_mails#create
GET /:locale/communication_mails/new(.:format) communication_mails#new
GET /:locale/communication_mails/:id/edit(.:format) communication_mails#edit
GET /:locale/communication_mails/:id(.:format) communication_mails#show
PUT /:locale/communication_mails/:id(.:format) communication_mails#update
DELETE /:locale/communication_mails/:id(.:format) communication_mails#destroy
The form I use to send and update the data
<%= form_for(#communication_mail) do |f| %>
<table class="toggle_header2">
<tr>
<td class="nobr width50px font_size13 font_weight_bold color03 border_left">
<%= t('forms.calendar') %>
</td>
<td class="color03 border_right">
<%= collection_select(:communication_mail,
:communication_mail_calendar_id,
#show_calendars,
:id,
:calendar_name,
{:include_blank => true },
{:prompt => true})
%>
</td>
</tr>
<tr>
<td class="nobr width50px font_size13 font_weight_bold color03 border_left">
<%= t('forms.headline') %>
</td>
<td class="color03 border_right">
<%= f.text_field :communication_mail_headline, :class => 'width350px' %>
</td>
</tr>
<tr>
<td class="nobr align_top font_size13 font_weight_bold color03 border_left">
<%= t('forms.text') %>
</td>
<td class="color03 border_right">
<%= f.text_area :communication_mail_text, :class => 'width350px' %>
</td>
</tr>
<tr>
<td class="color03 border_left">
<%= f.hidden_field :communication_mail_priority, :value => '1' %>
</td>
<td class="color03 border_right">
<% if action_name == 'edit' || action_name == 'update' %>
<%= f.submit t('buttons.update') %>
<% else %>
<%= f.submit t('buttons.insert') %>
<% end %>
</td>
</tr>
</table>
<% end %>
If you pick your :locale value from params, you have incorrect approach in your routing.
Update: be sure you are passing :locale value to your routing helpers on update action.
This code will generate routes with scope only for index, show, new, create, edit, update, destroy actions.
scope "/:locale" do
resources :communication_mails
end
This code will add additional routes to :communication_mails, but without scope.
resources :communication_mails do
collection do
get 'communication_mails'
post 'communication_mails'
put 'communication_mails'
end
end
Solution is to combine. You have to define :scope for all of your :communication_mails actions.
scope "/:locale" do
resources :communication_mails do
collection do
get 'communication_mails'
post 'communication_mails'
put 'communication_mails'
end
end
end
Please read documentation about routing (it is basics): http://guides.rubyonrails.org/routing.html

Why is Rails displaying memory addresses on my page?

My view:
<h1><%= #territory.name %></h1>
<%= link_to 'List of Territories', territories_path %>
<%= render 'shared/address_form' %>
<table>
<tr>
<td><strong>Name</strong></td>
<td><strong>Street</strong></td>
<td><strong>District</strong></td>
<td><strong>Note</strong></td>
<tr>
<%= #addresses.each do |address| %>
<tr>
<td><%= address.name %></td>
<td><%= address.street %></td>
<td><%= address.district %></td>
<td><%= address.note %></td>
</tr>
<% end %>
</table>
The form I render here is:
<%= form_for [#territory, #new_address] do |f| %>
<div>
<p>
<%= f.label :address %><br />
<%= f.text_area :address %>
</p>
</div>
<div class='file-wrapper'>
<%= f.submit "Submit" %>
</div>
<% end %>
Here is the territories controller, where the instance variable addresses is defined:
class TerritoriesController < ApplicationController
def index
#territories = Territory.all
end
def show
#territory = Territory.find(params[:id])
#new_address = #territory.addresses.build
#addresses = #territory.addresses
end
.
.
.
Why is Rails displaying
#<Address:0x7e088224>#<Address:0x7e0881d4>#<Address:0x7e088134>#<Address:0x7e088094># <Address:0x7e087ff4>#<Address:0x7e087f54>#<Address:0x7e087eb4>#<Address:0x7e087e14>#<Address:0x7e087d74>#<Address:0x7e0bce48>
after the form and before the table?
Thanks
Thomas
Check your layouts (app/views/layouts/*). Most likely you have included some ERB code in the one that is being rendered with this page that displays these addresses. Is that the full code of your view?
Edit: I found your solution. Right now, you have <%= #addresses.each ... %>. The each method runs the block on all elements, and then returns the list of elements. You do not want this code to be displayed. Remove the = so that <%= is just <%
You have some view code somewhere (in a layout or a view helper) that is implicitly calling the to_s method of your Address model instances. Look for something like <%= #address %>.
As you have seen, the non-overridden behaviour of the to_s method is to output the memory address of the object instance.
Those are not memory addresses. Those are instances of your Address class. If you'd override the to_s method in that class, you'd see that output there instead. And the reason you see those object printed out is your use of <%=. Changing this line
<%= #addresses.each do |address| %>
to this
<% #addresses.each do |address| %>
should fix it.
First: I can see no form in your view.
Second: Your view looks ok.
Have a look at your layout files.

Saving all nested form objects in one go

I'm trying to build two forms, nested. But all the resources I've found so far deal with how to save the main object, maybe add or remove nested objects, but not saving the entire list elsewhere with the values of the form. Is there a way to do this?
Here're the model I'm working with. I'm trying to create a pc configurator which will allow you to choose different components and quantities, and then you would add to the basket.
So I'm working with three models. Configuration, Configoption, Item.
-- Configuration model
has_many :configoptions
-- Configoption model
belongs_to :configuration
has_many :items
def range
a = []
b = self.quantity_rng.scan(/\w/)
b.each do |p|
a << p.to_i
end
return a
end
-- Item model
belongs_to :configoption
scope :sorted, order('items.position ASC')
The idea is that every configuration has a set of options, say 5. For each of these 5 options there could be a number of available items. For example option 1 is the processor, 2 could be RAM and so on.
-- Configuration controller
def list
#configurations = Configuration.find(:all)
end
def show
#configuration = Configuration.find(params[:id])
#options = #configuration.configoptions
end
-- configuration/show view
<table>
<tr>
<th>Elements</th>
<th>Quantity</th>
</tr>
<%= form_for(:configuration, :remote => true) do |p| %>
<% #options.each do |option| %>
<tr>
<%= form_for(:option, :remote => true) do |f| %>
<% if option.items.count > 1 %>
<th id="<%= option.name %>"> <%= f.select option.name, options_from_collection_for_select(option.items.sorted, 'id', 'name')%></th>
<% else%>
<th id="<%= option.name %>"> <%= f.label(option.items[0].name) %></th>
<% end %>
<% if option.quantity_rng == nil %>
<th id="<%= option.name + "_qty" %>"> <%= f.label(option.quantity) %></th>
<% else%>
<th id="<%= option.name %>"> <%= f.select option.name, option.range, :selected => option.quantity%></th>
<% end %>
<% end %>
<% end %>
</tr>
<% end %>
</table>
So far things are actually good, I can give different items to the options and the .range method let's me say quantity_rng in an option "1,2,3" and will make it into the array [1,2,3] passed for a drop-down if needed.
But now comes the crucial part, actually adding what I selected to the basket. How do I capture what the user has manipulated in the drop downs and store it (not as changes to the configoptions themselves, but as a new object elsewhere?)
BTW I'm using remote => true, because I intend to put some validation rules from jQuery later on, but one step at a time ;)
Thanks a lot!
May be i dint understand well your idea but i thing you need to use p.fields_for as nested options. Look at http://apidock.com/rails/v3.0.0/ActionView/Helpers/FormHelper/fields_for and dot forget to define
def address_attributes=(attributes)
# Process the attributes hash
end
in your model Configuration