Rails 3 - routing and parameterized name - ruby-on-rails-3

I use this rule in my model:
def to_param
"#{self.name.parameterize}"
end
and in my helper:
def articles_menu
menu = '<ul>'
Article.all.each do |article|
menu += '<li>'
menu += link_to "#{article.name}", article
menu += '</li>'
end
menu += '</ul>'
return menu.html_safe
end
but when I'll go to the /articles/my-new-flat, I'll get the error
ActiveRecord::RecordNotFound in ArticlesController#show
Couldn't find Article with id=my-new-flat
Missing I something else yet or is any problem in my app? I though for parameterizing of the name is needed only set up in the model the rule...

Use FriendlyId gem it has all what you need, here is the link https://github.com/norman/friendly_id/blob/master/README.md
Problem with your code is that rails under the hub is trying to query your model by "id" attribute, it is not querying "name" attribute. FriendlyId gem patches this for models you want

Related

sunspot surely this can be done with some ruby magic?

I need to access my rails model instance from inside the searchable block as indicated below.
class Product
include MongoMapper::Document
include Sunspot::Rails::Searchable
key :field_names, Array
searchable do |ss|
self.field_names.each do |field|
ss.double field[:name] do
field[:value]
end
end
end
end
does anyone know how to do this via Sunspot ?
I have a field_names array on each product instance that is different per product so i need to access it.
Thanks a lot
Rick
you mean this?
def Foo
attr_accessible :id, :title
def fields
['something']
end
searchable do
integer :id
string :title
string :fields, :multiple => true do
self.fields
end
end
end
well inside there, you're inside a different evaluation context (Solr::DSL or something like that). That's to provide the ability to have those keywords like "integer, string". Looks like you're trying to evaluate dynamic attributes/filters .. .. so see my modified response (below)
you mean this?
def Foo
attr_accessible :id, :title
#fields_to_dynamically_add = ['title']
searchable do |s|
s.integer :id
s.string :title
#fields_to_dynamically_add.each do |f|
s.string f.to_sym
end
end
end
PS: have not added fields to searchable blocks dynamically every myself (although the above works)

Process form data before creating table entry

Backstory: I'm building a site that takes in a Soundcloud URL as part of a post. Currently, I store the link they provide and, when a user loads their feed view, I retrieve the associated image / title / favorite count etc. via my post_helper. I have quickly come to realize that this is not scalable and is hurting load times.
So, what I think I should do (feel free to tell me that there is a better way), is to retrieve the SC/YT metadata on form submit and store it along with the other post data (id, user, content etc.) in the posts' table entry. How would I go about calling the helper methods to retrieve such on form submit and include the metadata in the submitted params?
post_helper.rb excerpt:
def soundcloud_info(soundcloud_url, type)
begin
resolve = scClient.get('/resolve', :url => soundcloud_url)
track_info = scClient.get("/tracks/#{resolve.id}")
rescue Soundcloud::ResponseError => e
%Q{ Error: #{e.message}, Status Code: #{e.response.code} }
end
if type == "title"
%Q{#{track_info['title']}}
elsif type == "image"
%Q{#{track_info['artwork_url']}}
elsif type == "favCount"
%Q{Favorite count: #{track_info['favoritings_count']}}
end
end
post_controler.rb excerpt:
def create
#post = current_user.posts.build(params[:post])
if #post.save
flash[:success] = "Your post was successful!"
redirect_to root_url
else
#feed_items = current_user.feed.paginate(page: params[:page])
render 'static_pages/home'
end
end
So apparently it's pretty straight forward... all I need to do is modify the parameters in the controller before I call #post = current_user.posts.build(params[:post]). My issue was that I was trying to do so in the helper.
I haven't quite adapted the whole thing to get all my required fields, but here's an example of how I have adapted the create method to pull the api URL out if someone submits SoundCloud's embed iframe.
micropost_controller.rb excerpt:
def create
#url = params[:post][:link_html]
if #url[/^.*src="(https|http):\/\/w.soundcloud.com\/player\/\?url=(.*)">/]
params[:post][:link_html] = CGI::unescape($2)
end
#post = current_user.posts.build(params[:post])
if #post.save
flash[:success] = "Your post was successful!"
redirect_to root_url
else
#feed_items = current_user.feed.paginate(page: params[:page])
render 'static_pages/home'
end
end

How can I troubleshoot this JSON method in DataTables gem?

I'm trying to implement the Railscast 340 that demos how to use DataTables, which looks like an awesome gem for my project.
My model is different, of course; but the datatables class the Mr Bates builds (very quickly), in order to do server-side processing, is rather complicated to follow. I got the source code, and basically attempted to follow along. My view comes up with zero records (but there are > 10,000 records), but does not break.
However, here is what the error message output from the rails server says just before it stops:
NameError (undefined local variable or method `genotypes' for #<GenotypesDatatable:0xa9e852c>):
app/datatables/genotypes_datatable.rb:12:in `as_json'
app/controllers/genotypes_controller.rb:8:in `block (2 levels) in index'
app/controllers/genotypes_controller.rb:6:in `index'
Just before this, there appears to be this JSON error, which starts:
Started GET "/genotypes.json?sEcho=1&iColumns=8&sColumns=&iDisplayStart=0&iDisplayLength=10&mDataProp_0=...
The relevant part of the genotypes controller looks like this:
def index
respond_to do |format|
format.html
format.json { render json: GenotypesDatatable.new(view_context) }
end
end
And my genotypes model looks like:
class Genotype < ActiveRecord::Base
attr_accessible :allele1, :allele2, :run_date
belongs_to :gmarkers
belongs_to :gsamples
end
My datatables class is given below. This is from Mr Bates code, modified (most likely incorrectly) to replace his Products model with my Genotypes model:
class GenotypesDatatable
delegate :params, :h, :link_to, to: :#view
def initialize(view)
#view = view
end
def as_json(options = {})
{
sEcho: params[:sEcho].to_i,
iTotalRecords: Genotype.count,
iTotalDisplayRecords: genotypes.total_entries,
aaData: data
}
end
private
def data
genotypes.map do |genotype|
[
link_to(genotype.name, genotype),
h(genotype.category),
h(genotype.released_on.strftime("%B %e, %Y")),
genotype.run_date
]
end
end
def Genotypes
#Genotypes ||= fetch_Genotypes
end
def fetch_genotypes
genotypes = Genotype.order("#{sort_column} #{sort_direction}")
genotypes = genotypes.page(page).per_page(per_page)
if params[:sSearch].present?
genotypes = genotypes.where("name like :search or category like :search", search: "%#{params[:sSearch]}%")
end
genotypes
end
def page
params[:iDisplayStart].to_i/per_page + 1
end
def per_page
params[:iDisplayLength].to_i > 0 ? params[:iDisplayLength].to_i : 10
end
def sort_column
columns = %w[gmarker gsample allele1 allele2 run_date]
columns[params[:iSortCol_0].to_i]
end
def sort_direction
params[:sSortDir_0] == "desc" ? "desc" : "asc"
end
end
Any hints on how to troubleshoot (or fix!) this error much appreciated! (Getting this working for my project would be awesome!)
TIA,
rixter
I'm not sure if this is it, but your class has a Genotype method with capital G, it should be all lowercase.

rails OR query based on multiple checkbox selections

This seems like it should be a common problem but I'm having trouble finding an answer. Basically I want to have a form with 10 or so checkboxes which I'm creating with check_box_tag. When the form is submitted I want to generate a query that return all records that match ANY of the checked selections. So, the number of checked selections will vary.
So, for example, if I have
class Book < ActiveRecord::Base
belongs_to :author
end
I want to generate something like
Book.where("author_id = ? or author_id = ?", params[authors[0]], params[authors[1]]) if there are two boxes checked, etc.
Thanks for any insight.
Will this work for you?
Book.where(author_id: [array_of_author_ids])
You need to collect author_ids from params first
I recently had to do something similar, this is how I achieved this. It's pretty clever (at least I think so. :))
I created a query model that serializes the query column (text field) in JSON. I use a form to get the query data from the user with selection fields.
class BookQuery < ActiveRecord::Base
has_many :books
# loop through each foreign key of the Book table and create a hash with empty selection
def self.empty_query
q = {}
Book.column_names.each do |column_name|
next unless column_name.ends_with?("_id")
q.merge column_name => []
end
end
end
I'm using Author as an example below:
<%= form_for #book_query do |f| %>
<% for author in Author.all %>
<%= check_box_tag "book_query[query][author_ids][]", author.id, false%>
<%= author.name %>
<% end %>
<%= f.submit "Save Query" %>
<% end %>
When this form is submitted you ended up with parameters like this:
When the form is submitted it generates this parameter:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"XXXXXXXXXXX", "book_query"=>{"query"=>{"author_ids"=>["2", "3"]}}, "commit"=>"Save Query"}
Now in the BookQuery controller's create action you can just do what create function always does:
def create
#book_query = BookQuery.build(params[:book_query])
if #book_query.save
flash[:success] = "Book query successfully saved."
redirect_to ...
else
flash[:error] = "Failed to save book query."
render :new
end
end
But by default rails serializes the data in hash type:
1.9.3p194 :015 > pp BookQuery.find(9).query
BookQuery Load (0.7ms) SELECT "book_queries".* FROM "book_queries" WHERE "book_queries"."id" = $1 LIMIT 1 [["id", 9]]
"--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess\nauthor_ids:\n- '2'\n- '3'\n"
=> "--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess\nauthor_ids:\n- '2'\n- '3'\n"
In BookQuery model, add the following:
serialize :query, JSON
But rail would change the IDs to string:
1.9.3p194 :018 > query = JSON.parse(BookQuery.find(10).query)
BookQuery Load (0.5ms) SELECT "book_queries".* FROM "book_queries" WHERE "book_queries"."id" = $1 LIMIT 1 [["id", 10]]
=> {"author_ids"=>["2", "3"]}
1.9.3p194 :019 > query["author_ids"]
=> ["2", "3"]
What I did then is override the attribute accessors in BookQuery model:
The below has to be done because the hash returns strings, not ids in integer.
def query=(query)
query.each_pair do |k, v|
if query[k].first.present?
query[k].map!(&:to_i)
else
query.except!(k)
end
end
write_attribute(:query, query)
end
# just want to avoid getting nil query's
def query
read_attribute(:query) || {}
end
To find book with this query, you can simply add this function to your Book model:
def self.find_by_book_query(book_query, options = {})
options[:conditions] = book_query.query
find(:all, options)
end
Now you get a customizable query string based on the model definition Book and everything works like the Rails way. :)

Rails 3: Sortable Columns

I'm following Railscasts #228 in Rails 3.0.5 and ruby 1.9.2p180.
I have copied code near verbatim from the verbatim with the exception of changing the class name from Product to Player. I'm also skipping the last portion where Ryan adds arrows to denote the sort direction. I'm able to load the correct index page and see all of the desired URL's with the desired parameters (direction and sort), but nothing is actually happening on click. The URL is changing, but the page is not reloading.
Here is my code:
ApplicationHelper
def sortable(column, title = nil)
title ||= column.titleize
direction = (column == params[:sort] && params[:direction] == "asc") ? "desc" : "asc"
link_to title, :sort => column, :direction => direction
end
PlayersController
def index
#players = Player.order(sort_column + ' ' + sort_direction)
end
private
def find_team
session[:team] ||= Team.new
end
def sort_column
Player.column_names.include?(params[:sort]) ? params[:sort] : "name_e"
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
end
Thanks for your help!
Edit: As requested, HTML code. You can see that the link for Position is currently desc, as I am at: http://localhost:3000/players?direction=asc&sort=abb_pos. However, no actual sorting has occurred for this column, or any other column.
<th>Name</th>
<th>Team</th>
<th>Position</th>
<th>Height</th>
<th>Weight</th>
Nathan
I'd suggest doing this first thing:
def index
order = sort_column + ' ' + sort_direction
puts "-- order:'#{order}'"
...
end
Click the links and then look in server's console for that "--" output. Most probably there's a logical flaw somewhere that makes the actual compiled ORDER clause always be the same. Links themselves look perfectly okay. Unless there's a # character in the links somewhere, all clicks should work (i.e. the browser should reload the content).
As for the problem in general, there's a gem called handles_sortable_columns, which gets you sortable columns for no effort at all.
Alex
Found the issue. I had the following code in my player model:
Player.rb
default_scope :order => 'name_e'
As a result, the SQL search generated looked like this:
SELECT `players`.* FROM `players` ORDER BY name_e, avg_points desc