Assign categories to a newly created post with Ruby and Padrino - ruby

I'm working on my ligthweight Padrino CMS which very much resembles the functionalities of Wordpress. When creating a new post I want to be able to assign them to many of the existing categories. Somehow I can not get my form work.
My models look like that:
Post model
class Post < ActiveRecord::Base
belongs_to :account
has_many :categorizations
has_many :categories, :through => :categorizations
accepts_nested_attributes_for :categories
end
Category model
class Category < ActiveRecord::Base
has_many :categorizations
has_many :posts, :through => :categorizations
belongs_to :category
end
Categorization model
class Categorization < ActiveRecord::Base
belongs_to :post
belongs_to :category
end
I have also created a migration for the joint table
class CreateCategorizations < ActiveRecord::Migration
def self.up
create_table :categorizations do |t|
t.integer :category_id
t.integer :post_id
t.timestamps
end
end
def self.down
drop_table :categorizations
end
end
And here is the related part of the form
<% fields_for :categories do |c| %>
<fieldset class='control-group <%= error ? 'has-error' : ''%>'>
<%= c.label 'Category title', :class => 'control-label' %>
<div class='controls'>
<%= c.select(:id, :collection => #categories, :fields => [:title, :id], :include_blank => true, :multiple => true, :class => 'form-control input-xlarge input-with-feedback') %>
<span class='help-inline'><%= error ? c.error_message_on(:id) : "Select a category if there is a parent category" %></span>
</div>
</fieldset>
<% end %>
I don't know what I'm missing but the association is not created. I do not mention categories in the controller during the creation but I do fill up the dropdown with the existing Categories. Somehow I would like to associate them to the new post.
I will greatly appreciate if someone can point me to the right direction with this. The error I get is this:
NoMethodError at /admin/posts/create
undefined method `each' for nil:NilClass
file: collection_association.rb location: replace line: 383
The forms POST data contains that:
POST
Variable authenticity_token
Value "c760c21a5d1f85bfc19e179b37d56f67"
category_active_record_relation {"id"=>["2", "3"]}
post
{"post_name"=>"Test post", "post_type"=>"blogpost", "post_title"=>"Postie", "slug"=>"This is a custom set slug", "post_date"=>"2015-06-30", "post_content"=>"Lorem ipsum dolor sit amet consequtiv", "post_excerpt"=>"Lorem ipsum", "post_status"=>"published", "comment_status"=>"closed", "comment_count"=>"0"}
save_and_continue "Save and continue"

I have managed to answer my own question, the solution was fairly easy, however maybe there is a nicer one, with more magic. Anyway using the CollectionProxy API documentation it became clear that I can assign these categories in the controller.
admin/controllers/posts.rb
Just include before the if #post.save
params[:category_active_record_relation]['id'].each do |category|
category = Category.find(category)
#post.categories << category
end
If I would create new categories than I could use the #post.categories.build(category) method.
Hope it will help others as well.

Related

associating post and user

Here are the three files associated with the original problem, I think...please excuse my ignorance...the rails generator does a lot of work for you, so I don't understand all the connections yet.
class Post < ActiveRecord::Base
has_many :comments
belongs_to :user
default_scope { order('created_at DESC') }
end
class AddUserToPosts < ActiveRecord::Migration
def change
add_column :posts, :user_id, :integer, :name
add_index :posts, :user_id
end
end
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.text :body
t.text :name #added this
t.timestamps
end
end
end
where the error is occuring:
<%= link_to post.title, post %>
</h4>
<small>
>> submitted
<%= time_ago_in_words(post.created_at) %> ago by
<%= post.user.name %> <br/>
<!-- <%= post.comments.count %> Comments -->
</small>
Ruby is basically telling you that on line 11 (<%= post.user.name %>) the user association of your post object is nil (i.e. a non-existent value, which in Ruby is a singleton instance of class NilClass).
Thus you're trying to call the #namemethod on nil, that obviously has no such method, hence the NoMethodError.
Just add a check to make sure that user exists before printing its name <%= post.user.name unless post.user.nil? %> or make sure that there is always a user associated with your posts (e.g. through a validation), whatever fits best in your scenario.

Rails 3 creates duplicate form object for nested records when updating them

There are two models
class Category < ActiveRecord::Base
has_many :products
accepts_nested_attributes_for :products, allow_destroy: true
validates_associated :products
end
class Product < ActiveRecord::Base
belongs_to :category
validate_uniqueness_of :name, scope: :category_id
end
And a form for category
<%= simple_form_for #category do |f| %>
<%= f.simple_fields_for :products do |p| %>
<%= render :partial => "product_fields", :locals => { :f => p } %>
<% end %>
<% end %>
As you can see there is a uniqueness validation which makes sure that products are uniq within category. The problem starts when validation is not passed.
Calling #category.update_attributes(params[:category]) results in duplicate form object. When rendering the form with errors rails creates additional associated product with the id of duplicate record but different name.
For example:
Given we have two products within category: Bread and Butter. If set Butter to Bread when editing a category's products a new form object will be created and the form will be rendered with Bread, Butter, Bread, saying last entry has a duplicate name.
How can i prevent rails from creating those duplicate records? I'm using rails 3.2.11 if it matters.

Edit a Parent Class from a Child Form

Currently, I am able to create multiple Students through my Adult Form by using accepts_nested_attributes_for :student.
But how can I Edit an existing Adult through a Student Form? (So the Opposite, except Edit)
Currently I am able to create more Parents through my Student form, but thats not what I want.
MODELS
class Adult < ActiveRecord::Base
has_many :students
accepts_nested_attributes_for :student
end
class Student < ActiveRecord::Base
belongs_to :adult
accepts_nested_attributes_for :adult
end
CONTROLLER
class StudentsController < ApplicationController
def update
#adult = Adult.find(params[:adult_id])
#student = Student.find(params[:id])
if #student.update_attributes(student_params)
redirect_to path
end
end
private
def student_params
params.require(:student).permit(:adult_id, :school_id, :username, :password,
:firstName, :middleName, :lastName, :alias,
adult_attributes: [:id, :name])
end
end
VIEWS
###HOW CAN I UPDATE THE EXISTING PARENT AS OPPOSE TO CREATING ONE
<%= simple_form_for #student.build_adult do |f| %>
<h4>Update Parent Information</h4>
<%= f.label :firstName, 'First Name' %>
<%= f.text_field :firstName, placeholder: "Parent's First Name", :class => "form-control"%>
<%= f.submit "Save & Continue", class: "btn btn-primary"%>
<% end %>
ROUTES
resources :adult do
resources :student
end
Firstly,it is has_many :students,so it should be accepts_nested_attributes_for :students not accepts_nested_attributes_for :student.
Secondly,if i understood your question correctly,you are trying to update the existing parent(adult) record but you are ending up creating a new one.Is that the problem? If so,you need to permit the :id of the student for which the parent(adult) record need to be updated.
Change your student_params method to like this
def student_params
params.require(:student).permit(:id,:adult_id, :school_id, :username, :password,
:firstName, :middleName, :lastName,:alias,adult_attributes: [:id, :name])
end
I'm not sure about this solution, but it may work...
Try using #parent.update_attributes instead of creating a separate parent form, send the parent params with the student params. You may need to define a parent_params() function to permit them.
** I believe the permit params will filter out the non-permitted ones, so you won't need to specify only the student or parents fields for their respect update_attributes.

Rails 4: checkboxes with a has_many through

I'm building an application which has to assign a assignment to multiple employers.
I have build these models:
#assignment.rb
class Assignment < ActiveRecord::Base
has_many :employer_assignments
has_many :employers, :through => :employer_assignments
end
#employer.rb
class Employer < ActiveRecord::Base
has_many :employer_assignments
has_many :assignments, :through => :employer_assignments
end
#employer_assignment.rb
class EmployerAssignment < ActiveRecord::Base
belongs_to :employer
belongs_to :assignment
end
And now I want the form to save to the employer_assignment table but the following code I used for my form doesn't work.
<div class="field">
<%= f.label :employer_ids %><br />
<%= collection_check_boxes(:assignment, :employer_ids, Employer.all, :id, :name) %>
</div>
I did add :employer_ids to my assignment controller from which I try to send the form which does create the assignment but doesn't create the records in the employer_assignment table.
When I add them via the console ( Assignment.last.employers << Employer.all
) it all works fine. I'm sure I'm missing something but can't figure out what.
Thanks in advance.
You're probably getting an Unpermitted parameters: in your log due to Strong Parameters in rails4 (#emil-kampp mentioned this), after a fresh rails generate, they are generated in your controller. So using your code it would look something like:
class EmployersController < ApplicationController
# <snip>
def update
#employer.update(employer_params)
end
def employer_params
params.require(:employer).permit(:name, { :employer_ids => [] })
end
end
Also see this Question on SO which answers this. Hopefully this saves someone a few cycles.

has_many through form driven by checkboxes

Models : based on rails 3 guide!
class Physician < ActiveRecord::Base
has_many :physician_specialities
has_many :specialities, :through => :physician_specialities
end
class speciality < ActiveRecord::Base
has_many :physician_specialities
has_many :physicians, :through => :physician_specialities
end
class PhycianSpeciality < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
end
And the database schema looks like this :
Physician
id
name
Speciality
id
name
PhycianSpeciality
id
physician_id
speciality_id
description
I want to have a form which is able to add specialities to a physician and write a small description of this speciality (according to the physician).
I think i can use somethings like this Quick Tip: has_many :through => checkboxes!
<% form_for #physician do -%>
<% Speciality.all.each do |group| -%>
<div>
<%= check_box_tag :speciality_ids, speciality.id, #user.specialities.include?(speciality), :name => 'user[speciality_ids][]' -%>
<%= label_tag :speciality_ids, speciality.name -%>
</div>
<% end -%>
<%= submit_tag -%>
<% end -%>
But i don't know where can i put the speciality description ...
It looks to me like you are missing at least two relationship tables/models.
SpecialtyDescription
PhysicianSpecialityDescription
That way you can have the right connection between PhysicianSpeciality & PhysicianSpecialityDescription (PhysicianSpeciality_id, SpecialtyDescription_id) & SpecialtyDescription.
Since the description is pending the creation of the join record in PhysicianSpecialty, I would just pass the description in as a text_area and sort it out pending the save of the Physician.
physicians_controller.rb
# i imagine ur update method would look kinda like this
def update
#physician = Physician.find(params[:id])
if #physician.update_attributes(params[:physician])
physician_specialty = PhysicianSpecialty.find_by_specialty_id(:specialty_id => specialty.id)
physician_specialty.update_attribute(:description, params[:description])
else
render :action => :edit
end
end

Resources