Best practice for Rails controller that paginates one mime format but not another - ruby-on-rails-3.1

My rails project is paginating the HTML format but not the the others. Can someone suggest a more elegant approach to dealing with the difference in getting the #contacts collection? Perhaps the pagination version should be a different method that only supports HTML?
def index
if request.format.to_sym == :html
#contacts = Contact.paginate(page: params[:page]).search(params[:search])
else
#contacts = Contact.search(params[:search])
end
respond_to do |format|
format.html { render html: #contacts }
format.mobile { render mobile: #contacts }
format.json { render json: #contacts }
format.xml { render xml: #contacts.to_xml }
end
end
My solution was to add paginate as a RESTful resource in routes.rb which automagically gives me the route helper method: paginate_contacts_path
resources :contacts do
collection do
get 'paginate'
end
end
and to have a separate paginate method in ContactsController
def index
#contacts = Contact.search(params[:search])
respond_to do |format|
format.html { render html: #contacts }
format.mobile { render mobile: #contacts }
format.json { render json: #contacts }
format.xml { render xml: #contacts.to_xml }
end
end
def paginate
#contacts = Contact.paginate(page: params[:page]).search(params[:search])
respond_to do |format|
format.html
end
end

Strongly prefer a separate method because this creates inconstancies and makes the piece less testable. Also you would, in for example documentation, need to create exceptions.
Another way is to handle this with some parameter. Now it suddenly (when you only change views) returns different data. That might look like an error for an unknown developer and might raise issues.
So don't do it magically, clear parameter or separate method.

Related

Carrierwave Rails 4 param is missing or the value is empty: image validates_presence model

I'm trying to figure out uploading pictures, followed a tutorial on how to do so, and now I am augmenting it for my future needs.
My issue, that I am trying to create a model where the only thing you do is upload a picture, but if you hit save and the picture isn't present, then you stay where you are and are given an error warning.
The error message I am getting is this:
ActionController::ParameterMissing in ImagesController#create
param is missing or the value is empty: image
Extracted source (around line #72):
70
71
72
73
74
# Never trust parameters from the scary internet, only allow the white list through.
def image_params
params.require(:image).permit(:image, :remove_image)
end
end
So I acknowledge that I did a somewhat confusing thing here, naming one of the columns the same thing as my model, so here is my code:
image.rb i.e. Image Model:
class Image < ActiveRecord::Base
mount_uploader :image, ImageUploader
validates_presence_of :image
validate :image_size_validation
validates :image, presence: true
private
def image_size_validation
errors[:image] << "should be less than 500KB" if image.size > 0.5.megabytes
end
end
Image Controller, just the create method:
def create
#image = Image.new(image_params)
respond_to do |format|
if #image.save
format.html { redirect_to #image, notice: 'Image was successfully created.' }
format.json { render :show, status: :created, location: #image }
else
format.html { render :new }
format.json { render json: #image.errors, status: :unprocessable_entity }
end
end
end
I assumed the validates :image, presence: true would fix my issue, but here I am asking for help. This is my first time trying to upload pictures/files, so whatever help you are able to give me is appreciated.
Thanks
I've had a similar issue. Changing the column name to something different than the table name fixed this for me. Don't for get to change it in the strong params and where you mount the uploader. If that doesn't work, you should share the code for your form.

Update multiple files upload with CarrierWave

I have implemented the "multiple file uploads" in my model just like explained in the documentation of CarrierWave and it's working just fine. My problem is that I can't get the model update working. When I try to add new files it removes the old ones. I'd like to keep both. Here is part of my model and controller:
class Album < ActiveRecord::Base
mount_uploaders :photos, PhotosUploader
end
class AlbumController < ApplicationController
def create
#album = Album.new(album_params)
if #album.save
flash[:success] = 'Album created'
redirect_to #album
else
render 'new'
end
end
def update
#album = Album.find(params[:id])
if #album.update_attributes(album_params)
flash[:success] = 'Album created'
redirect_to #album
else
render 'edit'
end
end
private
def album_params
params.require(:album).permit({ photos: [] })
end
end
I thought about putting the photos in a different model but if I could make it work this way would be better. Any suggestions?
I have the below in my update method to ensure existing images (avatars) uploaded by CarrierWave remain in tact. I have a separate method that allows users to individually delete images.
def update
project_params_holder = project_params
project_params_holder[:avatars] += #project.avatars if project_params_holder[:avatars]
respond_to do |format|
if #project.update(project_params_holder)
format.html { redirect_to #project, notice: 'Project was successfully updated.' }
format.json { render :show, status: :ok, location: #project }
else
format.html { render :edit }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end

Rails: Submitting an array of child elements

I'm trying to submit a form which is supposed to have an array of child elements. I'm not sure if I have it correctly. Can somebody help me refactor?
I have a couple of models user and item. A userhas_many :items.
The form that sends the information for user and items look like the following -
<%= form_for(#user) do |f| %>
<% f.text_field :name %>
<% f.fields_for :items do |item| %>
<% item.text_field :name %>
<% item.text_field :price %>
<% end %>
<% end %>
I have the following in my controller -
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
#items = #user.items.build(item_params)
if #items.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
end
format.html { redirect_to #user, notice: 'User was successfully created. But there was a problem saving the items.' }
else
format.html { render action: 'new' }
format.json { render json: #userd.errors, status: :unprocessable_entity }
end
end
end
private
def user_params
params.require(:user).permit(:name)
end
def item_params
params.require(:user).require(:item).permit(:name, :price)
end
When I save the user, only 1 record of items get saved, meaning - the data isn't being passed as an array of objects. How do I get this to work?
It looks like right now you are only ever telling Rails to build one item object. Your form is passing up the two parameters for an item, and in your controller you call build once, so #items is only ever set equal to the single Item returned by build. Unless their are hidden parts of your form you aren't showing, it looks like you're only setting one set of options for a user's items. If your goal is to have an array of many items with identical parameters, the fastest fix would be to just do this within the logic of your create action. There are many ways you could implement that (here is one simple way):
#items = []
x.times { #items << #user.items.build(item_params) }
If you're looking to send a request from the form with multiple unique items, you'll have to add more fields to your form, since currently you are only sending one set of parameters.
There are few corrections to be made in your code.
In your users_controller
def new
#user = User.new
3.times do #this will generate three records of items
#user.items.build
end
end
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
else
format.html { render action: 'new' }
format.json { render json: #userd.errors, status: :unprocessable_entity }
end
end
end
private
def user_params
params.require(:user).permit(:name,items_attributes: [:name,price])
end

Ruby render partial on form submit on same page

I am trying to render a partial that I made on top of the current page after a form submit. This should happen in the controller's create method, but I can't seem to figure out if this can be done in Ruby, or if I should just render it using Javascript.
Here is what I have tried so far:
Created a partial in the same folder as the new.html.erb (called _lightbox.html.erb)
The controller render changed to this:
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
BackgroundJob.perform_async(#user.id)
format.html { render :partial=>"lightbox", :layout=>false}
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
I have read up on render, however using the :partial key it simply renders the partial on a new page. I should probably just change the form to use :remote and add the lightbox-esque content with an ajax success, however I was curious as to if this can be done with Ruby on Rails with its rendering functionality.
The code you've displayed here isn't really the problem. It's all in the view.
You need to prevent the default action from form submission, which is to post to the form URL. If the browser posts to that URL, it will render the response. Once you've prevented the default action, you'll then need to submit the form yourself using javascript and set up a callback to deal with the response. That callback should put the html in the place you want it in the page. If any parts of this are unclear, I can expand upon them.

rails insert ajax via jquery

Good day!
I'm trying to implement ajax in my rails test app.
my controller code app/controllers/admin/data
class Admin::DataController < ApplicationController
...
def ajax
if params[:ajax] == 'list'
#responce = Admin::Datum.all
else
#responce ={error: true}
end
respond_to do |format|
# format.html { redirect_to #user }
# format.js
format.json { render json: #responce }
end
end
end
index.js.erb
alert('1');
$.post('/admin/data/ajax',{ajax:'list'},function(responce){
alert('2');
console.log(responce);
}
);
could you help me in determining the url that i've to use in ajax to access ajax method?
or any other help is very welcome!
Update 1
Updated initial code to represent more complex problem
I added to routes.rb
match 'admin/data/ajax' => 'Admin::Data#ajax'
could be any url, it's what you write in your jquery.
And it works!

Resources