Tire and Elastic Search - Object Associations - ruby-on-rails-3

I'm having a little difficulty with the Tire and Elastic Search functionality.
I have a Listing that has a Property. I'm trying to get a basic search form working so that I can create a query from the Property.
# listings/index.html.erb
<%= form_tag searches_listings_path, method: :get do %>
<p>
<%= text_field_tag :query, params[:query] %>
<%= text_field_tag :property_postcode, params[:property_postcode] %>
<%= submit_tag "Search", name: nil %>
</p>
<% end %>
At the moment, whenever I try filtering down the search results, it seems like the property_postcode is being ignored and all results are being returned.
# Listing.rb
include Tire::Model::Search
include Tire::Model::Callbacks
mapping do
indexes :id, type: 'integer'
indexes :title, boost: 10
indexes :description, analyzer: 'snowball'
indexes :posted_at, type: 'date'
indexes :property do
indexes :postcode, :type => 'string'
end
end
def self.search(params)
tire.search(page: params[:page], per_page: 5, load: true) do
query do
boolean do
must { string params[:query], default_operator: "AND" } if params[:query].present?
must { term "property.postcode", params[:property_postcode] } if params[:property_postcode].present?
end
end
end
end
def to_indexed_json
to_json(:include => {
:property => {
:only => [:postcode]
}
})
end
And finally for the property
#Property.rb
class Property < ActiveRecord::Base
belongs_to :listing, touch: true
after_touch() { tire.update_index }
end
Then finally
rake environment tire:import CLASS=Listing FORCE=true
Thanks in advance,
Ryan

Property.search(page: params[:page], per_page: 5, load: true) do
query { string params[:query], default_operator => "AND" } if params[:query].present?
filter :term, "property.postcode" => params[:property_postcode] if params[:property_postcode].present?
end
be sure to turn on routing in your mapping too
mapping :_routing => { :required => true, :path => property.postcode } do

Related

Rails 3 - how to assign the value to nested attributes before calling save in update action

Models associations are
document.rb
has_many :sections
accepts_nested_attributes_for :sections, :allow_destroy => :true, :reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } }
section.rb
belongs_to :document
has_many :paragraphs, :dependent => :destroy
has_many :contents :through => :paragraphs
validates :user_id, :presence => { :message => "Must be filled" }
paragraph.rb
attr_accessible :user_id, :section_id, :content_id
belongs_to :section
belongs_to :content
validates :user_id, :section, :content, :presence => { :message => "Must be filled" }
paragraphs table just like a intermediate table for sections and contents and I want to save records in documents, sections and paragraphs table using single submission.
So I designed form as like
_form.html.erb
<%= form_for #document, :validate => true do |f| %>
<%= f.error_messages %>
<%= f.text_field :name %>
<% f.fields_for :sections do |builder| %>
<%= builder.text_field :name %>
<%= builder.select :content_ids .... {:multiple => true} %>
<% end %>
<% end %>
example parameters when submiting the form
{"document"=>{"name"=>"sdf", "sections_attributes"=>{"0"=>{"name"=>"sdf", "description"=>"sdf", "_destroy"=>"0", "content_ids" => ["1", "2"]}}, "commit"=>"Update Document", "id"=>"3"}
In additionally, I am updating current_user's id to user_id column of paragraphs table.
update
#document = Document.find(params[:id])
#document.attributes = params[:document]
#document.sections.each {|section|
section.user_id = current_user.id
section.paragraphs.each {|paragraph| paragraph.user_id = current_user.id}
}
if #document.save!
# success
else
render :action => 'edit'
end
I got "Validation failed: User Must be filled".
Is validation triggered when assigning attributes using object.attributes= as above
How to assign the value to user_id in paragraph object before calling save method
Might help.
<%= f.hidden_field :user_id, value: current_user.id %>

How to write routes with model inherit

I have a model in app/models/post.rb
class Post < ActiveRecord::Base
end
And I have another model in app/models/post/note.rb
class Post::Note < Post
mount_uploader :file, FileUploader
end
In my controller :
def new
#note = Post::Note.new
end
My view form is :
<%= simple_form_for #post, :validate => true, :html => {:class => 'form-horizontal'} do |form| %>
<%= form.input :title, :validate => {:presence => true} %>
<%= form.button :submit %>
<% end %>
The error is undefined methodpost_notes_path' for #<#:0x007fe3d3fe2b08>`
I want to know how to write the correct route config ?
You can specify the url as an option to simple_form, to override the default path it uses. So if your Post::Note model has a path helper note_path, then this should work:
<%= simple_form_for #post, :url => note_path, :validate => true, :html => {:class => 'form-horizontal'} do |form| %>
<%= form.input :title, :validate => {:presence => true} %>
<%= form.button :submit %>
<% end %>
Ref: How do you handle single table inheritance in SimpleForm so a single helper handles all models?

How to display only the value in edit page in Active Admin

I have a edit form in Active Admin. I need some field as read only.
My current edit page is like
I need the page look like this
How can this be done. My code for the edit form page is like
form :html => { :enctype => "multipart/form-data" } do |f|
f.inputs "Users" do
f.input :device, :label => 'Device', :as => :select, :collection => DEVICE, :include_blank => false
f.input :current_address, :label => 'Current Address', :as => :string
end
end
Please help.
As Alex said, set to disabled. You could then use css to get the visual you wanted, if you can live with the semantics of that.
The syntax was slightly different for me to get this to work.
in your admin form:
f.input :finish_position, input_html: { disabled: true }
in your CSS active_admin.css
input[disabled="disabled"],
input[disabled] {
background-color: #F4F4F4;
border: 0px solid #F4F4F4 !important;
}
For a cleaner form definition within your ActiveAdmin.register{} block you may as well want to define a "readonly" input type to be used within active admin using formtastic:
Form block syntax is for activeadmin version 1.0.0.pre at 0becbef0918a.
# app/admin/inputs/readonly_input.rb
class ReadonlyInput < Formtastic::Inputs::StringInput
def to_html
input_wrapping do
label_html <<
template.content_tag('div', #object.send(method))
end
end
end
# app/admin/your_model.rb
ActiveAdmin.register YourModel do
# ...
form do |f|
# ...
input :current_address, as: :readonly
# ...
end
end
I was facing the same issue and tried using :disabled but it did not solve my problem as I wanted field value to be included in params object while sending it to the server. When you mark a form input as :input_html => {:disabled => true} , it does not include this field value in params.
So, instead I used :input_html => {:readonly => true} which solved both of my problems:
Does not allow user to edit
Includes the value in params
I hope this will help.
How about this?
form :html => { :enctype => "multipart/form-data" } do |f|
f.inputs "Users" do
f.input :device, :label => 'Device', :as => :select, :collection => DEVICE, :include_blank => false
f.li do
f.label :current_address
f.span f.object.current_address
end
end
end
Try to add , :disabled => true for address input field.
The trick is to use "object". Here is how you should code it:
form :html => { :enctype => "multipart/form-data" } do |f|
f.inputs "Users" do
f.input :device, :label => 'Device', :as => :select, :collection => DEVICE, :include_blank => false
f.label :current_address, f.object.current_address
end
end

Rails Form In General Layout

I'm know this is a newbie question just not sure what I'm missing and decided to post hear after my usual search through Google. I'm trying to post content to the database from a form in the footer of the application (for a newsletter) the view is therefore repeated throughout the application. Right now when I submit the form a new object is created in the database but all the fields are "NULL". It seems I need to put the #newsletter variable somewhere, I'm just not sure where.
Partial I'm Rendering in the View
<%= form_tag({:controller => "newsletters", :action => "create"}, :method => "post", :id => "footer_email_form") do %>
<%= text_field_tag :first_name, '', id: "footer_email_firstname" %>
<%= text_field_tag :last_name, '', id: 'footer_email_lastname' %>
<%= text_field_tag :email, '', id: 'footer_email_address' %>
<%= submit_tag "Submit", :name => nil, id: 'footer_email_submit', class: "btn btn-primary" %>
<% end %>
Controller (Create Action)
class NewslettersController < ApplicationController
def create
#newsletter = Newsletter.new(params[:newsletter])
if #newsletter.save
format.html { redirect_to 'pages#home', notice: 'Thank You for signing up for our newsletter' }
format.json { render json: #newsletter, status: :created, location: #newsletter }
else
format.json { render json: #newsletter.errors, status: :unprocessable_entity }
end
end
end
Routes
resources :newsletters, :only => [:create, :destroy]
Use something like this:
<%= form_for Newsletter.new do |f| %>
<%= f.text_field :first_name %>
<%= f.text_field :last_name %>
<%= f.text_field :email %>
<%= f.submit_tag "Submit", class: "btn btn-primary" %>
<% end %>
The way your original form works the params are submitted like this:
params = {
:first_name => 'A',
:last_name => 'B',
:email => 'C',
# and so on...
}
Now if you do #newsletter = Newsletter.new(params[:newsletter]) nothing will happen, because params[:newsletter] is nil and therefore all your attributes are going to be nil (and show up as NULL in the DB).
You should always have an eye on the development log. It's going to help you debug such errors.

Submitting AJAX form for a nested child with another nested child (AssociationTypeMismatch)

My models
I'm trying to create a form for an Annotation. This annotation belongs to a Map, and each annotation should have one Boundary. A map can have many annotations.
I first created the association by letting both Annotation and Map has_one Boundary, but later I switched to using a polymorphic boundary_object. The error was the same regardless.
has_one :boundary, :as => :boundary_object # <= Map
has_one :boundary, :as => :boundary_object # <= Annotation
belongs_to :boundary_object, :polymorphic => true # <= Boundary
Views and Controller
Here's the thing: First I used Boundary.new to create a new boundary object here, since I didn't have a pre-set annotation object, since the form can be submitted multiple times.
maps/show.html.erb
<%= form_for([#map, Annotation.new], :remote => true ) do |f| %>
<%= f.text_area :body, :cols => 80, :rows => 10, :style => "width: 500px" %>
<%= f.fields_for Boundary.new do |b| %>
<%= b.text_field :ne_x, :style => "display:none" %>
<%= b.text_field :ne_y, :style => "display:none" %>
<%= b.text_field :sw_x, :style => "display:none" %>
<%= b.text_field :sw_y, :style => "display:none" %>
<% end %>
<% end %>
I could use f.fields_for :boundary too, if I have this in the maps_controller.rb:
#annotation = #map.annotations.build
#annotation.boundary = Boundary.new
But the result is still the same.
annotations_controller.rb
def create
#annotation = Annotation.new(params[:annotation])
respond_to do |format|
if #annotation.save
format.js { }
end
end
The Error
When submitting that form, this results in the following error at the first line in the create method.
ActiveRecord::AssociationTypeMismatch (Boundary(#2158793660) expected, got ActiveSupport::HashWithIndifferentAccess(#2165684420))
Obviously, the form works without the whole boundary thing. These are the parameters submitted:
{
"utf8"=>"✓",
"authenticity_token"=>"6GDF6aDc6GMR3CMP+QzWKZW9IV9gSxfdkxipfg39q7U=",
"annotation"=>
{
"body"=>"foo bar",
"boundary"=>
{
"ne_x"=>"11312",
"ne_y"=>"5919",
"sw_x"=>"6176",
"sw_y"=>"1871"
}
},
"map_id"=>"1"
}
What do I have to do to be able to create the Boundary object for this annotation right away?
According to your associations:
First, you need to build a new boundary object (see here for more info):
def show
#map = ...
#annotation = #map.annotations.build
#boundary = #annotation.build_boundary # build new boundary
end
Second, you need to edit your view:
<%= form_for([#map, #annotation], :remote => true ) do |f| %>
<%= f.text_area :body, :cols => 80, :rows => 10, :style => "width: 500px" %>
<%= f.fields_for :boundary do |b| %>
...
<% end %>
<% end %>
Third, check that you have accepts_nested_attributes_for for your Boundary in the Annotation model.
accepts_nested_attributes_for :boundary
The form will then look like this – note that the name of the association needs _attributes:
<input … name="annotation[boundary_attributes][ne_x]" … />