Why the mass assignment code does not work - ruby-on-rails

There is a mass assignment defined in sys_log model in our rails 3.1.4 app:
attr_accessible :log_date, :user_name, :user_id, :user_ip, :action_logged, :as => :new_log
A method is defined in application_controller to save the log:
def sys_logger(action_logged)
log = SysLog.new(:log_date => Time.now, :user_id => session[:user_id], :user_name => session[:user_name], :user_ip => session[:user_ip],
:action_logged => action_logged, :as => :new_log)
log.save
end
However, the mass assignment does not work. Here is the warning message:
WARNING: Can't mass-assign protected attributes: log_date, user_id, user_name,
user_ip, action_logged, as
:new_log is not working as defined. What's wrong with the code above? Thanks so much.

The :as => :new_log is now part of the hash of attributes, instead of a separate option you pass in.
Adding some curly braces should help:
def sys_logger(action_logged)
log = SysLog.new({:log_date => Time.now, :user_id => session[:user_id],
:user_name => session[:user_name], :user_ip => session[:user_ip],
:action_logged => action_logged }, :as => :new_log)
log.save
end
Or assigning it temporarily:
def sys_logger(action_logged)
attrs = { :log_date => Time.now, :user_id => session[:user_id],
:user_name => session[:user_name], :user_ip => session[:user_ip],
:action_logged => action_logged }
log = SysLog.new(attrs, :as => :new_log)
log.save
end

Related

Rails thinking sphinx includes not working

I have the code like following
Listing.search(
Riddle::Query.escape(params[:search]),
:include => params[:include],
:page => page,
:per_page => per_page,
:star => true,
:with => with,
:with_all => with_all,
:order => params[:sort]
)
params[:include] contains the value like [:listing_images, :author, :category, :origin_loc]
I don’t know what was wrong here.

Rails 4 render json nested objects

I need to render as Json a complex structure. I have next structure working:
render :json => #booking, :include => [:paypal,
:boat_people,
:boat => {:only => :boat_model, :include => {:boat_model => {:only => :name, :include => { :boat_type => {:only => :name}}}}}]
but I´m not able to add a port attribute with some other nested attributes to :boat, such as :boat_model (at same level).
UPDATE:
Although it´s not working, I include my port attribute.
render :json => #booking, :include => [:paypal,
:boat_people,
:boat => {:only => [:boat_model => {:include => {:boat_model => {:only => :name, :include => { :boat_type => {:only => :name}}}}},
:port => {:include => :city => {:only => name}}]}]
I mean, boat_model and port are both boat attributes.
This is the model object:
class Boat < ActiveRecord::Base
attr_accessor :price
#price
attr_accessor :extrasPrice
#extrasPrice
def as_json(options = { })
h = super(options)
h[:price] = #price
h[:extrasPrice] = #extrasPrice
h
end
belongs_to :boat_model
belongs_to :port
belongs_to :state
has_many :photos
end
I got it.
render :json => #booking, :include => [:paypal,
:boat_people,
:boat => {:only => :name, :include => {:port => {:only => :name, :include => {:city => {:only => :name, :include => {:country => {:only => :name}}}}},
:boat_model => {:only => :name, :include => {:boat_type => {:only => :name}}}}}]
You are probably going to want a much more robust system for displaying JSON. The built-in Rails helpers are really designed primarily for simple additions that enable users to do most of what they would want to accomplish. However, in your case, you are trying to make it do more than it was designed for.
I would highly recommend either creating a view object or using a gem like RABL.
My preference is to use Rabl for complex JSON. It basically creates the 'view object' for you by building a domain specific language that makes it relatively easy to build complex JSON objects in rails.
RABL basically allows you to build views that format JSON instead of HTML. The DSL is extremely rich and enables you to do just about anything you would want. In your case, I think the code would look something like this:
app/views/bookings/show.rabl
object #booking
#these are attributes that exist on your booking model:
attributes :booking_attribute, :other_booking_attribute
child :paypal do
#these are attributes that exist on your paypal model:
attributes :paypay_attribute1, :other_paypal_attribute
end
child :boat_people do
#boat_people attributes that you want to include
attributes :blah_blah
end
child :boat do
#boat attributes that you want to include
attributes :boat_attribute1, :boat_attribute2
child :boat_model do
attributes :name
child :boat_type do
attributes :name
end
end
end

Insert record in assosiated model through console

I have 2 tables User and Member and there relation is
In user
has_one :member, :class_name => 'User::Member'
Member
belongs_to :user
I am trying to insert data using console and I am using this code
u = User.create(
:group => UserGroup.find_by_slug(:members),
:first_name => 'abc',
:last_name => 'fgh',
:company_name => 'xyz',
:email => 'test#test.com',
:password => '123456',
:password_confirmation => '123456'
)
m = User::Member.create(
:user => u,
:pricing_plan => PricingPlan.order('RANDOM()').first,
:state => UserState.order('RANDOM()').first,
:industry => Industry.order('RANDOM()').first,
:fy_start_month => 7
)
It is throwing this error
syntax error, unexpected tIDENTIFIER, expecting $end
) m = User::Member.create(
I am wondering what is wrong with my syntax.Thanks in advance
This may be due to an invisible char (not whitespace). Your syntax seems to be ok, but if your editor allows you to show invisibles (in textmate, for example, go to view > show invisibles, try to do that. It sometimes happens to me that I insert invisibles instead of whitespace.
To give you an impression what I am talking about:
This is invisibles hidden
This is invisibles shown. The invisible lozenges you do not see in normal mode cause a syntax error:
I am assuming user_id is your foreign key which is associated with the users table.
If so use following
m= Member.create(
:user_id => u.id,
:pricing_plan => PricingPlan.order('RANDOM()').first,
:state => UserState.order('RANDOM()').first,
:industry => Industry.order('RANDOM()').first,
:fy_start_month => 7
)
try this
In your User Model
has_one :member
attr_accessible :member_attributes
accepts_nested_attributes_for :member
In your Member Model
belongs_to :user
then try in your console as well as your form
user = User.create(
:group => UserGroup.find_by_slug(:members),
:first_name => 'abc',
:last_name => 'fgh',
:company_name => 'xyz',
:email => 'test#test.com',
:password => '123456',
:password_confirmation => '123456'
)
and
user.build_member(
:pricing_plan => PricingPlan.order('RANDOM()').first,
:state => UserState.order('RANDOM()').first,
:industry => Industry.order('RANDOM()').first,
:fy_start_month => 7
)
or
member = Member.create(
:user_id => user.id,
:pricing_plan => PricingPlan.order('RANDOM()').first,
:state => UserState.order('RANDOM()').first,
:industry => Industry.order('RANDOM()').first,
:fy_start_month => 7
)

Adding conditions in rails include

going directly to my problem.
render :json => projects.to_json(:only => ['name', 'id'],:include => {:client => {:only => ['name']}, :deliverables => {:only => ['name', 'id'], :include => {:tasks => {:only => ['name','id']} } } })
This is how my controller responds for json request. Now my problem is that it lists all the deliverables & tasks that are in given project but here I want to respond with tasks & deliverables that meets certain condition like all that are created in specific month.
Thanks is advance.
Here's what I did, in project model
has_many :uncompleted_deliverables,
:class_name => 'Deliverable',
:conditions => 'completed = false'
The same applies to deliverable model
has_many :uncompleted_tsks, :class_name => 'Task', :conditions => 'completed = false'
And then responded json in following way,
format.json { render :json => projects.to_json(:only => ['name', 'id'],
:include => {:client => {:only => ['name']}, :uncompleted_deliverables => {:only => ['name', 'id'], :include => {:uncompleted_tsks => {:only => ['name','id']} } } }) }
Anyway thanks guys for your response..
Could you just include a proc? (see end of documentation here)
I guess the code could look something like that:
in you Project model:
def to_json(options={})
tasks_json = Proc.new { |options|
options[:builder].tasks do
selected_tasks = tasks.select {|t| t.created_at > 30.days.ago } # or whatever your condition is
selected_tasks.each do |t|
options[:builder].task do
options[:builder].tag!('id', t.id)
options[:builder].tag!('name', t.name)
end
end
end }
options.merge!(:procs => [tasks_json])
end
Would that work for you?

group_by using value from other model

Using ROR 2.3.8
I have this in cities_controller.rb:
#shops = Shop.published.search params[:keyword], {
:conditions => conditions,
:star => true,
:group_by => 'city_id',
:group_function => :attr,
:page => params[:page]
}.merge(:order => 'rating_average DESC')
#cities = #shops.collect { |shop| shopy.city }
How can I tell Rails to get the rating_average from City model instead of Shop model? Because the Shop model does not have rating_average. It's actually City model that gets rated.
Thank you.
UPDATES
published namescope in Shop.rb
sphinx_scope(:published) {
{:conditions => {:status => 'published'}}
}
Indexes in Shop.rb
define_index do
indexes city.name, :as => :name, :sortable => true
indexes city.duration, :as => :duration
indexes city.status, :as => :status
#has city.budget, :as => :budget
#has city(:created_at), :as => :created_at
has city(:rating_average), :as => :rating_average
has city_id
end
UPDATES 2
class City < ActiveRecord::Base
has_many :shops, :dependent => :destroy
...
end
You should use joins to acheive this:
#shops = Shop.published.search params[:keyword], {
:conditions => conditions,
:star => true,
:group_by => :city_id,
:group_function => :attr,
:page => params[:page]
}.merge(:order => :rating_average,
:sort_mode => :desc)
You should also add cities. or shops. before columns to specify which table's column.

Resources