2 models in a form in rails 3 - ruby-on-rails-3

I am very new to rails development.
I am creating a simple backend for my portfolio site.
I am not sure about the title of this question. A previous question I asked maybe too convoluted. So I am simplifying it.
Im using 3 models: Post, Attachment, Attachment_Category
I have a form that I use to:
Draft the post with a title, content and a category.
Display attachment categories in a drop down (slideshow, image, video)
Upload the attachment(s).
I have implemented steps 1 and 2.
For step 3: I want it so that when I finally hit submit on the form, the attachment_category_id is saved to the attachment table.
I have the following relationships:
Post.rb
class Post < ActiveRecord::Base
has_many :attachment_categories, :through => :attachments
has_many :attachments,:dependent => :destroy
accepts_nested_attributes_for :attachments
validates_presence_of :title, :content, :category
end
Attachment.rb
class Attachment < ActiveRecord::Base
belongs_to :post
belongs_to :attachment_category
#paperclip
has_attached_file :photo, :styles =>{
:thumb => "100x100#",
:small => "400x400>"
}
end
Attachment_category.rb
class AttachmentCategory < ActiveRecord::Base
has_many :posts , :through => :attachments
has_many :attachments
validates :category_name, :presence =>true
end

So I have accomplished Steps 1, parts of step 2 and step 3.
With my solution, I am able to upload just one attachment.
But it works: The attachment gets saved to the Attachments table with the post_id and the attachment_category_id.
The following code is from _form.html.erb which gets sent to post_controller.rb.
Truncated code:
.....
<%= f.fields_for :attachments do |attach| %> <br>
<%= attach.collection_select :attachment_category_id, AttachmentCategory.all, :id, :category_name %>
<%= attach.file_field :photo %> <br>
<% end %>
.....

Related

Nested form not saving the data

I have 3 models. Firstly I have a voter which has many votes. Votes is a join table to link the voter and the entry. But when I try to save the votes they are not saving. My models look like this:
class Vote < ActiveRecord::Base
belongs_to :entry
belongs_to :voter
attr_accessible :entry, :voter, :voter_id
class Voter < ActiveRecord::Base
attr_accessible :email_address, :verification_code, :verified, :votes_attributes, :votes
has_many :votes, :class_name => "Vote"
accepts_nested_attributes_for :votes
class Entry < ActiveRecord::Base
attr_accessible :caption, :email_address, :filename
end
I am then my form looks like this:
<%= f.fields_for :votes do |builder| %>
<fieldset>
<%= builder.label :votes, "Vote" %>
<%= collection_select(:votes, :entry_id, Entry.all, :id, :caption, :prompt => 'Please select an Entry') %>
</fieldset>
<% end %>
But the votes are not saving in the database. The response looks like this:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"x5f85viIp/KHJKQF7DotaF3MhebARWcaLDKRbcZw/lM=", "voter"=>{"email_address"=>"sadasfd"}, "votes"=>{"entry_id"=>"3"}, "commit"=>"Create Voter"}
So whats going wrong?
Please try
class Voter < ActiveRecord::Base
attr_accessible :email_address, :verification_code, :verified, :votes
has_many :votes, :class_name => "Vote"
attr_accessible :votes_attributes,
accepts_nested_attributes_for :votes
Modify vote_params in VotesController
private
def vote_params
params.require(:vote).permit(:id, :email_address, :verification_code, :verified, votes_attributes: [:id, :name])
end

Accessing object in a nested form

i have the following nested form :
<%= form_for #contrat,:url => backend_orders_update_report_url(#contrat) do |f| %>
<%= f.fields_for :contrat_lines do |fcl| %>
<%= fcl.object.inspect %>
<% end %>
<% end %>
the output is the following :
nil
In the nested forms i want to display a few elements not as form but as raw text and a few ones as form field. Usually in a form by doing f.object.name, i would access the name and be able to display it as I want. However, here if i do fcl.object, there is only nil. It should display the inspection of a contrat_line object.
Is it possible to access the data in a nested form?
EDIT :
the controller action :
def show_report
#contrat = Contrat.find(params[:id])
end
Here is what models look like with the relation at the beggining :
ContratLine :
class ContratLine < ActiveRecord::Base
include Priceable
belongs_to :contrat
belongs_to :good
#a enlever ici et dans la base
attr_accessible :active_start,:active,:good_id,:pricing,:contrat
validates :active_start, :presence=> true,:if => "active"
validate :active_start_smaller_than_active_stop
validate :active_start_day_cannot_be_greater_than_28
has_one :pricing, :as => :priceable, :dependent => :delete
before_validation :convert_month_year_to_date
after_save :set_user_subscription_date
Contrat :
class Contrat < ActiveRecord::Base
has_many :contrat_lines, :dependent => :delete_all
belongs_to :user
attr_accessible :user_id,:pricing_id,:state,:adresse_id,:adresse,:payment,:adresse_attributes,:automatic,:start_date,:end_date
enum_attr :state, %w(basket waiting_data to_confirm paid) do
labels :basket=>'Panier', :to_confirm=>'Non payé',:paid=>'Payé'
end
enum_attr :payment, %w(debit_card wire_transfer cheque direct_debit)
belongs_to :adresse
accepts_nested_attributes_for :adresse, :allow_destroy => true
scope :by_state, lambda { |state| where("state = ?",state) }
scope :last_automatic, where("automatic = true").order("invoice_date DESC")
scope :last_with_adresse, where("state != 'basket'").order("invoice_date DESC")
before_validation :set_numbers
You're missing an accepts_nested_attributes_for :contrat_lines as well as :contrat_lines_attributes in attr_accessible

Rails scoped form not assigning belongs_to

I have two models in Rails 3 - a User model and a Profile model.
class User < ActiveRecord::Base
has_one :profile, :dependent => :destroy
end
class Profile < ActiveRecord::Base
belongs_to :user
end
They are scoped in my routes.rb file, as such:
resources :users do
resources :profiles
end
So now, my form to create a profile reads like this (Using SimpleForm):
<%= simple_form_for([#user, #profile]) do |f| %>
<%= f.error_notification %>
...(Other Inputs)
<% end %>
However, the user ID doesn't seem to be automatically sent to the profile model as I had assumed. Do I have to set that manually through the controller? Or am I missing something?
You should start by making sure that the relationship between User and Profile is indeed working correctly. You've actually put "has_one :user" in your User model, when I think you mean:
class User < ActiveRecord::Base
has_one :profile, :dependent => :destroy
end
In order to send the user ID with the form, the form should be on a page with a URL of something like "localhost:3000/users/5/profiles/new" which you can link to with the helper "new_user_profile_path(5)", for a user with ID 5.
When you submit the form, it will hit the create action in your ProfilesController. The following should result in the creation of the profile:
def create
#user = User.find(params[:user_id])
#profile = #user.build_profile(params[:profile])
#profile.save!
end
add :method => :post to your form since ur html request is GET which should be POST
simple_form_for([#user, #profile], :method => :post) do |f| %>

jQuery TokenInput plugin with deep nested_attributes pre-populating tokens on edit

I have the following structure working on my application.
class Foo < ActiveRecord::Base
has_many :examples, :dependent => :destroy
accepts_nested_attributes_for :examples
end
class Example < ActiveRecord::Base
belongs_to :foo
has_many :codes, :dependent => :destroy
accepts_nested_attributes_for :codes, :reject_if => lambda { |a| a[:code].blank? }
end
class Code < ActiveRecord::Base
belongs_to :example
has_many :code_kinds
has_many :kinds, :through => :code_kinds
attr_reader :kind_tokens
def kind_tokens=(ids)
self.kind_ids = ids.split(",")
end
end
class CodeKind < ActiveRecord::Base
belongs_to :code
belongs_to :kind
end
class Kind < ActiveRecord::Base
has_many :code_kinds
has_many :codes, :through => :code_kinds
end
And it's working perfectly for the form with fields_for on create and save.
I'm using kind_tokens as described on RailsCast #258 Token Fields
But on the edit form everything displays perfectly now I should be pre-populating the data in a data-pre attribute on the kind_tokens field inside the nested attributes for code in examples.
The RailsCast say:
<%= f.text_field :author_tokens, "data-pre" => #book.authors.map(&:attributes).to_json %>
But I can't do #foo.examples.codes.kinds.map... because the relation with Foo and examples returns a collection, the same situation with codes.
I'm just using:
<%= f.fields_for :codes do |codes_form| %>
That's inside of
<%= f.fields_for :examples do |examples_form| %>
Now how can I pre-populate the kind for code if I don't have any loop, and everything's done by nested_attributes and fields_for ?
Solved
Everytime you use a
<%= f.fields_for ...
Rails automatically makes a loop so you can have some kind of counter there like:
<%
#ctrEx = 0
#ctrCd = 0
%>
<%= form_for #foo ...
<%= f.fields_for :examples do |examples_form| %>
...
<%= examples_form.fields_for :codes do |codes_form| %>
...
<%= codes_form.text_field :kind_tokens, :class => "tag_matcher", "data-pre" => #foo.examples[#ctrEx].codes[#ctrCd].kinds.map(&:attributes).to_json %>
...
<%#ctrCd +=1%>
<%end%>
...
<%
#ctrEx += 1
#ctrCd = 0
%>
<%end%>
<%end%>
Now you can use your counters in the data-pre like this:
#foo.examples[#ctrEx].codes[#ctrCd].kinds.map(&:attributes).to_json
That's the way i figured it out, but there must be another way.

Rails 3 polymorphic association with Carrierwave and Simple Form

I'm trying to set up a polymorphic association for photo uploads which are processed using Carrierwave. I'm using Simple Form to build my forms. I feel like the association is correct so I'm wondering if my problem is just something with the form or controller.
Here are my associations:
property.rb:
class Property < ActiveRecord::Base
attr_accessible :image
...
has_many :image, :as => :attachable
...
end
unit.rb
class Unit < ActiveRecord::Base
attr_accessible :image
...
has_many :image, :as => :attachable
end
image.rb
class Image < ActiveRecord::Base
belongs_to :attachable, :polymorphic => true
mount_uploader :image, PhotoUploader
end
properties_controller.rb:
def edit
#property = Property.find params[:id]
#property.image.build if #property.image.empty?
end
def update
#property = Property.find params[:id]
if #property.update_attributes params[:property]
redirect_to admin_properties_path, :notice => 'The property has been successfully updated.'
else
render "edit"
end
end
Snippet from properties/_form.html.erb
<%= f.input :image, :label => 'Image:', :as => :file %>
Here is the error I get when submitting with an image attached:
undefined method `each' for #<ActionDispatch::Http::UploadedFile:0x00000102291bb8>
And here are the params:
{"utf8"=>"✓",
"_method"=>"put",
"authenticity_token"=>"lvB7EMdc7juip3gBZD3XhCLyiv1Vwq/hIFdb6f1MtIA=",
"property"=>{"name"=>"Delaware Woods",
"address"=>"",
"city"=>"",
"state"=>"",
"postal_code"=>"",
"description"=>"2 bedroom with large kitchen. Garage available",
"incentives"=>"",
"active"=>"1",
"feature_ids"=>[""],
"user_ids"=>[""],
"image"=>#<ActionDispatch::Http::UploadedFile:0x00000102291bb8 #original_filename="wallpaper-4331.jpg",
#content_type="image/jpeg",
#headers="Content-Disposition: form-data; name=\"property[image]\"; filename=\"wallpaper-4331.jpg\"\r\nContent-Type: image/jpeg\r\n",
#tempfile=#<File:/tmp/RackMultipart20120608-3102-13f3pyv>>},
"commit"=>"Update Property",
"id"=>"18"}
I'm looking everywhere for help on polymorphic associations and am getting nowhere. I've seen simple examples that look pretty straight forward. One thing I've noticed is that it seems like in a lot of the examples the has_many association in my case should be images and not image. However when I do that I get an error:
Can't mass-assign protected attributes: image
I've tried updating my form to use fields_for as I've seen in other blogs like so:
<%= f.input :image, :label => "Photo", :as => :file %>
<% f.simple_fields_for :images do |images_form| %>
<%= images_form.input :id, :as => :hidden %>
<%= images_form.input :attachable_id, :as => :hidden %>
<%= images_form.input :attachable_type, :as => :hidden %>
<%= images_form.input :image, :as => :file %>
<% end %>
All I know is I'm having a heck of a time getting this to work. I'm pretty new to Rails so even debugging it is difficult. It doesn't help that the debugger doesn't really work in 3.2 :(
Since your models have_many :images (it should be :images, not :image), you'll want to use nested_forms in your views. You should set up accepts_nested_attributes_for :images on the unit and property models and change the attr_accessible from :image to :image_attributes.
Check out http://railscasts.com/episodes/196-nested-model-form-part-1 for a good guide on getting going with it.