My rails console shows the same model twice - uninitialized constant error - ruby-on-rails-4

I have a model named pictures.rb aka Picture class which should map to pictures table but in rails console it gets displayed twice?
irb(main):013:0> #models = ActiveRecord::Base.subclasses.collect { |type| type.name }.sort
=> ["Picture", "Picture"]
I am trying to use Picture class aka picture.rb model in my ControlPanelController index function
so when I load my index page I get the following error
uninitialized constant ControlPanelController::Picture
def index
#pictures = Picture.all
end
I am guessing it might be because that Picture model shows up twice in rails console? Not sure.

The reason it can't find it is your model file name is called pictures.rb.
The filename should be picture.rb (not plural).
It should be:
app/models/picture.rb:
class Picture< ActiveRecord::Base
...
end

Related

Why do I get an unexpected keyword argument?

I have created a model in my Djano project and the name of the model is Questions in which I have created a primary key called questionid. I am able to get all listings as summaries on one page however when I try to get a detailed listing of one query (say question number 4 out of the several in the table) by going to the http://127.0.0.1:8000/qanda/4 (here 4 is the question number), I get an error that says
TypeError at /qanda/4
question() got an unexpected keyword argument 'question_questionid'
Please see the code below
In my model's views file
def question(request):
questionsm = Questions.objects.order_by('-published_date').filter(is_published=True)
context = {
'questionid': questionsm
}
return render(request,'qanda/question.html', context)
In my model url file
path('<int:question_questionid>', views.question, name='question'),
I will appreciate any help. thanks
You are not passing the var to the view.
def question(request, **id_what_you_want**):
# and if you want an individual view, you should get by id
Questions.objects.get(pk=id_what_you_want)

How to add custom attribute to all simple_form input based on model name and attribute value?

I want to add a custom attribute to every input generated by simple_form. The attribute value is based on model name and field. So I did this:
# app/inputs/base.rb
class Base < SimpleForm::Inputs::Base
def input_html_options
super['custom-attr'] = "#{object_name}.#{attribute_name}"
end
end
This isn't working. The code is not being loaded for execution at all. Am I missing something here?
you should add code in lib/simple_form/inputs/base.rb, code should look like this to make sure it can be loaded automatically
module SimpleForm
module Inputs
class Base
def input_html_options
#input_html_options...
end
end
end
end
or use class_eval in config/initializers/simple_form_ext.rb like this
SimpleForm::Inputs::Base.class_eval do
def input_html_options
#input_html_options[:'custom-attr'] = "#{object_name}.#{attribute_name}"
#input_html_options
end
end

Copy a Paperclip image to a new record in Rails 4

My site is for posting album reviews, which are called Pins. The pins model has the following attributes:
:artist, :year, :title, :rank, :description, and :image
The image uses Paperclip and is stored on Amazon S3 if that matters
I am trying to allow a user to see a review that another user posted and click a link to more simply write their own review for that same album. So basically the link takes them to the Pin.new page and the form already has the :artist, :title, :image, and :year filled in.
I figured out how to do it while bringing ALL of the attributes, including the :description and :rank, which I don't want. I am also not able to bring over the image to the new form.
Here is the pins_controller.rb code I'm using:
def copy
#source = Pin.find(params[:id])
#pin = #source.dup
render 'new'
end
And in my show view:
<%= link_to "copy", copy_pin_path(params[:id]) %>
So question one is how to #source.dup only :artist, :title, and :year
question two is how to bring over the paperclip image. I tried adding this to my pins_controller.rb:
def copy
#source = Pin.find(params[:id])
#pin = #source.dup
#pin.image = #source.image
render 'new'
end
but that didn't work.
UPDATE: miller350 answered my first question, but I still can't get the paperclip image to copy over to the "new" form. In the console I can copy from one Pin record and save a new pin like this:
r = Pin.new
r.image = Pin.find(83).image
r.save
I think the issue is that the new pin form requires that an image is chosen from the user's PC before saving the pin. Whatever that function of Paperclip is, I think that is where I'm getting stuck.
For the first part, you could pull the attributes individually and set them to the instance variable, and for the second part, you could use URI.
def copy
#source = Pin.find(params[:id])
#image = URI.parse(#source.image)
#pin = Pin.new(artist: #source.artist, title: #source.title, year: #source.year, image: #image)
render 'new'
end
Here is what I ended up doing to copy the image to a new pin form.
I have Paperclip's image_remote_url functionality set up already, but I needed to add .to_s to the method below in the pin.rb:
def image_remote_url=(url_value)
self.image = URI.parse(url_value).to_s unless url_value.blank?
super
end
Then my controller:
def copy
#source = Pin.find(params[:id])
#image = #source.image.url
#pin = Pin.new(artist: #source.artist, album: #source.album, year: #source.year, image_remote_url: #image)
render 'new'
end
This pastes the url of the image into the new form. It only works on my Heroku production version, not the local version.
Try below code to copy paperclip image from one record to another
Suppose you have one active record of model Course and copy image to another record
c1 = Course.last
c2.image = c1.image
c2.save
how it works -
c2.image = c1.image - It copy from c1.image to local file
and when you save it then it first delete c2.image if present and set new image to that record

Generating image url using carrierwave in rails

This is somewhat related my question about joins here. By default when I use listing.image.name in my search results view, it does a full query to find the image for every listing in my results array. It even does an extra query just to check if the listing has any images. So to avoid this, I'm adding the following to my Thinking Sphinx query:
#ts_params[:sql][:joins] = "INNER JOIN listing_images ON listing_images.listing_id = listings.id AND listing_images.position = 0"
#ts_params[:sql][:select] = "listings.*, listing_images.image as image_name, listing_images.id as image_id"
This works, however I'm not sure how to generate the full image_url using carrierwave. Previously, where it was doing an extra query per result, I was using listing.image.image_url(:sizename). So, I can find the image name and ID from my join as above, but how to I convert this to a full image url via carrierwave? Is there a built-in method to retrieve the url, that doesn't require an 'image' object?
I tried listing.image_id.image_url(:sizename) but it gave an undefined method error as expected.
From carrierwave's perspective, the answer is obvious:
user.avatar.url
user.avatar.thumbnail.url
Here, user is an instance of a model, and avatar is the field on the model with mount_uploader called on it. In your case this would be something like:
listing_image.image_name.url
listing_image.image_name.thumbnail.url
That probably doesn't work, though, because it looks like you may be loading your listing_image fields into the Listing instead of through includes (or the dreaded N+1 non-eager loads). You may need to resolve your other stackoverflow question before this one will be possible.
Edit:
Per our discussion on your other issue, once you've got a has_one :main_image for just the one ListingImage you want, you're going to use something like #listing.main_image.image_name.url and, if you have a version named "thumbnail", #listing.main_image.image_name.thumbnail.url.
I had the similar issue when I was fetching image using query and wanted to build image url using db field instead of issuing full sql query for each image.
I found out that with couple of field fetched from related image table we can build image which will not run any sql for image if we have three fields id, updated_at and image_name this field should be from the table where image is being saved. It could be from the main table where image is saved as separate column or completely separate table use to specially for image here is a sample code
It can be in your helper or in decorator as per your choice
def logo_url(id, updated_at, name)
return if id.blank? || updated_at.blank? || name.blank?
Company.new(id: id, updated_at: updated_at, logo: name).logo
end
and in view you can call this helper method as
<%= logo_url(company.id, company.updated_at, company.logo).url %>
This way you can have your image with url without executing sql query on each image.

Assigning Virtual Attribute in Rails

I'm attempting to understand the difference between these two ways of assigning virtual attributes in Rails 4. One of them causes a "stack level too deep" and one of them works fine. I'm attempting to use the new ActiveRecord array field by parsing a textfield and splitting it by commas to create a tag field. The working code is as follows:
class Post < ActiveRecord::Base
def tags=(s)
self[:tags] = s.split(/,\s+/)
end
end
However, when I change this to assign the tag field in this model by assigning to the class variable, it causes a "stack level too deep".
class Post < ActiveRecord::Base
def tags=(s)
self.tags = s.split(/,\s+/)
end
end
Can someone explain why this happens to me? It seems like using self.tags causes this virtual attribute to be run until the stack blows up. Which part of ActiveRecord causes this?
The stack level too deep error has nothing to do with rails. Any basic Ruby class would do this:
class Post
def tags=(s)
self.tags = s
end
end
> Post.new.tags = "a,b,c"
SystemStackError: stack level too deep
Calling self.tags = will just re-execute tags=(s) on the same object, over and over again. In your first example, you're directly setting the attribute via self[:tags] =, which doesn't re-execute tags=(s) at all. I would assume an oversimplification of ActiveRecord is that it does something like your first example for all of a model's fields.