rails3-jquery-autocomplete passing parameter to scope query - ruby-on-rails

I'm struggling to find an answer to a problem I have with the rails3-jquery-autocomplete gem.
I have 2 models. Environment & Property.
class Environment < ActiveRecord::Base
has_many :properties
name: string, envfile: string
class Property < ActiveRecord::Base
scope :with_environment_id, where(:environment_id => 14)
belongs_to :environment
name: string, value: string, environment_id: integer
I have a view which displays all the properties belonging to a particular environment and in that view the following code which auto searches based on the property name
<%= form_tag('tbd')%>
<%= autocomplete_field_tag :property_name, '', autocomplete_property_name_properties_path>
The properties controller
class PropertiesController < ApplicationController
autocomplete :property, :name, :scopes => [:with_environment_id]
and routes.rb has
get :autocomplete_property_name, :on => :collection
The autocomplete works fine but it returns returns all records in properties table. Where I would like only the properties belonging to the environment displayed in the view.
As you can see I've defined a scope in the property model in which I've hardcoded a valid environment_id to make this work as I would want it.
So my question is how do I pass the environment_id from the view/controller back into the scope?
Perhaps I'm tackling this from the wrong angle.
Apologies if it's a dumb question but it has stumped me all day.

def get_autocomplete_items(parameters)
super(parameters).where(:user_id => current_user.id)
end

Related

Uniqueness error in has_many nested attributes

I have a class student with has_many tests. The test class has a student_id, marks, name. Here the test name should be unique. The test is a nested attribute for student. So the parameters are this way:
:student => {:first_name => "abc",
:email => "dfsdf#sfdsdsd.bbb",
:tests_attributes => { "0" => {:name => "bgc", :marks => "470"}}}
I have a problem with update. If I update_attributes with the tests_attributes, it throws a validation error saying the name for test is not unique. I am actually addressing the same record here. How do I overcome this?
Without seeing your models (& validations), it's going to be quite difficult to diagnose your error directly.
--
Nested Attributes
We've done something like this, and found that your nested data is passed to the child model as if it were receiving a new object (without being nested). This means if you've got validates uniqueness for that model, it should be okay:
#app/models/test.rb
Class Test < ActiveRecord::Base
belongs_to :student
validates :name, uniqueness: true
end
Reason I write this is because there's a method called inverse_of, which basically allows you to access the parent model data in your child model
--
Update
I think the problem will likely lie with your use of update_attributes. Problem being you're trying to update both the student and the test attributes at one time.
I'm not sure exactly why this would be a problem, but I'd test this:
#app/controllers/students_controller.rb
class StudentsController < ApplicationController
def update
#student = Student.find params[:id]
#student.test.update(name: params[:test_name], marks: params[:marks])
end
end
I think if you can explain your methodology a little more, it will be much more helpful. I.E are you trying to update student or test? If you're updating student & adding a new test, how are you updating the studet?
Thanks for the reply guys. I ended up finding the answer myself. I did have a uniqueness validation for name.
I had a situation where initially I wouldn't know the student but have only his details. So I would have to create this hash and pass it to update. The trick to not trying to create a new record for the same name in test is to pass the actual record's ID along with it. This solved the problem
Nested Attributes
I think the problem with nested_attributes. For update need to pass nested_attributes with ID.
Ex.
:student => {:first_name => "abc",
:email => "dfsdf#sfdsdsd.bbb",
:tests_attributes => { "0" => {id: 1, :name => "bgc", :marks => "470"}}}
I have tried below-given example it is worked for me:
Update
#app/controllers/students_controller.rb
class StudentsController < ApplicationController
def update
#student = Student.find params[:id]
#student.update_attributes(student_params)
end
private
def student_params
params.require(:student).permit(:first_name, :email,
tests_attributes: [:id, :name, :marks])
end
end

How to pull information from associated model (Rails)

I'm running a search using the Ransack gem.
Controller code (for ItemsController)
#q = Item.search(params[:q])
#search_results = #q.result
After running the search, #search_results contains multiple Items (Item 1, Item 2, Item 3, …). Where each Item is a hash:
Item = { "id" => "12", "name" => "shovel", "user_id" => "2", "type" => "A" }
In this case, for each Item hash, I want to add an additional key-value pair that translates the user_id into the name that is associated with that instance of the User model (i.e., User has_many :Items and Item belongs_to :Users)
I tried in the same controller code section
#search_results.each do |item|
item[:user_name] = User.find_by_id(item.user_id).name
end
But I get an error that I can't write to item. I suspect Ransack has something to do with it though, because if I just print #search_results, instead of getting the actual Item data, I get #<ActiveRecord::Relation::ActiveRecord_Relation_Item:0x000001025e6c78>
Help greatly appreciated!
Btw, in case there's even an easier way, the reason I want to add another key/value pair with the user_name is because the ultimate output is a JSON that is being picked up by another part of the codebase, and we don't want to run two separate database queries.
Firstly, you're receiving a ruby object back, which I take means you can create a set of attributes for in the model. Why don't you try using a getter in your item model to set for you:
#app/models/item.rb
Class Item < ActiveRecord::Base
belongs_to :user #-> needs to be singular
attr_accessor :user_name
def user_name
self.user.name
end
end
This means that instead of having to append a user_name attribute from your controller, every Item object will automatically have the user_name attribute anyway
A refactor of this would also be to use the delegate method inside your Item model:
Class Item < ActiveRecord::Base
belongs_to :user
delegate :name, to: :user, prefix: true #-> allows you to call #item.user_name
end

How to pass a parameter inside a simple_form group_method?

I'm trying to display active projects per party in a drop down list. active_projects is a method within the Party model. The grouped_collection_select code below works however, when I attempt to convert my form into a simple_form, my active_projects method is no longer recognised.
Below are my two code extracts. The first working correctly while the other causes an error.
# rails default
<%= f.grouped_collection_select(:project_id,
Party.all,
:"active_projects(#{date.strftime("%Y%m%d")})",
:party_name,
:id, :project_name) %>
# simple form
<%= f.input :project_id,
collection: Party.all, as: :grouped_select,
group_method: :"active_projects(#{date})" %>
I know this one is a little old but I have a solution to this problem using simple_form. I am not sure if it is the best solution but it does work.
Basically, the issue comes down to passing in a value to the group_method. In my case I had a class that needed to get the current_users company that he/she belongs to. My model/database structure was like this:
Type -> Category
In my case the Type records were global and did not belong to a specific company. However, the category model records did belong to a specific company. The goal is to show a grouped select with global types and then company-specific categories underneath them. Here is what I did:
class Type < ActiveRecord::Base
has_many :categories
attr_accessor :company_id
# Basically returns all the 'type' records but before doing so sets the
# company_id attribute based on the value passed. This is possible because
# simple_form uses the same instance of the parent class to call the
# group_by method on.
def self.all_with_company(company_id)
Type.all.each do |item|
item.company_id = company_id
end
end
# Then for my group_by method I added a where clause that reuses the
# attribute set when I originally grabbed the records from the model.
def categories_for_company
self.categories.where(:company_id => self.company_id)
end
end
So the above is a definition of the type class. For reference here is my definition of the category class.
class Category < ActiveRecord::Base
belongs_to :company
belongs_to :type
end
Then on my simple_form control I did this:
<%= f.association :category, :label => 'Category', :as => :grouped_select, :collection => Type.all_with_company(company_id), :group_method => :categories_for_company, :label_method => :name %>
Basically instead of passing in the value we want to filter on in the :group_method property we pass it in on the :collection property. Even though it will not be used to get the parent collection it is just being stored for later use in the class instance. This way, when we call another method on that class it has the value we need to do our filtering on the child.

Rails 3 - polymorphic_path - How to Create One given a table

i have table AuditLog with fields including: audited_id | audited_type
That results in data like:
108 | Photo
303 | Comment
What I want to do is create a link to the item, so for the example above:
here is the photo
I'm trying to use a polymorphic_path but am getting an error: "undefined method `model_name' for Fixnum:Class"
When using:
<%= link_to 'Here she is', polymorphic_path([audited_id, audited_type]) %>
Ideas? Thanks
Updating with code based on the answer by Luke below:
class NewsFeed < ActiveRecord::Base
default_scope :order => 'news_feeds.created_at DESC'
belongs_to :feeded, :polymorphic => true
end
class Note < ActiveRecord::Base
has_many :newsfeed, :as => :feeded
end
In the partial which is being passed the local storyitem:
<%= link_to 'Here she is', polymorphic_path(storyitem.feeded) %>
The DB migration file, contains the following line for CreateNewsFeeds
t.references :feeded, :polymorphic => true
You should have a method #auditable (or whatever your polymorphic association is called) on AuditLog objects. If you pass the result of that method to polymorphic_path it will return the correct path for you.
Update:
Assuming you have the following associations (or are using acts_as_auditable or something that sets up the relationships for you):
class AuditLog
belongs_to :auditable, :polymorphic => true
end
class AuditedObject
has_many :audits, :as => :auditable
end
You'll be able to call auditable on any instance of AuditLog, and it will return the associated audited object. So you can call
<%= link_to 'Here she is', polymorphic_path(audit_log.auditable) %>
to get a link to the audited object.
So, anywhere that you have a polymorphic association in a class, there is an instance method setup with the name of that association that will return the associated object.
Gosh, I'm hoping that makes sense. Let me know if you need me to clarify it further.
The problem with polymorphic_path it needs an object, so you first need to fetch the object from the database.
Depending on your use case this can be a big performance problem.
In case of a log viewer, where you have a list of for example 100 entries,
and just want to show links to the entires, you will fetch 100 objects, just to get their path.
I had a similar problem, my solution was to hack a method to construct the path from the class name and id:
class AuditLog
...
def audited_path
"/#{self.audited_type.tableize}/#{self.audited_id}"
end
The method will return for example "/photos/302". But of course it will work only for quite simple routings.

Exclude draft articles from Solr index with Sunspot

I have an indexed model called Article and I don't want solr to index unpublished articles.
class Article < ActiveRecord::Base
searchable do
text :title
text :body
end
end
How can I specify that article that is not #published? should not be indexed?
Be sure to index the published status.
class Article < ActiveRecord::Base
searchable do
text :title
text :body
boolean :is_published, :using => :published?
end
end
Then add a filter to your query
Sunspot.search(Article) do |search|
search.with(:is_published, true)
# ...
end
If you want to make sure unpublished articles are never included in the search index, you can do it this way instead:
class Article < ActiveRecord::Base
searchable :if => :published? do
text :title
text :body
end
end
The model will then only be indexed when published.
My approach is less interesting if you also want admins to be able to search for articles, including unpublished ones, however.
Note: calling article.index! will add the instance to the index regardless of the :if => :method param.
A small look into the code base of sunspot_rails reveals a method called maybe_mark_for_auto_indexing which will be added to the models that include solr. You could override that method and set #marked_for_auto_indexing based on your criteria in the specific model. Its monkey patching but can help you solve the problem. The code for ur reference is in lib/sunspot/searchable.rb.

Resources