Before I forget, here's what I'm running with:
Rails 3.2.4.rc1
Ruby 1.9.3
Formtastic 2.1 (stable)
I'm trying to use formtastic to do user information forms. The date field doesn't seem to be working correctly. All other data is updating correctly. It looks like the PUT request is ok, but when I query my database (mysql), it says that the date = NULL.
Code examples:
From my view:
<%= semantic_form_for #author do |f| %>
<%= f.inputs do %>
<%= f.input :first_name %>
<%= f.input :last_name %>
<%= f.input :date_of_birth, :start_year => Time.now.year-500 %>
<%= f.input :nationality %>
<%= f.input :bio %>
<% end %>
<%= f.actions %>
<% end %>
The PUT request:
Started PUT "/authors/4" for 127.0.0.1 at 2012-07-19 11:08:02 -0400
Processing by AuthorsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"UARYU7S0FTOLYU1Z04lZp/2Gn94DXiKuX/FN/DgYk/c=", "author"=>{"first_name"=>"Sheila", "last_name"=>"Wedigo", "date_of_birth(1i)"=>"1514", "date_of_birth(2i)"=>"3", "date_of_birth(3i)"=>"5", "nationality"=>"American", "bio"=>"Sheila is an awesome Great American Playwright"}, "commit"=>"Update Author", "id"=>"4"}
ETA: Here's the MYSQL in the console:
Processing by AuthorsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"gjSXdsSWPBzL65fOHX/pe3XTFRau4NYzZSYsyp1aPAs=", "author"=>{"first_name"=>"Stinky ", "last_name"=>"mggee", "date_of_birth(1i)"=>"2010", "date_of_birth(2i)"=>"4", "date_of_birth(3i)"=>"4", "nationality"=>"Finnish", "bio"=>"TEST"}, "commit"=>"Create Author"}
SQL (0.2ms) BEGIN
SQL (154.1ms) INSERT INTO `authors` (`bio`, `created_at`, `date_of_birth`, `date_of_death`, `first_name`, `last_name`, `nationality`, `updated_at`) VALUES (?, ?, ?, ?, ?, ?, ?, ?) [["bio", "TEST"], ["created_at", Tue, 24 Jul 2012 13:30:23 EDT -04:00], ["date_of_birth", nil], ["date_of_death", nil], ["first_name", "Stinky "], ["last_name", "mggee"], ["nationality", "Finnish"], ["updated_at", Tue, 24 Jul 2012 13:30:23 EDT -04:00]]
The output when I ask mysql about it:
mysql> select date_of_birth from authors where id = 4;
+---------------+
| date_of_birth |
+---------------+
| NULL |
+---------------+
1 row in set (0.00 sec)
I suspect it might have something to do with the following information from RoR Guides: "select_date does not work well with forms that update or create Active Record objects as Active Record expects each element of the params hash to correspond to one attribute. The model object helpers for dates and times submit parameters with special names, when Active Record sees parameters with such names it knows they must be combined with the other parameters and given to a constructor appropriate to the column type."
That said, I'm not seeing anyone else on the internet with this problem, and it seems like the kind of thing that Formtastic would be handling. This worked correctly before my recent upgrade from Rails 2 to Rails 3.
Related
I have 2 models user and team. a team can have many users each users belong to a team.
team_id is a column in my user table as a fk.
I want to have a select drop down on my create user form that has all my teams team_id in it.
This code does what I want BUT
<%= f.fields_for :teams do |builder| %>
<p>
<%= f.label :team_id, "Select Team For User" %>
<%= builder.collection_select :team_initials, Team.all, :id, :team_initials %>
</p>
<% end %>
it does not try to add the id value to a user. here is the error
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"xxxxx",
"user"=>{"name"=>"brand new",
"email"=>"test1#test.com",
"password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]",
"teams"=>{"team_initials"=>"27"}},
"commit"=>"Create my account"}
It complains that it cant add to the team model.
All I want to do is grab the ID of all existing teams for my create user form so when you crate a user you can select that users team.
The reason I have team_initials above is I was trying to use a more user friendly field for select but still user team Id as the value.
I think you're on the right track. The fields_for mechanism is for setting values in the associated model. I think all you're trying to do is make the association.
So you can lose the fields_for line and then this section:
builder.collection_select :team_initials, Team.all, :id, :team_initials
Should be:
f.collection_select :team_id, Team.all, :id, :team_initials
I'm looking here for my info on collection_select since I don't know it off the top of my head:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html
I think this will change this parameter from "teams"=>{"team_initials"=>"27"}}, to "team_id"=>"27",
I hope that fixes it.
Update start
This problem was with rendering a form for each project, not with SQl queries. To optimize I will add the form as needed with javascript.
It seems like I didn't read the miniprofiler log correct. I apologize, but leave the question for others that might have similar questions.
Update end
I am using miniprofiler to find bottlenecks in my app. And I found one!
SELECT "projects".* FROM "projects" INNER JOIN "memberships" ON
"projects"."id" = "memberships"."project_id" WHERE
"memberships"."user_id" = 1 AND (active = 't')
1059.50 ms
Rendering: projects/_index — 1023.18 ms
It is finding 185 projects in 1 whole second.
How can I make a query that does this more efficient?
I have this in my projects_controller index
#projects = current_user.projects.is_active
The is_active scope in the projects model
scope :is_active, where(["active = ?", true])
The projects and users has a many to many relationship, with a membership join table
The membership model
class Membership < ActiveRecord::Base
attr_accessible :project_id,:user_id,:created_at,:updated_at
belongs_to :user
belongs_to :project
end
The membership table
def self.up
create_table :memberships do |t|
t.integer :project_id
t.integer :user_id
t.timestamps
end
add_index :memberships, [:project_id, :user_id], :unique => true
end
I am running this in the production environment on the local computer with postgreSQL as the database
Adding explain by Jiří Pospíšil request. In the console it does not seem to be slow at all. This explain is done in development. Have the same problem there
User.first.projects.is_active.explain
User Load (0.3ms) SELECT "users".* FROM "users" LIMIT 1
Project Load (2.3ms) SELECT "projects".* FROM "projects" INNER JOIN "memberships" ON "projects"."id" = "memberships"."project_id" WHERE "memberships"."user_id" = 1 AND (active = 't')
EXPLAIN (0.2ms) EXPLAIN QUERY PLAN SELECT "projects".* FROM "projects" INNER JOIN "memberships" ON "projects"."id" = "memberships"."project_id" WHERE "memberships"."user_id" = 1 AND (active = 't')
=> "EXPLAIN for: SELECT \"projects\".* FROM \"projects\" INNER JOIN \"memberships\" ON \"projects\".\"id\" = \"memberships\".\"project_id\" WHERE \"memberships\".\"user_id\" = 1 AND (active = 't')\n0|0|1|SEARCH TABLE memberships USING INDEX index_memberships_on_user_id (user_id=?) (~10 rows)\n0|1|0|SEARCH TABLE projects USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)\n"
The view
<% #projects.each do |project| %>
<li class="tab_list" id="project_<%= project.id.to_s %>">
<div class="tab_list_text"><%= link_to project.name, project_path(project) %></div>
<span class='open_project_update button edit' id="project_update" data-id="<%= project.id %>" data-object="project" title="Edit project">Edit</span>
<div class="dialog_form" id="project_update_<%= project.id %>_form" title="Update project" style="display:none;">
<%= form_for(project) do |f| %>
<ul>
<li><%= f.label :name %><%= f.text_field :name %></li>
<li><%= f.label :description %><%= f.text_field :description %></li>
<li><%= f.label :due %><%= f.text_field :due, :value => project.due.strftime("%Y-%m-%d"), :id => "date_project_#{project.id}" %></li>
<li><%= f.label :customer_id %><%= f.select(:customer_id, #customers.map {|customer| [customer.name, customer.id]}, {:include_blank => 'None'})%></li>
<li><%= f.submit 'Save', :class => 'submit' %></li></ul>
<% end %>
</div>
<a class="activate_project button" data-object="project" data-id="<%= project.id.to_s %>">Archive</a>
</li>
<% end %>
Project load is only taking 2.3ms. The time to render projects/_index is 1 second. The query is not your bottleneck.
Based on your comment, you say that you're lazy loading the relationships. Make sure that you eager load the relationships by using includes.
For example:
#user.projects.is_active.includes(:some_association).includes(:another_association)
includes will cause the relationship to be eager loaded.
If you're iterating over a list of users, to get the active projects, you'll need to do something like:
User.includes(:projects)
.merge(Project.is_active)
.includes(projects: :some_other_association)
It is good practice to not put DB queries in your views. Try to do that via the controller.
You can use a new released gem 'query_optimizer'
now .
query_optimizer is the best gem for optimizing query in rails for has_many and belongs_to relationship two tables
Since no one has mentioned it yet, the bullet gem is excellent for identifying pages in your apps where you inadvertently created N+1 queries (your specific case) that could benefit from eager loading (using includes as well-outlined in the accepted answer) and counter-caching.
This great post outlines both the problems and solutions in simple, clear language as well as giving an intro to using the bullet gem. There is also a RailsCast on implementing bullet though I have not gone through it.
I am trying to build a dropdown select input of months using simple_form. However, I am having trouble figuring out where to even begin. Currently, it is a text input area:
<%= f.input :start_month %>
I need to know what arguments to pass in order for this to be a dropdown of all 12 months. It is not important for it to return an integer value for the months but would be ideal in the event I use it for ordering later on.
I am still a beginner with rails and could really use the help on this one. I can provide any extra information necessary.
Edit:
I would like the dropdown to show the month names, not simply numbers.
Here is my solution:
<%= f.input :start_month, collection: (1..12).map{|i| [I18n.t("date.month_names")[i], i]} %>
What about this:
<%= f.input :start_month, :collection => 1..12 %>
or with month names:
<%= f.input :start_month, :collection => ['January','February',...,'December'] %>
<%= f.select :month, Date::MONTHNAMES.compact.each_with_index.collect{|m,i| [m,i]}, prompt: 'Month'
I have an index where I'm showing a list of documents. I would like to implement a multiple select in order to do different actions to the documents the user has selected
I have created a
<%= check_box_tag 'id', 'document.id %>
for each document, inside a form_tag
But if I select multiple checkboxes, the params that are passed to the action are overwrited and I'm just receiving the id of the last checkbox I've selected in the id param.
¿Anyone knows how to implement multiple select?¿Any other approach?
I'm running Rails 3 and Ruby 1.8.7
Thanks in advance
You need to set :multiple => true
<%= check_box_tag 'id', document.id, :multitple => true %>
This will give you results in form of an array in params[:id]
Minor correction (plural):
<%= check_box_tag 'ids[]', document.id %>
ensure your model is properly set for attr_accessible something like :document_ids
I have a problem with datetime attribute in Rails model.
model:
attr_accessor :from, :to, :via, :datetime
erb template:
<%= f.text_field :from %>
<%= f.text_field :to %>
<%= f.text_field :via %>
<%= f.datetime_select :datetime, :discard_year => true %>
I got:
#datetime(4i)' is not allowed as an instance variable name
On this line: #search_form = SearchForm.new params[:search_form]
What's wrong?
I don't know exactly what's causing the error, but I can tell you that to fix it, you'll need to change the attribute name datetime to, say sent_on (most anything else, really).
Why the error? I'd guess it's because datetime is a data type in SQL, and thus shouldn't be used as a column name, but the error seems to be coming from ruby - either your model or ActionView, so I'm not sure if that supports my theory...
Anyway, hope this helps!
Update: I just tested it, and you can use "datetime" as a column name in SQL (MySQL, at least). There goes that theory - it's a Rails thing, then, I guess...