Rails best_in_place gem with nested resource - ruby-on-rails-3

Does anyone know if it is possible (and, if so, what the syntax is) for using a nested resource with the best_in_place gem?
My routes.rb looks something like this
resources :users do
resources :goals
end
I would like to edit the :description field of the goal, but the code in my view for
<%= best_in_place [#user, #goal], :description %>
gives a NoMethodError saying
undefined method `description' for #<Array:0x20e0d28>
Using
<%= best_in_place #goal, :description %>
give me an undefined method error also because there is no goal_path
I can get the gem to work for #user (the non nested resource) field without problems.
I'm running Rails 3.1.1, Ruby 1.9.2, best_in_place 1.0.4

I figured it out.
I needed to set the path option in the call like so
<%= best_in_place #goal, :description, :path => user_goal_path %>
It works like a champ now!

Add path and the objects to the path:
<%= best_in_place #goal, :description, :path => user_goal_path(#user,#goal) %>
Somehow the simple path solution of bknoles didn't work for me.

Now above method is deprecated.
According to latest Documentation use ":url" instead of ":path" like below in the example
<%= best_in_place #goal, :description, :url => user_goal_path %>
Cheers!

Thank you, #bknoles. Your answer definitely helped me reach a similar solution of my own. Here's my implementation:
#widget.rb
class Widget < ActiveRecord::Base
validates_presence_of :name
has_many :gadgets
attr_accessible :name, :description
end
#gadget.rb
class Gadget < ActiveRecord::Base
belongs_to :widget
attr_accessible :name, :widget_id, :id
end
#gadgets_controller.rb
def update
#gadget=#widget.gadgets.find(params[:id])
if #gadget.update_attributes(params[:gadget])
respond_to do |format|
format.html
format.json { respond_with_bip(#gadget) }
end
else
respond_to do |format|
format.html { render :action => "edit" }
format.json { respond_with_bip(#gadget) }
end
end
end
#views/gadgets/_gadget.html.haml
%tr{ :name => "gadget_", :id => gadget.id }
%td= gadget.created_at.localtime.strftime("%B %d, %l:%M%p")
%td.big=best_in_place gadget, :name, :path => [#widget, gadget]
%td.delete{:style => 'text-align:center;'}
=check_box_tag "gadget_ids[]", gadget.id, false, :class => "checkbox"
You can checkout the entire project on github if you want to see more of the code.
https://github.com/hernamesbarbara/ajax-rails-full-crud
Best,
Austin

Related

Rails - "include CarrierWave::RMagick" results in: undefined method `model_name' for NilClass:Class

I'm building a simple app with standard User model that has_one Profile model. I would like the profiles table to have a column for an image attribute. Therefore, I followed RailsCast #253 titled CarrierWave File Uploads. All is going well until I try to resize an image that has been uploaded. This requires the installation of ImageMagick & RMagick which took an entire day of searching to get done. However, I think I finally got it right and successfully installed rmagick version 2.13.2 (as verified by running "gem list").
But not so fast...now when I try to render the form to create a new profile, I get the following error:
NoMethodError in Profiles#new
undefined method `model_name' for NilClass:Class
FYI, this form was working fine until I un-commented "include CarrierWave::RMagick" in my ImageUploader (which I'm suppose to do if I want to use RMagick methods for image re-sizing).
Any thoughts on how to fix this?
My version info (I used RailsInstaller for Windows to get up & running)
Rails 3.2.13
Ruby 1.9.3p392 [i386-minw32]
ImageMagick 6.8.5-Q16
rmagick 2.13.2
Gemfile
gem 'rmagick'
gem 'carrierwave'
Models
class User < ActiveRecord::Base
has_one :profile
class Profile < ActiveRecord::Base
attr_accessbile :image
belongs_to :user
mount_uploader :image, ImageUploader
ImageUploader
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::RMagick
storage :file
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
ProfilesController
def new
#profile = current_user.build_profile
end
views/profiles/new.html.erb
<%= form_for #profile, :html => {:multipart => true} do |f| %>
<%= f.file_field :image %>
<%= f.submit "Create my profile" %>
<% end %>
Just replace this line
<%= form_for #profile, :html => {:multipart => true} do |f| %>
by
<%= form_for #instructor_profile, :html => {:multipart => true} do |f| %>
Issue is really with form_for not with RMagick, you have defined #instructor_profile in controller but using #profile in view. Make sure that there will be single space between form_for and #instructor_profile

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.

Nested model form not working properly - need to pinpoint POST/GET redirect

I have a nested model form that isn't functioning properly. The POST is to the proper place, but then the GET reroutes me. So I'm wondering if anyone can help explain what I'm doing wrong.
I have two models: User and Profile. Code for them below:
User:
class User < ActiveRecord::Base
attr_accessor :password, :email
has_one :profile, :dependent => :destroy
accepts_nested_attributes_for :profile
...
end
Profile:
class Profile < ActiveRecord::Base
attr_accessible :first_name, :last_name, etc.
belongs_to :user
accepts_nested_attributes_for :user
...
end
New/Create from both models:
class UsersController < ApplicationController
def new
#user = User.new
if logged_in?
redirect_to current_user.profile
end
end
def create
#user = User.new(params[:user])
if #user.save
redirect_to signup_path, :notice => 'User successfully added.'
else
render :action => 'new'
end
end
class ProfilesController < ApplicationController
def new
#profile = Profile.new
end
def create
#profile = Profile.new(params[:profile])
if #profile.save
redirect_to profile_path, :notice => 'User successfully added.'
else
render :action => 'new'
end
end
def index
#profile = current_user.profile
end
My signup (two step process) mixes the models, so as I said I'm using a nested model form in my Users new.html.erb file. Code form_for and f.fields_for below:
<%= form_for(:user, :url => signup_path, :html => {:id => 'homepage'}) do |f| %>
<%= f.fields_for :profile do |f| %>
Now when I enter data into the form, my routes.rb file seems to POST to the proper place (/signup so profile can be filled out further), but GET routes me to /login.
Routes.rb:
match '/login' => "sessions#new", :as => "login"
match '/signup' => 'profiles#new', :as => "signup"
match 'skip/signup', :to => 'info#signupskip'
match 'skip/profiles/new', :to => 'profiles#newskip'
root :to => 'users#new'
resources :users
resources :profiles
In rails server:
Started POST "/signup" for 127.0.0.1 at Sun Aug 28 19:54:11 -0400 2011
Processing by ProfilesController#new as HTML
Started GET "/login" for 127.0.0.1 at Sun Aug 28 19:54:11 -0400 2011
Processing by SessionsController#new as HTML
Rendered sessions/new.html.erb within layouts/application (32.1ms)
I'm wondering if the problem is in my layouts/application file, specifically this code:
<% if logged_in? %>
<%= render 'layouts/header_in' %>
<% else %>
<%= render 'layouts/header_out' %>
<% end %>
Can anyone help explain to me what I'm doing wrong?
UPDATE:
I deleted the if/else argument in `layouts/application' and it was still redirected. So I'm back to wondering what's going on.
I believe your problem has to do with an inherent issue (though arguably not problem) with HTTP protocol. You cannot return a redirect to a POST request. Alternatives include calling the other method from within the first controller action, or rendering the correct page directly from that action, or some mix of both.

New record not being saved with any values

I started the question differently, about a collection_select, but I found out that is not the problem.
This particular model won't save any data at all. It just ignores the values in the parameters. I can only save new records with NULL values (except for the timestamp fields).
See my comment for my latest try to fix it.
I have generated a few models with the handy scaffold command. Now I have tried to change a textbox to a collection_select for linking the new entity to the correct related one.
Using rails 3.1RC4 (hopefully this is not a bug).
In the _form.html.erb I use the following code:
<div class="field">
<%= f.label :category_id %><br />
<%= f.collection_select(:category_id, Admin::Category.all, :id, :name) %>
</div>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
...all other items...
<div class="actions">
<%= f.submit %>
</div>
After I click the submit button I receive error messages. It says that the name and permalink do not comply to the validation. I don't understand however, because in the logfiles I find this:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"my token is here", "admin_branche"=>{"category_id"=>"3", "name"=>"Verzekeraars", "permalink"=>"verzekeraars", "visible"=>"1"}, "commit"=>"Create Branche"}
To me it seems that the params contain all the needed values.
For the sake of completeness I will post my create method and model below.
So far I have tried switching back and forth between collection_select and f.coll... with no success. The current setup seems most appropriate to me, based on the logs.
I have also googled a lot, but haven't been able to find the answer. Question 2280106 on this site looks the same, but it had to do with attr_accessible which I have commented out in the model (I restarted the server afterwards and retried, just to be sure).
Help is much appreciated!
branche.rb:
class Admin::Branche < ActiveRecord::Base
# attr_accessible :name, :permalink
#relationships
has_many :courses, :as => :parent
belongs_to :category
#validations
validates :name, :presence => true, :length => {:maximum => 255}
validates :permalink, :presence => true, :length => { :within => 4..25 }
end
create action in the controller:
def create
#admin_branch = Admin::Branche.new(params[:admin_branch])
respond_to do |format|
if #admin_branch.save
format.html { redirect_to #admin_branch, notice: 'Branche was successfully created.' }
format.json { render json: #admin_branch, status: :created, location: #admin_branch }
else
format.html { render action: "new" }
format.json { render json: #admin_branch.errors, status: :unprocessable_entity }
end
end
end
In the controller, you're doing this:
#admin_branch = Admin::Branche.new(params[:admin_branch])
You should do this:
#admin_branch = Admin::Branche.new(params[:admin_branche])
If you look at the request parameters, the attributes are under "admin_branche", not "admin_branch".
I think that should solve your problems, if not, please let us know.
If you have problems with the generated inflections, you can completely customize them in the config/initializers/inflections.rb
just add something like this:
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'branch', 'branches'
end

A better way to get paperclip thumbnail in index.html.erb

I've been struggling with this for hours. For some background, I have paperclip set up, keeping in mind that I may one day want to add multiple attachments. I followed Emerson's screencast to help me figure it out. (http://www.emersonlackey.com/article/paperclip-with-rails-3)
I now have this in my view, which shows what I want it to show. I had trouble for a long time because it was kicking up errors when a thumbnail didn't exist for some posts.
Anyway, wrote it, it's in my view, and I just think it's really ugly. I feel like I must be missing something. For one thing, I'm completely repeating myself on one line. Secondarily, I've got this code in my view. Is there something that I should be doing in my controller to help me keep my view cleaner?
Thanks a bunch!
<% if Asset.where(:piece_id => piece.id).first
my_asset = Asset.where(:piece_id => piece.id).first%>
<%= piece.id%>
<%= image_tag my_asset.asset.url(:thumb)%>
<% end%>
Because I haven't done anything to my controller to speak of, I'm leaving all of that code out. But here's what my models look like:
Assets
class Asset < ActiveRecord::Base
belongs_to :piece
has_attached_file :asset, :styles => {:large => ['700x700', :jpg], :medium => ['300x300>', :jpg], :thumb => ["100x100>", :jpg]}
end
Pieces
class Piece < ActiveRecord::Base
attr_accessible :assets_attributes,:name, :campaign_id,:election_date, :mail_date, :pdf_link, :photo_desc, :photo_stock, :killed, :format, :artist
belongs_to :client
has_many :assets
accepts_nested_attributes_for :assets, :allow_destroy => true
validates :campaign_id, :presence => true
end
So your problem is that sometimes a Piece has a thumbnail and sometimes it doesn't, right?
I'd agree that your ERB solution smells bad. You could add a thumb_nail_url method to Piece:
def thumb_nail_url
asset = assets.first
asset ? asset.asset.url(:thumb) : nil
end
And then:
<% thumb_url = piece.thumb_nail_url %>
<% if thumb_url %>
<%= image_tag thumb_url %>
<% end %>
You could also wrap the above in a helper:
def piece_thumb_image_tag(piece)
thumb_url = piece.thumb_nail_url
thumb_url ? image_tag(thumb_url) : ''
end
and then:
<%= piece_thumb_image_tag piece %>