fields_for in rails 3 issue - ruby-on-rails

Converting another app from Rails 2 to Rails 3 - in one of my views I have this code:
<%fields_for "order[commission_attributes][]", commission do |f|%>
This is driven from the controller action below:
def edit
#order = Order.find(params[:id],:include=>[{:orderitems=>:item_schedules}, :memberids ],:order=>"orderitems.updated_at DESC")
#active_order_iems = []
#inactive_order_items = []
#order.orderitems.each do |oi|
oi_active = nil
oi.item_schedules.each do |is|
if (is.end_date > Date.today)
oi_active =true
break
end
end
#active_order_iems << oi if !oi_active.nil?
#inactive_order_items << oi if oi_active.nil?
end
#commissions = #order.commissions.find(:all)
#ordertypes = Ordertype.find(:all, :order=>"description")
#salesreps = Salesrep.find(:all, :order=>"fullname")
#customers = Customer.find(:all, :order=>"company_name")
#memberids = Memberid.find_all_by_customer_id(#order.customer_id)
#products = Product.find(:all, :include=>[:items],:order=>["products.description"])
#partners = Partner.find(:all, :order=>"company_name")
end
def get_reps
#salesreps = Salesrep.find(:all,:order=>"fullname")
#commission = Commission.new
render :partial=>'commission'
end
In my 'order' model I then have this:
def commission_attributes=(commission_attributes)
commission_attributes.each do |attributes|
if attributes[:id].blank?
commissions.build(attributes)
else
commission = commissions.detect{|t| t.id == attributes[:id].to_i}
commission.attributes = attributes
end
end
end
This works in rails 2, however in rails 3 I get the error below:
#order[commission_attributes]' is not allowed as an instance variable name</code></pre>
I can't seem to work out what the problem is, or how to work around this issue.. any help is very appreciated.
Andrew

The fields_for method only takes objects or symbols. It's hard to give a specific solution without more code but something like this might work:
<%= form_for #order do |form| %>
...
<%= fields_for #order.commission do |commission_form| %>
Read up on it here: http://apidock.com/rails/v3.0.0/ActionView/Helpers/FormHelper/fields_for

Another alternative is
<%= f.fields_for :commission, commission do |commission_form| %>
This should cause then submit to trigger commission_attributes= instead of messing with another model directly, and by supplying the object you can populate the form with said object.
But this is just another method worth mentioning. Here's the doc fields_for#Nested Attributes

Related

Rails: How to pass params of multiple checkbox to the model

i built this form that generate me some chebox with value like "U6", "U8" eccc
<%= form.label "Seleziona Categorie" %>
<% TeamCategory::NAMES.each do |category| %>
<%= check_box_tag 'categories_selected[]', category -%>
<% end %>
Now i have to pass the value of selected check_box to a method in my model.
Now is:
def create_tournament_team_categories
TeamCategory::NAMES.each do |name|
team_category = TeamCategory.where(name: name).first_or_create
self.tournament_team_categories << TournamentTeamCategory.create(team_category: team_category)
end
end
I would like to replace the TeamCategory::NAMES.each do with "selected check_box each do" and TeamCategory.where(name: name) with the value selected.
Thank you in advance
I am a newbie with Rails. What I see is that you took the part of the form to create the team, right?
For your code straight forward it could be:
<%= form.label "Seleziona Categorie" %>
<% TeamCategory::NAMES.each do |name| %> #you are looping through team category NAMES constant
<%= check_box_tag 'category_names_selected[]', name %>
<% end %>
Your form as is allows more than one category to be selected.
For the method:
def create_tournament_team_categories(category_names_selected)
category_names_selected.each do |name|
team_category = name
self.tournament_team_categories << TournamentTeamCategory.create(team_category: team_category)
end
end
you will probably use this method in your teams_controller.rb. In the controller, you should be able to retrieve from params a freshly created array of selected names with something along the lines with this.
#category_names_selected = params[:category_names_selected]
I do not know how complicated your app is so it might also be nested under ["team"][:category_names_selected] or ["team"]["category_names_selected"] in your params hash.
To see the exact structure of the params hash and adjust the equation above you can add for example require 'pry' at the top of your controller file and then but the binding.pry just after the part where your method is executed. When you restart the server and the app hits this part of the controller you should be able to see the exact structure of your params hash in the terminal.
You can then pass the array to the method that you can call in the controller. Do not forget to add :category_names_selected to the strong params in the controller. I hope this helps.
Controller on line 30
def create
#tournament = Tournament.new(tournament_params)
#tournament.sport_club = current_user.sport_club
#category_names_selected = params[:category_names_selected]
if #tournament.save
redirect_to tournaments_path, notice: 'Torneo creato con successo'
end
end
Method create_tournament_team_categories in the model
after_create :create_tournament_team_categories
def create_tournament_team_categories(category_names_selected)
#category_names_selected.each do |name|
team_category = name
self.tournament_team_categories << TournamentTeamCategory.create(team_category: team_category)
end
end

Getting the string from a rails pluck to display n

got a super quick question. I'm still new to rails and tried following these two questions but they didn't work for me:Why does Array.to_s return brackets? and ruby 1.9 how to convert array to string without brackets.
I'm trying to show the last message and the date in which it was sent out in my chatroom application. I am able to get the results using this code, but it has brackets around it and I would like to have those brackets removed. Any help here would be amazing, I've attached a screenshot as well. Thank you so much!
Show.html.erb
For the Date:
<%= chatroom.messages.last(1).pluck(:created_at) %>
For the Last Message in Chatroom:
<%= chatroom.messages.last(1).pluck(:body) %>
DirectMessages Controller
class DirectMessagesController < ApplicationController
before_action :authenticate_user!
def show
users = [current_user, User.find(params[:id])]
#messageduser = User.find(params[:id])
#chatroom = Chatroom.direct_message_for_users(users)
#chatroomall = current_user.chatrooms
#messages = #chatroom.messages.order(created_at: :desc).limit(100).reverse
#messagelast = #chatroom.messages.last(1)
last_message = #chatroom.messages.last
render "chatrooms/show"
end
private
def chatroomuserlocator
#chatroomlocator = Chatroom.find(params[:chatroom_id])
end
end
Try this:
<%= chatroom.messages.last.created_at %>
And this:
<%= chatroom.messages.last.body %>
Keep in mind that pluck returns an array, so that would explain your brackets.
I don't think you need pluck here since you are just accessing an attribute on a single item.
If you're not too worried about memory usage, you can fetch the whole object and only access the fields you want.
<%= chatroom.messages.last.created_at %>
<%= chatroom.messages.last.body %>
You can assign the lookup to a value, so it doesn't run twice:
last_message = chatroom.messages.last
Then you can access the attributes efficiently:
last_message.created_at
last_message.body
If you are interested in limiting the attributes or last_message, use select:
last_message = chatroom.messages.select(:created_at, :body).last
Putting it all together:
<% last_message = chatroom.messages.select(:created_at, :body).last %>
<%= last_message.created_at %>
<%= last_message.body %>

Creating associated model with rails

I am trying to create associated models with Rails. My models are Financial which have many documents and Document which belongs to Financial. A working code when creating the associated model could be
def create
#financial = Financial.find(2)
#document = #financial.documents.create(document_params)
...
end
In my view I have a form which looks like this to select the right Financial
<%= form_for Document.new do |f| %>
<%= f.collection_select :financial_id, Financial.all, :id, :description %>
<%= f.submit %>
I do see the right parameters being transferred in the log when I submit the form
"financial_id"=>"3"
So I figured I would just need to change the initial code to:
def create
#financial = Financial.find(params[:financial_id])
#document = #financial.documents.create(document_params)
...
end
but I get a "Couldn't find Financial with 'id'=". I have tried other things including:
#financial = Financial.find_by(id: params[:financial_id])
Without much success. Could anyone give me the appropriate syntax please? Thanks.
Couldn't find Financial with 'id'=
Because, the params that are submitted are actually inside document hash. So params[:financial_id] won't work. Instead you need to use params[:document][:financial_id]
def create
#financial = Financial.find(params[:dcument][:financial_id])
#document = #financial.documents.create(document_params)
...
end

How to get class name with orm_class on custom scaffold generator

I am making custom templates to help the development on our application and I got stuck in a silly issue.
I am trying to put the ransack parameter in the index action controller but I cant make the generator spell only the classname.
The default controler is
def index
#<%= plural_table_name %> = <%= orm_class.all(class_name) %>
end
Which will produce a thing like:
def index
#stuffs = Stuff.all
end
What I want is something like:
def index
#search = <%= orm_class.search(class_name, params[:q]) %>
#<%= plural_table_name %> = #search.result.order('id')
.paginate(page: params[:page], per_page: 50)
end
that would produce:
def index
#search = Stuff.search(params[:q])
#stuffs = #search.result.order('id')
.paginate(page: params[:page], per_page: 50)
end
The thing is, orm_class doesn't have a search method.
I could solve this if the function give me only "Classname" but if I try
orm_class alone, it return in the code "Rails::Generators::ActiveModel".
How can I make the orm_class give me only "Classname"?
The "best" I've come so far was
#search = <%= orm_class.all(class_name) %>.search(params[:q])
But then I have manually remove the "all" after I generate the scaffold.
ActiveSupport::Inflector adds a variety of methods for transforming strings. You want classify:
plural_table_name.classify
For example:
> "my_stuffs".classify
=> "MyStuff"
In your case:
#<%= plural_table_name %> = <%= plural_table_name.classify %>.search(params[:q])

Pagination with Kaminari

All the examples of Kaminari I have seen only have 1 variable in the controller action.
But here is my example:
def index
#draft_item = #account.draft_item # only ever one
#in_force_item = #account.in_force_item # only ever one
#historical_items = #account.lo_items.historical # many of these
respond_to do |format|
format.html
end
end
These are all displayed in a table on the view, which I want to paginate. Do I need to combine these into 1 array first in the index action?
My loop on the view is like this:
<% [#in_force_item, #draft_item, #historical_items].compact.flatten.each do |lo_item| %>
then I have code like:
<% if lo_item == #draft_item %>
Is this possible and still be able to call the line above>?
Thanks to the answer below, I was able to do it like this:
#total_items = Kaminari.paginate_array([#draft_item, #in_force_item, #historical_items].compact.flatten).page(params[:page]).per(10)
It all had to be on one line for it to work, unlike the answer below which had it split across two lines.
It is. Kaminari has paginate_array
#draft_item = #account.draft_item # only ever one
#in_force_item = #account.in_force_item # only ever one
#historical_items = #account.lo_items.historical
#total_items = [#in_force_item, #draft_item, #historical_items].compact.flatten
Kaminari.paginate_array(#total_items).page(params[:page]).per(10)
Then
<% #total_items.each do |lo_item| %>
<% end %>
<%= paginate #total_items %>

Resources